xref: /petsc/src/ksp/pc/impls/saviennacl/saviennacl.cxx (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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 */
389371c9d4SSatish Balay static PetscErrorCode PCSetUp_SAVIENNACL(PC pc) {
3907598726SKarl Rupp   PC_SAVIENNACL      *sa  = (PC_SAVIENNACL *)pc->data;
4007598726SKarl Rupp   PetscBool           flg = PETSC_FALSE;
4107598726SKarl Rupp   Mat_SeqAIJViennaCL *gpustruct;
4207598726SKarl Rupp 
4307598726SKarl Rupp   PetscFunctionBegin;
449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATSEQAIJVIENNACL, &flg));
4528b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Currently only handles ViennaCL matrices");
4607598726SKarl Rupp   if (pc->setupcalled != 0) {
4707598726SKarl Rupp     try {
4807598726SKarl Rupp       delete sa->SAVIENNACL;
499371c9d4SSatish Balay     } catch (char *ex) { SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex); }
5007598726SKarl Rupp   }
5107598726SKarl Rupp   try {
5207598726SKarl Rupp #if defined(PETSC_USE_COMPLEX)
5307598726SKarl Rupp     gpustruct = NULL;
5407598726SKarl Rupp     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "No support for complex arithmetic in SAVIENNACL preconditioner");
5507598726SKarl Rupp #else
569566063dSJacob Faibussowitsch     PetscCall(MatViennaCLCopyToGPU(pc->pmat));
5707598726SKarl Rupp     gpustruct = (Mat_SeqAIJViennaCL *)(pc->pmat->spptr);
5807598726SKarl Rupp 
5907598726SKarl Rupp     viennacl::linalg::amg_tag amg_tag_sa_pmis;
6007598726SKarl Rupp     amg_tag_sa_pmis.set_coarsening_method(viennacl::linalg::AMG_COARSENING_METHOD_MIS2_AGGREGATION);
6107598726SKarl Rupp     amg_tag_sa_pmis.set_interpolation_method(viennacl::linalg::AMG_INTERPOLATION_METHOD_SMOOTHED_AGGREGATION);
6207598726SKarl Rupp     ViennaCLAIJMatrix *mat = (ViennaCLAIJMatrix *)gpustruct->mat;
6307598726SKarl Rupp     sa->SAVIENNACL         = new viennacl::linalg::amg_precond<viennacl::compressed_matrix<PetscScalar>>(*mat, amg_tag_sa_pmis);
6407598726SKarl Rupp     sa->SAVIENNACL->setup();
6507598726SKarl Rupp #endif
669371c9d4SSatish Balay   } catch (char *ex) { SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex); }
6707598726SKarl Rupp   PetscFunctionReturn(0);
6807598726SKarl Rupp }
6907598726SKarl Rupp 
7007598726SKarl Rupp /* -------------------------------------------------------------------------- */
7107598726SKarl Rupp /*
7207598726SKarl Rupp    PCApply_SAVIENNACL - Applies the SAVIENNACL preconditioner to a vector.
7307598726SKarl Rupp 
7407598726SKarl Rupp    Input Parameters:
7507598726SKarl Rupp .  pc - the preconditioner context
7607598726SKarl Rupp .  x - input vector
7707598726SKarl Rupp 
7807598726SKarl Rupp    Output Parameter:
7907598726SKarl Rupp .  y - output vector
8007598726SKarl Rupp 
8107598726SKarl Rupp    Application Interface Routine: PCApply()
8207598726SKarl Rupp  */
839371c9d4SSatish Balay static PetscErrorCode PCApply_SAVIENNACL(PC pc, Vec x, Vec y) {
8407598726SKarl Rupp   PC_SAVIENNACL                       *sac = (PC_SAVIENNACL *)pc->data;
8507598726SKarl Rupp   PetscBool                            flg1, flg2;
8607598726SKarl Rupp   viennacl::vector<PetscScalar> const *xarray = NULL;
8707598726SKarl Rupp   viennacl::vector<PetscScalar>       *yarray = NULL;
8807598726SKarl Rupp 
8907598726SKarl Rupp   PetscFunctionBegin;
9007598726SKarl Rupp   /*how to apply a certain fixed number of iterations?*/
919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)x, VECSEQVIENNACL, &flg1));
929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)y, VECSEQVIENNACL, &flg2));
9308401ef6SPierre Jolivet   PetscCheck((flg1 && flg2), PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Currently only handles ViennaCL vectors");
94*48a46eb9SPierre Jolivet   if (!sac->SAVIENNACL) PetscCall(PCSetUp_SAVIENNACL(pc));
959566063dSJacob Faibussowitsch   PetscCall(VecViennaCLGetArrayRead(x, &xarray));
969566063dSJacob Faibussowitsch   PetscCall(VecViennaCLGetArrayWrite(y, &yarray));
9707598726SKarl Rupp   try {
98c4163675SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
9907598726SKarl Rupp     *yarray = *xarray;
10007598726SKarl Rupp     sac->SAVIENNACL->apply(*yarray);
10107598726SKarl Rupp #endif
1029371c9d4SSatish Balay   } catch (char *ex) { SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex); }
1039566063dSJacob Faibussowitsch   PetscCall(VecViennaCLRestoreArrayRead(x, &xarray));
1049566063dSJacob Faibussowitsch   PetscCall(VecViennaCLRestoreArrayWrite(y, &yarray));
1059566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)y));
10607598726SKarl Rupp   PetscFunctionReturn(0);
10707598726SKarl Rupp }
10807598726SKarl Rupp /* -------------------------------------------------------------------------- */
10907598726SKarl Rupp /*
11007598726SKarl Rupp    PCDestroy_SAVIENNACL - Destroys the private context for the SAVIENNACL preconditioner
11107598726SKarl Rupp    that was created with PCCreate_SAVIENNACL().
11207598726SKarl Rupp 
11307598726SKarl Rupp    Input Parameter:
11407598726SKarl Rupp .  pc - the preconditioner context
11507598726SKarl Rupp 
11607598726SKarl Rupp    Application Interface Routine: PCDestroy()
11707598726SKarl Rupp */
1189371c9d4SSatish Balay static PetscErrorCode PCDestroy_SAVIENNACL(PC pc) {
11907598726SKarl Rupp   PC_SAVIENNACL *sac = (PC_SAVIENNACL *)pc->data;
12007598726SKarl Rupp 
12107598726SKarl Rupp   PetscFunctionBegin;
12207598726SKarl Rupp   if (sac->SAVIENNACL) {
12307598726SKarl Rupp     try {
12407598726SKarl Rupp       delete sac->SAVIENNACL;
1259371c9d4SSatish Balay     } catch (char *ex) { SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex); }
12607598726SKarl Rupp   }
12707598726SKarl Rupp 
12807598726SKarl Rupp   /*
12907598726SKarl Rupp       Free the private data structure that was hanging off the PC
13007598726SKarl Rupp   */
1319566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
13207598726SKarl Rupp   PetscFunctionReturn(0);
13307598726SKarl Rupp }
13407598726SKarl Rupp 
1359371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_SAVIENNACL(PC pc, PetscOptionItems *PetscOptionsObject) {
13607598726SKarl Rupp   PetscFunctionBegin;
137d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SAVIENNACL options");
138d0609cedSBarry Smith   PetscOptionsHeadEnd();
13907598726SKarl Rupp   PetscFunctionReturn(0);
14007598726SKarl Rupp }
14107598726SKarl Rupp 
14207598726SKarl Rupp /* -------------------------------------------------------------------------- */
14307598726SKarl Rupp 
14407598726SKarl Rupp /*MC
14507598726SKarl Rupp      PCSAViennaCL  - A smoothed agglomeration algorithm that can be used via the CUDA, OpenCL, and OpenMP backends of ViennaCL
14607598726SKarl Rupp 
14707598726SKarl Rupp    Level: advanced
14807598726SKarl Rupp 
149db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`
15007598726SKarl Rupp 
15107598726SKarl Rupp M*/
15207598726SKarl Rupp 
1539371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_SAVIENNACL(PC pc) {
15407598726SKarl Rupp   PC_SAVIENNACL *sac;
15507598726SKarl Rupp 
15607598726SKarl Rupp   PetscFunctionBegin;
15707598726SKarl Rupp   /*
15807598726SKarl Rupp      Creates the private data structure for this preconditioner and
15907598726SKarl Rupp      attach it to the PC object.
16007598726SKarl Rupp   */
1619566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc, &sac));
16207598726SKarl Rupp   pc->data = (void *)sac;
16307598726SKarl Rupp 
16407598726SKarl Rupp   /*
16507598726SKarl Rupp      Initialize the pointer to zero
16607598726SKarl Rupp      Initialize number of v-cycles to default (1)
16707598726SKarl Rupp   */
16807598726SKarl Rupp   sac->SAVIENNACL = 0;
16907598726SKarl Rupp 
17007598726SKarl Rupp   /*
17107598726SKarl Rupp       Set the pointers for the functions that are provided above.
17207598726SKarl Rupp       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
17307598726SKarl Rupp       are called, they will automatically call these functions.  Note we
17407598726SKarl Rupp       choose not to provide a couple of these functions since they are
17507598726SKarl Rupp       not needed.
17607598726SKarl Rupp   */
17707598726SKarl Rupp   pc->ops->apply               = PCApply_SAVIENNACL;
17807598726SKarl Rupp   pc->ops->applytranspose      = 0;
17907598726SKarl Rupp   pc->ops->setup               = PCSetUp_SAVIENNACL;
18007598726SKarl Rupp   pc->ops->destroy             = PCDestroy_SAVIENNACL;
18107598726SKarl Rupp   pc->ops->setfromoptions      = PCSetFromOptions_SAVIENNACL;
18207598726SKarl Rupp   pc->ops->view                = 0;
18307598726SKarl Rupp   pc->ops->applyrichardson     = 0;
18407598726SKarl Rupp   pc->ops->applysymmetricleft  = 0;
18507598726SKarl Rupp   pc->ops->applysymmetricright = 0;
18607598726SKarl Rupp   PetscFunctionReturn(0);
18707598726SKarl Rupp }
188