xref: /petsc/src/ksp/pc/impls/saviennacl/saviennacl.cxx (revision 98921bda46e76d7aaed9e0138c5ff9d0ce93f355)
107598726SKarl Rupp 
207598726SKarl Rupp /*  -------------------------------------------------------------------- */
307598726SKarl Rupp 
407598726SKarl Rupp /*
507598726SKarl Rupp    Include files needed for the ViennaCL Smoothed Aggregation preconditioner:
607598726SKarl Rupp      pcimpl.h - private include file intended for use by all preconditioners
707598726SKarl Rupp */
807598726SKarl Rupp #define PETSC_SKIP_SPINLOCK
999acd6aaSStefano Zampini #define PETSC_SKIP_IMMINTRIN_H_CUDAWORKAROUND 1
1007598726SKarl Rupp #include <petsc/private/pcimpl.h>   /*I "petscpc.h" I*/
1107598726SKarl Rupp #include <../src/mat/impls/aij/seq/aij.h>
1207598726SKarl Rupp #include <../src/vec/vec/impls/dvecimpl.h>
1307598726SKarl Rupp #include <../src/mat/impls/aij/seq/seqviennacl/viennaclmatimpl.h>
1407598726SKarl Rupp #include <../src/vec/vec/impls/seq/seqviennacl/viennaclvecimpl.h>
1507598726SKarl Rupp #include <viennacl/linalg/amg.hpp>
1607598726SKarl Rupp 
1707598726SKarl Rupp /*
1807598726SKarl Rupp    Private context (data structure) for the SAVIENNACL preconditioner.
1907598726SKarl Rupp */
2007598726SKarl Rupp typedef struct {
2107598726SKarl Rupp   viennacl::linalg::amg_precond<viennacl::compressed_matrix<PetscScalar> > *SAVIENNACL;
2207598726SKarl Rupp } PC_SAVIENNACL;
2307598726SKarl Rupp 
2407598726SKarl Rupp /* -------------------------------------------------------------------------- */
2507598726SKarl Rupp /*
2607598726SKarl Rupp    PCSetUp_SAVIENNACL - Prepares for the use of the SAVIENNACL preconditioner
2707598726SKarl Rupp                         by setting data structures and options.
2807598726SKarl Rupp 
2907598726SKarl Rupp    Input Parameter:
3007598726SKarl Rupp .  pc - the preconditioner context
3107598726SKarl Rupp 
3207598726SKarl Rupp    Application Interface Routine: PCSetUp()
3307598726SKarl Rupp 
3407598726SKarl Rupp    Notes:
3507598726SKarl Rupp    The interface routine PCSetUp() is not usually called directly by
3607598726SKarl Rupp    the user, but instead is called by PCApply() if necessary.
3707598726SKarl Rupp */
3807598726SKarl Rupp static PetscErrorCode PCSetUp_SAVIENNACL(PC pc)
3907598726SKarl Rupp {
4007598726SKarl Rupp   PC_SAVIENNACL      *sa = (PC_SAVIENNACL*)pc->data;
4107598726SKarl Rupp   PetscBool          flg = PETSC_FALSE;
4207598726SKarl Rupp   PetscErrorCode     ierr;
4307598726SKarl Rupp   Mat_SeqAIJViennaCL *gpustruct;
4407598726SKarl Rupp 
4507598726SKarl Rupp   PetscFunctionBegin;
4607598726SKarl Rupp   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATSEQAIJVIENNACL,&flg);CHKERRQ(ierr);
4707598726SKarl Rupp   if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Currently only handles ViennaCL matrices");
4807598726SKarl Rupp   if (pc->setupcalled != 0) {
4907598726SKarl Rupp     try {
5007598726SKarl Rupp       delete sa->SAVIENNACL;
5107598726SKarl Rupp     } catch(char *ex) {
52*98921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
5307598726SKarl Rupp     }
5407598726SKarl Rupp   }
5507598726SKarl Rupp   try {
5607598726SKarl Rupp #if defined(PETSC_USE_COMPLEX)
5707598726SKarl Rupp     gpustruct = NULL;
5807598726SKarl Rupp     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"No support for complex arithmetic in SAVIENNACL preconditioner");
5907598726SKarl Rupp #else
6007598726SKarl Rupp     ierr      = MatViennaCLCopyToGPU(pc->pmat);CHKERRQ(ierr);
6107598726SKarl Rupp     gpustruct = (Mat_SeqAIJViennaCL*)(pc->pmat->spptr);
6207598726SKarl Rupp 
6307598726SKarl Rupp     viennacl::linalg::amg_tag amg_tag_sa_pmis;
6407598726SKarl Rupp     amg_tag_sa_pmis.set_coarsening_method(viennacl::linalg::AMG_COARSENING_METHOD_MIS2_AGGREGATION);
6507598726SKarl Rupp     amg_tag_sa_pmis.set_interpolation_method(viennacl::linalg::AMG_INTERPOLATION_METHOD_SMOOTHED_AGGREGATION);
6607598726SKarl Rupp     ViennaCLAIJMatrix *mat = (ViennaCLAIJMatrix*)gpustruct->mat;
6707598726SKarl Rupp     sa->SAVIENNACL = new viennacl::linalg::amg_precond<viennacl::compressed_matrix<PetscScalar> >(*mat, amg_tag_sa_pmis);
6807598726SKarl Rupp     sa->SAVIENNACL->setup();
6907598726SKarl Rupp #endif
7007598726SKarl Rupp   } catch(char *ex) {
71*98921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
7207598726SKarl Rupp   }
7307598726SKarl Rupp   PetscFunctionReturn(0);
7407598726SKarl Rupp }
7507598726SKarl Rupp 
7607598726SKarl Rupp /* -------------------------------------------------------------------------- */
7707598726SKarl Rupp /*
7807598726SKarl Rupp    PCApply_SAVIENNACL - Applies the SAVIENNACL preconditioner to a vector.
7907598726SKarl Rupp 
8007598726SKarl Rupp    Input Parameters:
8107598726SKarl Rupp .  pc - the preconditioner context
8207598726SKarl Rupp .  x - input vector
8307598726SKarl Rupp 
8407598726SKarl Rupp    Output Parameter:
8507598726SKarl Rupp .  y - output vector
8607598726SKarl Rupp 
8707598726SKarl Rupp    Application Interface Routine: PCApply()
8807598726SKarl Rupp  */
8907598726SKarl Rupp static PetscErrorCode PCApply_SAVIENNACL(PC pc,Vec x,Vec y)
9007598726SKarl Rupp {
9107598726SKarl Rupp   PC_SAVIENNACL                 *sac = (PC_SAVIENNACL*)pc->data;
9207598726SKarl Rupp   PetscErrorCode                ierr;
9307598726SKarl Rupp   PetscBool                     flg1,flg2;
9407598726SKarl Rupp   viennacl::vector<PetscScalar> const *xarray=NULL;
9507598726SKarl Rupp   viennacl::vector<PetscScalar> *yarray=NULL;
9607598726SKarl Rupp 
9707598726SKarl Rupp   PetscFunctionBegin;
9807598726SKarl Rupp   /*how to apply a certain fixed number of iterations?*/
9907598726SKarl Rupp   ierr = PetscObjectTypeCompare((PetscObject)x,VECSEQVIENNACL,&flg1);CHKERRQ(ierr);
10007598726SKarl Rupp   ierr = PetscObjectTypeCompare((PetscObject)y,VECSEQVIENNACL,&flg2);CHKERRQ(ierr);
10107598726SKarl Rupp   if (!(flg1 && flg2)) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP, "Currently only handles ViennaCL vectors");
10207598726SKarl Rupp   if (!sac->SAVIENNACL) {
10307598726SKarl Rupp     ierr = PCSetUp_SAVIENNACL(pc);CHKERRQ(ierr);
10407598726SKarl Rupp   }
10507598726SKarl Rupp   ierr = VecViennaCLGetArrayRead(x,&xarray);CHKERRQ(ierr);
10607598726SKarl Rupp   ierr = VecViennaCLGetArrayWrite(y,&yarray);CHKERRQ(ierr);
10707598726SKarl Rupp   try {
108c4163675SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
10907598726SKarl Rupp     *yarray = *xarray;
11007598726SKarl Rupp     sac->SAVIENNACL->apply(*yarray);
11107598726SKarl Rupp #endif
11207598726SKarl Rupp   } catch(char * ex) {
113*98921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
11407598726SKarl Rupp   }
11507598726SKarl Rupp   ierr = VecViennaCLRestoreArrayRead(x,&xarray);CHKERRQ(ierr);
11607598726SKarl Rupp   ierr = VecViennaCLRestoreArrayWrite(y,&yarray);CHKERRQ(ierr);
11707598726SKarl Rupp   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
11807598726SKarl Rupp   PetscFunctionReturn(0);
11907598726SKarl Rupp }
12007598726SKarl Rupp /* -------------------------------------------------------------------------- */
12107598726SKarl Rupp /*
12207598726SKarl Rupp    PCDestroy_SAVIENNACL - Destroys the private context for the SAVIENNACL preconditioner
12307598726SKarl Rupp    that was created with PCCreate_SAVIENNACL().
12407598726SKarl Rupp 
12507598726SKarl Rupp    Input Parameter:
12607598726SKarl Rupp .  pc - the preconditioner context
12707598726SKarl Rupp 
12807598726SKarl Rupp    Application Interface Routine: PCDestroy()
12907598726SKarl Rupp */
13007598726SKarl Rupp static PetscErrorCode PCDestroy_SAVIENNACL(PC pc)
13107598726SKarl Rupp {
13207598726SKarl Rupp   PC_SAVIENNACL  *sac = (PC_SAVIENNACL*)pc->data;
13307598726SKarl Rupp   PetscErrorCode ierr;
13407598726SKarl Rupp 
13507598726SKarl Rupp   PetscFunctionBegin;
13607598726SKarl Rupp   if (sac->SAVIENNACL) {
13707598726SKarl Rupp     try {
13807598726SKarl Rupp       delete sac->SAVIENNACL;
13907598726SKarl Rupp     } catch(char * ex) {
140*98921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
14107598726SKarl Rupp     }
14207598726SKarl Rupp   }
14307598726SKarl Rupp 
14407598726SKarl Rupp   /*
14507598726SKarl Rupp       Free the private data structure that was hanging off the PC
14607598726SKarl Rupp   */
14707598726SKarl Rupp   ierr = PetscFree(pc->data);CHKERRQ(ierr);
14807598726SKarl Rupp   PetscFunctionReturn(0);
14907598726SKarl Rupp }
15007598726SKarl Rupp 
15107598726SKarl Rupp static PetscErrorCode PCSetFromOptions_SAVIENNACL(PetscOptionItems *PetscOptionsObject,PC pc)
15207598726SKarl Rupp {
15307598726SKarl Rupp   PetscErrorCode ierr;
15407598726SKarl Rupp 
15507598726SKarl Rupp   PetscFunctionBegin;
15607598726SKarl Rupp   ierr = PetscOptionsHead(PetscOptionsObject,"SAVIENNACL options");CHKERRQ(ierr);
15707598726SKarl Rupp   ierr = PetscOptionsTail();CHKERRQ(ierr);
15807598726SKarl Rupp   PetscFunctionReturn(0);
15907598726SKarl Rupp }
16007598726SKarl Rupp 
16107598726SKarl Rupp /* -------------------------------------------------------------------------- */
16207598726SKarl Rupp 
16307598726SKarl Rupp /*MC
16407598726SKarl Rupp      PCSAViennaCL  - A smoothed agglomeration algorithm that can be used via the CUDA, OpenCL, and OpenMP backends of ViennaCL
16507598726SKarl Rupp 
16607598726SKarl Rupp    Level: advanced
16707598726SKarl Rupp 
16807598726SKarl Rupp .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
16907598726SKarl Rupp 
17007598726SKarl Rupp M*/
17107598726SKarl Rupp 
17207598726SKarl Rupp PETSC_EXTERN PetscErrorCode PCCreate_SAVIENNACL(PC pc)
17307598726SKarl Rupp {
17407598726SKarl Rupp   PC_SAVIENNACL  *sac;
17507598726SKarl Rupp   PetscErrorCode ierr;
17607598726SKarl Rupp 
17707598726SKarl Rupp   PetscFunctionBegin;
17807598726SKarl Rupp   /*
17907598726SKarl Rupp      Creates the private data structure for this preconditioner and
18007598726SKarl Rupp      attach it to the PC object.
18107598726SKarl Rupp   */
18207598726SKarl Rupp   ierr     = PetscNewLog(pc,&sac);CHKERRQ(ierr);
18307598726SKarl Rupp   pc->data = (void*)sac;
18407598726SKarl Rupp 
18507598726SKarl Rupp   /*
18607598726SKarl Rupp      Initialize the pointer to zero
18707598726SKarl Rupp      Initialize number of v-cycles to default (1)
18807598726SKarl Rupp   */
18907598726SKarl Rupp   sac->SAVIENNACL = 0;
19007598726SKarl Rupp 
19107598726SKarl Rupp   /*
19207598726SKarl Rupp       Set the pointers for the functions that are provided above.
19307598726SKarl Rupp       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
19407598726SKarl Rupp       are called, they will automatically call these functions.  Note we
19507598726SKarl Rupp       choose not to provide a couple of these functions since they are
19607598726SKarl Rupp       not needed.
19707598726SKarl Rupp   */
19807598726SKarl Rupp   pc->ops->apply               = PCApply_SAVIENNACL;
19907598726SKarl Rupp   pc->ops->applytranspose      = 0;
20007598726SKarl Rupp   pc->ops->setup               = PCSetUp_SAVIENNACL;
20107598726SKarl Rupp   pc->ops->destroy             = PCDestroy_SAVIENNACL;
20207598726SKarl Rupp   pc->ops->setfromoptions      = PCSetFromOptions_SAVIENNACL;
20307598726SKarl Rupp   pc->ops->view                = 0;
20407598726SKarl Rupp   pc->ops->applyrichardson     = 0;
20507598726SKarl Rupp   pc->ops->applysymmetricleft  = 0;
20607598726SKarl Rupp   pc->ops->applysymmetricright = 0;
20707598726SKarl Rupp   PetscFunctionReturn(0);
20807598726SKarl Rupp }
20907598726SKarl Rupp 
210