1*07598726SKarl Rupp 2*07598726SKarl Rupp /* -------------------------------------------------------------------- */ 3*07598726SKarl Rupp 4*07598726SKarl Rupp /* 5*07598726SKarl Rupp Include files needed for the ViennaCL Smoothed Aggregation preconditioner: 6*07598726SKarl Rupp pcimpl.h - private include file intended for use by all preconditioners 7*07598726SKarl Rupp */ 8*07598726SKarl Rupp #define PETSC_SKIP_SPINLOCK 9*07598726SKarl Rupp #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 10*07598726SKarl Rupp #include <../src/mat/impls/aij/seq/aij.h> 11*07598726SKarl Rupp #include <../src/vec/vec/impls/dvecimpl.h> 12*07598726SKarl Rupp #include <../src/mat/impls/aij/seq/seqviennacl/viennaclmatimpl.h> 13*07598726SKarl Rupp #include <../src/vec/vec/impls/seq/seqviennacl/viennaclvecimpl.h> 14*07598726SKarl Rupp #include <viennacl/linalg/amg.hpp> 15*07598726SKarl Rupp 16*07598726SKarl Rupp /* 17*07598726SKarl Rupp Private context (data structure) for the SAVIENNACL preconditioner. 18*07598726SKarl Rupp */ 19*07598726SKarl Rupp typedef struct { 20*07598726SKarl Rupp viennacl::linalg::amg_precond<viennacl::compressed_matrix<PetscScalar> > *SAVIENNACL; 21*07598726SKarl Rupp } PC_SAVIENNACL; 22*07598726SKarl Rupp 23*07598726SKarl Rupp 24*07598726SKarl Rupp /* -------------------------------------------------------------------------- */ 25*07598726SKarl Rupp /* 26*07598726SKarl Rupp PCSetUp_SAVIENNACL - Prepares for the use of the SAVIENNACL preconditioner 27*07598726SKarl Rupp by setting data structures and options. 28*07598726SKarl Rupp 29*07598726SKarl Rupp Input Parameter: 30*07598726SKarl Rupp . pc - the preconditioner context 31*07598726SKarl Rupp 32*07598726SKarl Rupp Application Interface Routine: PCSetUp() 33*07598726SKarl Rupp 34*07598726SKarl Rupp Notes: 35*07598726SKarl Rupp The interface routine PCSetUp() is not usually called directly by 36*07598726SKarl Rupp the user, but instead is called by PCApply() if necessary. 37*07598726SKarl Rupp */ 38*07598726SKarl Rupp #undef __FUNCT__ 39*07598726SKarl Rupp #define __FUNCT__ "PCSetUp_SAVIENNACL" 40*07598726SKarl Rupp static PetscErrorCode PCSetUp_SAVIENNACL(PC pc) 41*07598726SKarl Rupp { 42*07598726SKarl Rupp PC_SAVIENNACL *sa = (PC_SAVIENNACL*)pc->data; 43*07598726SKarl Rupp PetscBool flg = PETSC_FALSE; 44*07598726SKarl Rupp PetscErrorCode ierr; 45*07598726SKarl Rupp Mat_SeqAIJViennaCL *gpustruct; 46*07598726SKarl Rupp 47*07598726SKarl Rupp PetscFunctionBegin; 48*07598726SKarl Rupp ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATSEQAIJVIENNACL,&flg);CHKERRQ(ierr); 49*07598726SKarl Rupp if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Currently only handles ViennaCL matrices"); 50*07598726SKarl Rupp if (pc->setupcalled != 0) { 51*07598726SKarl Rupp try { 52*07598726SKarl Rupp delete sa->SAVIENNACL; 53*07598726SKarl Rupp } catch(char *ex) { 54*07598726SKarl Rupp SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex); 55*07598726SKarl Rupp } 56*07598726SKarl Rupp } 57*07598726SKarl Rupp try { 58*07598726SKarl Rupp #if defined(PETSC_USE_COMPLEX) 59*07598726SKarl Rupp gpustruct = NULL; 60*07598726SKarl Rupp SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"No support for complex arithmetic in SAVIENNACL preconditioner"); 61*07598726SKarl Rupp #else 62*07598726SKarl Rupp ierr = MatViennaCLCopyToGPU(pc->pmat);CHKERRQ(ierr); 63*07598726SKarl Rupp gpustruct = (Mat_SeqAIJViennaCL*)(pc->pmat->spptr); 64*07598726SKarl Rupp 65*07598726SKarl Rupp viennacl::linalg::amg_tag amg_tag_sa_pmis; 66*07598726SKarl Rupp amg_tag_sa_pmis.set_coarsening_method(viennacl::linalg::AMG_COARSENING_METHOD_MIS2_AGGREGATION); 67*07598726SKarl Rupp amg_tag_sa_pmis.set_interpolation_method(viennacl::linalg::AMG_INTERPOLATION_METHOD_SMOOTHED_AGGREGATION); 68*07598726SKarl Rupp ViennaCLAIJMatrix *mat = (ViennaCLAIJMatrix*)gpustruct->mat; 69*07598726SKarl Rupp sa->SAVIENNACL = new viennacl::linalg::amg_precond<viennacl::compressed_matrix<PetscScalar> >(*mat, amg_tag_sa_pmis); 70*07598726SKarl Rupp sa->SAVIENNACL->setup(); 71*07598726SKarl Rupp #endif 72*07598726SKarl Rupp } catch(char *ex) { 73*07598726SKarl Rupp SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex); 74*07598726SKarl Rupp } 75*07598726SKarl Rupp PetscFunctionReturn(0); 76*07598726SKarl Rupp } 77*07598726SKarl Rupp 78*07598726SKarl Rupp /* -------------------------------------------------------------------------- */ 79*07598726SKarl Rupp /* 80*07598726SKarl Rupp PCApply_SAVIENNACL - Applies the SAVIENNACL preconditioner to a vector. 81*07598726SKarl Rupp 82*07598726SKarl Rupp Input Parameters: 83*07598726SKarl Rupp . pc - the preconditioner context 84*07598726SKarl Rupp . x - input vector 85*07598726SKarl Rupp 86*07598726SKarl Rupp Output Parameter: 87*07598726SKarl Rupp . y - output vector 88*07598726SKarl Rupp 89*07598726SKarl Rupp Application Interface Routine: PCApply() 90*07598726SKarl Rupp */ 91*07598726SKarl Rupp #undef __FUNCT__ 92*07598726SKarl Rupp #define __FUNCT__ "PCApply_SAVIENNACL" 93*07598726SKarl Rupp static PetscErrorCode PCApply_SAVIENNACL(PC pc,Vec x,Vec y) 94*07598726SKarl Rupp { 95*07598726SKarl Rupp PC_SAVIENNACL *sac = (PC_SAVIENNACL*)pc->data; 96*07598726SKarl Rupp PetscErrorCode ierr; 97*07598726SKarl Rupp PetscBool flg1,flg2; 98*07598726SKarl Rupp viennacl::vector<PetscScalar> const *xarray=NULL; 99*07598726SKarl Rupp viennacl::vector<PetscScalar> *yarray=NULL; 100*07598726SKarl Rupp 101*07598726SKarl Rupp PetscFunctionBegin; 102*07598726SKarl Rupp /*how to apply a certain fixed number of iterations?*/ 103*07598726SKarl Rupp ierr = PetscObjectTypeCompare((PetscObject)x,VECSEQVIENNACL,&flg1);CHKERRQ(ierr); 104*07598726SKarl Rupp ierr = PetscObjectTypeCompare((PetscObject)y,VECSEQVIENNACL,&flg2);CHKERRQ(ierr); 105*07598726SKarl Rupp if (!(flg1 && flg2)) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP, "Currently only handles ViennaCL vectors"); 106*07598726SKarl Rupp if (!sac->SAVIENNACL) { 107*07598726SKarl Rupp ierr = PCSetUp_SAVIENNACL(pc);CHKERRQ(ierr); 108*07598726SKarl Rupp } 109*07598726SKarl Rupp ierr = VecSet(y,0.0);CHKERRQ(ierr); 110*07598726SKarl Rupp ierr = VecViennaCLGetArrayRead(x,&xarray);CHKERRQ(ierr); 111*07598726SKarl Rupp ierr = VecViennaCLGetArrayWrite(y,&yarray);CHKERRQ(ierr); 112*07598726SKarl Rupp try { 113*07598726SKarl Rupp #if defined(PETSC_USE_COMPLEX) 114*07598726SKarl Rupp 115*07598726SKarl Rupp #else 116*07598726SKarl Rupp *yarray = *xarray; 117*07598726SKarl Rupp sac->SAVIENNACL->apply(*yarray); 118*07598726SKarl Rupp #endif 119*07598726SKarl Rupp } catch(char * ex) { 120*07598726SKarl Rupp SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex); 121*07598726SKarl Rupp } 122*07598726SKarl Rupp ierr = VecViennaCLRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 123*07598726SKarl Rupp ierr = VecViennaCLRestoreArrayWrite(y,&yarray);CHKERRQ(ierr); 124*07598726SKarl Rupp ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr); 125*07598726SKarl Rupp PetscFunctionReturn(0); 126*07598726SKarl Rupp } 127*07598726SKarl Rupp /* -------------------------------------------------------------------------- */ 128*07598726SKarl Rupp /* 129*07598726SKarl Rupp PCDestroy_SAVIENNACL - Destroys the private context for the SAVIENNACL preconditioner 130*07598726SKarl Rupp that was created with PCCreate_SAVIENNACL(). 131*07598726SKarl Rupp 132*07598726SKarl Rupp Input Parameter: 133*07598726SKarl Rupp . pc - the preconditioner context 134*07598726SKarl Rupp 135*07598726SKarl Rupp Application Interface Routine: PCDestroy() 136*07598726SKarl Rupp */ 137*07598726SKarl Rupp #undef __FUNCT__ 138*07598726SKarl Rupp #define __FUNCT__ "PCDestroy_SAVIENNACL" 139*07598726SKarl Rupp static PetscErrorCode PCDestroy_SAVIENNACL(PC pc) 140*07598726SKarl Rupp { 141*07598726SKarl Rupp PC_SAVIENNACL *sac = (PC_SAVIENNACL*)pc->data; 142*07598726SKarl Rupp PetscErrorCode ierr; 143*07598726SKarl Rupp 144*07598726SKarl Rupp PetscFunctionBegin; 145*07598726SKarl Rupp if (sac->SAVIENNACL) { 146*07598726SKarl Rupp try { 147*07598726SKarl Rupp delete sac->SAVIENNACL; 148*07598726SKarl Rupp } catch(char * ex) { 149*07598726SKarl Rupp SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex); 150*07598726SKarl Rupp } 151*07598726SKarl Rupp } 152*07598726SKarl Rupp 153*07598726SKarl Rupp /* 154*07598726SKarl Rupp Free the private data structure that was hanging off the PC 155*07598726SKarl Rupp */ 156*07598726SKarl Rupp ierr = PetscFree(pc->data);CHKERRQ(ierr); 157*07598726SKarl Rupp PetscFunctionReturn(0); 158*07598726SKarl Rupp } 159*07598726SKarl Rupp 160*07598726SKarl Rupp #undef __FUNCT__ 161*07598726SKarl Rupp #define __FUNCT__ "PCSetFromOptions_SAVIENNACL" 162*07598726SKarl Rupp static PetscErrorCode PCSetFromOptions_SAVIENNACL(PetscOptionItems *PetscOptionsObject,PC pc) 163*07598726SKarl Rupp { 164*07598726SKarl Rupp PetscErrorCode ierr; 165*07598726SKarl Rupp 166*07598726SKarl Rupp PetscFunctionBegin; 167*07598726SKarl Rupp ierr = PetscOptionsHead(PetscOptionsObject,"SAVIENNACL options");CHKERRQ(ierr); 168*07598726SKarl Rupp ierr = PetscOptionsTail();CHKERRQ(ierr); 169*07598726SKarl Rupp PetscFunctionReturn(0); 170*07598726SKarl Rupp } 171*07598726SKarl Rupp 172*07598726SKarl Rupp /* -------------------------------------------------------------------------- */ 173*07598726SKarl Rupp 174*07598726SKarl Rupp 175*07598726SKarl Rupp /*MC 176*07598726SKarl Rupp PCSAViennaCL - A smoothed agglomeration algorithm that can be used via the CUDA, OpenCL, and OpenMP backends of ViennaCL 177*07598726SKarl Rupp 178*07598726SKarl Rupp Level: advanced 179*07598726SKarl Rupp 180*07598726SKarl Rupp .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC 181*07598726SKarl Rupp 182*07598726SKarl Rupp M*/ 183*07598726SKarl Rupp 184*07598726SKarl Rupp #undef __FUNCT__ 185*07598726SKarl Rupp #define __FUNCT__ "PCCreate_SAVIENNACL" 186*07598726SKarl Rupp PETSC_EXTERN PetscErrorCode PCCreate_SAVIENNACL(PC pc) 187*07598726SKarl Rupp { 188*07598726SKarl Rupp PC_SAVIENNACL *sac; 189*07598726SKarl Rupp PetscErrorCode ierr; 190*07598726SKarl Rupp 191*07598726SKarl Rupp PetscFunctionBegin; 192*07598726SKarl Rupp /* 193*07598726SKarl Rupp Creates the private data structure for this preconditioner and 194*07598726SKarl Rupp attach it to the PC object. 195*07598726SKarl Rupp */ 196*07598726SKarl Rupp ierr = PetscNewLog(pc,&sac);CHKERRQ(ierr); 197*07598726SKarl Rupp pc->data = (void*)sac; 198*07598726SKarl Rupp 199*07598726SKarl Rupp /* 200*07598726SKarl Rupp Initialize the pointer to zero 201*07598726SKarl Rupp Initialize number of v-cycles to default (1) 202*07598726SKarl Rupp */ 203*07598726SKarl Rupp sac->SAVIENNACL = 0; 204*07598726SKarl Rupp 205*07598726SKarl Rupp /* 206*07598726SKarl Rupp Set the pointers for the functions that are provided above. 207*07598726SKarl Rupp Now when the user-level routines (such as PCApply(), PCDestroy(), etc.) 208*07598726SKarl Rupp are called, they will automatically call these functions. Note we 209*07598726SKarl Rupp choose not to provide a couple of these functions since they are 210*07598726SKarl Rupp not needed. 211*07598726SKarl Rupp */ 212*07598726SKarl Rupp pc->ops->apply = PCApply_SAVIENNACL; 213*07598726SKarl Rupp pc->ops->applytranspose = 0; 214*07598726SKarl Rupp pc->ops->setup = PCSetUp_SAVIENNACL; 215*07598726SKarl Rupp pc->ops->destroy = PCDestroy_SAVIENNACL; 216*07598726SKarl Rupp pc->ops->setfromoptions = PCSetFromOptions_SAVIENNACL; 217*07598726SKarl Rupp pc->ops->view = 0; 218*07598726SKarl Rupp pc->ops->applyrichardson = 0; 219*07598726SKarl Rupp pc->ops->applysymmetricleft = 0; 220*07598726SKarl Rupp pc->ops->applysymmetricright = 0; 221*07598726SKarl Rupp PetscFunctionReturn(0); 222*07598726SKarl Rupp } 223*07598726SKarl Rupp 224