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); 47*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!flg,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) { 5298921bdaSJacob 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) { 7198921bdaSJacob 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); 101*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!(flg1 && flg2),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) { 11398921bdaSJacob 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) { 14098921bdaSJacob 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