xref: /petsc/src/ksp/pc/impls/saviennacl/saviennacl.cxx (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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   Mat_SeqAIJViennaCL *gpustruct;
4307598726SKarl Rupp 
4407598726SKarl Rupp   PetscFunctionBegin;
455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)pc->pmat,MATSEQAIJVIENNACL,&flg));
46*28b400f6SJacob Faibussowitsch   PetscCheck(flg,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Currently only handles ViennaCL matrices");
4707598726SKarl Rupp   if (pc->setupcalled != 0) {
4807598726SKarl Rupp     try {
4907598726SKarl Rupp       delete sa->SAVIENNACL;
5007598726SKarl Rupp     } catch(char *ex) {
5198921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
5207598726SKarl Rupp     }
5307598726SKarl Rupp   }
5407598726SKarl Rupp   try {
5507598726SKarl Rupp #if defined(PETSC_USE_COMPLEX)
5607598726SKarl Rupp     gpustruct = NULL;
5707598726SKarl Rupp     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"No support for complex arithmetic in SAVIENNACL preconditioner");
5807598726SKarl Rupp #else
595f80ce2aSJacob Faibussowitsch     CHKERRQ(MatViennaCLCopyToGPU(pc->pmat));
6007598726SKarl Rupp     gpustruct = (Mat_SeqAIJViennaCL*)(pc->pmat->spptr);
6107598726SKarl Rupp 
6207598726SKarl Rupp     viennacl::linalg::amg_tag amg_tag_sa_pmis;
6307598726SKarl Rupp     amg_tag_sa_pmis.set_coarsening_method(viennacl::linalg::AMG_COARSENING_METHOD_MIS2_AGGREGATION);
6407598726SKarl Rupp     amg_tag_sa_pmis.set_interpolation_method(viennacl::linalg::AMG_INTERPOLATION_METHOD_SMOOTHED_AGGREGATION);
6507598726SKarl Rupp     ViennaCLAIJMatrix *mat = (ViennaCLAIJMatrix*)gpustruct->mat;
6607598726SKarl Rupp     sa->SAVIENNACL = new viennacl::linalg::amg_precond<viennacl::compressed_matrix<PetscScalar> >(*mat, amg_tag_sa_pmis);
6707598726SKarl Rupp     sa->SAVIENNACL->setup();
6807598726SKarl Rupp #endif
6907598726SKarl Rupp   } catch(char *ex) {
7098921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
7107598726SKarl Rupp   }
7207598726SKarl Rupp   PetscFunctionReturn(0);
7307598726SKarl Rupp }
7407598726SKarl Rupp 
7507598726SKarl Rupp /* -------------------------------------------------------------------------- */
7607598726SKarl Rupp /*
7707598726SKarl Rupp    PCApply_SAVIENNACL - Applies the SAVIENNACL preconditioner to a vector.
7807598726SKarl Rupp 
7907598726SKarl Rupp    Input Parameters:
8007598726SKarl Rupp .  pc - the preconditioner context
8107598726SKarl Rupp .  x - input vector
8207598726SKarl Rupp 
8307598726SKarl Rupp    Output Parameter:
8407598726SKarl Rupp .  y - output vector
8507598726SKarl Rupp 
8607598726SKarl Rupp    Application Interface Routine: PCApply()
8707598726SKarl Rupp  */
8807598726SKarl Rupp static PetscErrorCode PCApply_SAVIENNACL(PC pc,Vec x,Vec y)
8907598726SKarl Rupp {
9007598726SKarl Rupp   PC_SAVIENNACL                 *sac = (PC_SAVIENNACL*)pc->data;
9107598726SKarl Rupp   PetscBool                     flg1,flg2;
9207598726SKarl Rupp   viennacl::vector<PetscScalar> const *xarray=NULL;
9307598726SKarl Rupp   viennacl::vector<PetscScalar> *yarray=NULL;
9407598726SKarl Rupp 
9507598726SKarl Rupp   PetscFunctionBegin;
9607598726SKarl Rupp   /*how to apply a certain fixed number of iterations?*/
975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)x,VECSEQVIENNACL,&flg1));
985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)y,VECSEQVIENNACL,&flg2));
992c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!(flg1 && flg2),PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP, "Currently only handles ViennaCL vectors");
10007598726SKarl Rupp   if (!sac->SAVIENNACL) {
1015f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetUp_SAVIENNACL(pc));
10207598726SKarl Rupp   }
1035f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViennaCLGetArrayRead(x,&xarray));
1045f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViennaCLGetArrayWrite(y,&yarray));
10507598726SKarl Rupp   try {
106c4163675SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
10707598726SKarl Rupp     *yarray = *xarray;
10807598726SKarl Rupp     sac->SAVIENNACL->apply(*yarray);
10907598726SKarl Rupp #endif
11007598726SKarl Rupp   } catch(char * ex) {
11198921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
11207598726SKarl Rupp   }
1135f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViennaCLRestoreArrayRead(x,&xarray));
1145f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViennaCLRestoreArrayWrite(y,&yarray));
1155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateIncrease((PetscObject)y));
11607598726SKarl Rupp   PetscFunctionReturn(0);
11707598726SKarl Rupp }
11807598726SKarl Rupp /* -------------------------------------------------------------------------- */
11907598726SKarl Rupp /*
12007598726SKarl Rupp    PCDestroy_SAVIENNACL - Destroys the private context for the SAVIENNACL preconditioner
12107598726SKarl Rupp    that was created with PCCreate_SAVIENNACL().
12207598726SKarl Rupp 
12307598726SKarl Rupp    Input Parameter:
12407598726SKarl Rupp .  pc - the preconditioner context
12507598726SKarl Rupp 
12607598726SKarl Rupp    Application Interface Routine: PCDestroy()
12707598726SKarl Rupp */
12807598726SKarl Rupp static PetscErrorCode PCDestroy_SAVIENNACL(PC pc)
12907598726SKarl Rupp {
13007598726SKarl Rupp   PC_SAVIENNACL  *sac = (PC_SAVIENNACL*)pc->data;
13107598726SKarl Rupp 
13207598726SKarl Rupp   PetscFunctionBegin;
13307598726SKarl Rupp   if (sac->SAVIENNACL) {
13407598726SKarl Rupp     try {
13507598726SKarl Rupp       delete sac->SAVIENNACL;
13607598726SKarl Rupp     } catch(char * ex) {
13798921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
13807598726SKarl Rupp     }
13907598726SKarl Rupp   }
14007598726SKarl Rupp 
14107598726SKarl Rupp   /*
14207598726SKarl Rupp       Free the private data structure that was hanging off the PC
14307598726SKarl Rupp   */
1445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pc->data));
14507598726SKarl Rupp   PetscFunctionReturn(0);
14607598726SKarl Rupp }
14707598726SKarl Rupp 
14807598726SKarl Rupp static PetscErrorCode PCSetFromOptions_SAVIENNACL(PetscOptionItems *PetscOptionsObject,PC pc)
14907598726SKarl Rupp {
15007598726SKarl Rupp   PetscFunctionBegin;
1515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"SAVIENNACL options"));
1525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
15307598726SKarl Rupp   PetscFunctionReturn(0);
15407598726SKarl Rupp }
15507598726SKarl Rupp 
15607598726SKarl Rupp /* -------------------------------------------------------------------------- */
15707598726SKarl Rupp 
15807598726SKarl Rupp /*MC
15907598726SKarl Rupp      PCSAViennaCL  - A smoothed agglomeration algorithm that can be used via the CUDA, OpenCL, and OpenMP backends of ViennaCL
16007598726SKarl Rupp 
16107598726SKarl Rupp    Level: advanced
16207598726SKarl Rupp 
16307598726SKarl Rupp .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
16407598726SKarl Rupp 
16507598726SKarl Rupp M*/
16607598726SKarl Rupp 
16707598726SKarl Rupp PETSC_EXTERN PetscErrorCode PCCreate_SAVIENNACL(PC pc)
16807598726SKarl Rupp {
16907598726SKarl Rupp   PC_SAVIENNACL  *sac;
17007598726SKarl Rupp 
17107598726SKarl Rupp   PetscFunctionBegin;
17207598726SKarl Rupp   /*
17307598726SKarl Rupp      Creates the private data structure for this preconditioner and
17407598726SKarl Rupp      attach it to the PC object.
17507598726SKarl Rupp   */
1765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(pc,&sac));
17707598726SKarl Rupp   pc->data = (void*)sac;
17807598726SKarl Rupp 
17907598726SKarl Rupp   /*
18007598726SKarl Rupp      Initialize the pointer to zero
18107598726SKarl Rupp      Initialize number of v-cycles to default (1)
18207598726SKarl Rupp   */
18307598726SKarl Rupp   sac->SAVIENNACL = 0;
18407598726SKarl Rupp 
18507598726SKarl Rupp   /*
18607598726SKarl Rupp       Set the pointers for the functions that are provided above.
18707598726SKarl Rupp       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
18807598726SKarl Rupp       are called, they will automatically call these functions.  Note we
18907598726SKarl Rupp       choose not to provide a couple of these functions since they are
19007598726SKarl Rupp       not needed.
19107598726SKarl Rupp   */
19207598726SKarl Rupp   pc->ops->apply               = PCApply_SAVIENNACL;
19307598726SKarl Rupp   pc->ops->applytranspose      = 0;
19407598726SKarl Rupp   pc->ops->setup               = PCSetUp_SAVIENNACL;
19507598726SKarl Rupp   pc->ops->destroy             = PCDestroy_SAVIENNACL;
19607598726SKarl Rupp   pc->ops->setfromoptions      = PCSetFromOptions_SAVIENNACL;
19707598726SKarl Rupp   pc->ops->view                = 0;
19807598726SKarl Rupp   pc->ops->applyrichardson     = 0;
19907598726SKarl Rupp   pc->ops->applysymmetricleft  = 0;
20007598726SKarl Rupp   pc->ops->applysymmetricright = 0;
20107598726SKarl Rupp   PetscFunctionReturn(0);
20207598726SKarl Rupp }
203