170baa948SKarl Rupp 270baa948SKarl Rupp /* -------------------------------------------------------------------- */ 370baa948SKarl Rupp 470baa948SKarl Rupp /* 570baa948SKarl Rupp Include files needed for the ViennaCL row-scaling preconditioner: 670baa948SKarl Rupp pcimpl.h - private include file intended for use by all preconditioners 770baa948SKarl Rupp */ 870baa948SKarl Rupp #define PETSC_SKIP_SPINLOCK 9*99acd6aaSStefano Zampini #define PETSC_SKIP_IMMINTRIN_H_CUDAWORKAROUND 1 10*99acd6aaSStefano Zampini 1170baa948SKarl Rupp #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 1270baa948SKarl Rupp #include <../src/mat/impls/aij/seq/aij.h> 1370baa948SKarl Rupp #include <../src/vec/vec/impls/dvecimpl.h> 1470baa948SKarl Rupp #include <../src/mat/impls/aij/seq/seqviennacl/viennaclmatimpl.h> 1570baa948SKarl Rupp #include <../src/vec/vec/impls/seq/seqviennacl/viennaclvecimpl.h> 1670baa948SKarl Rupp #include <viennacl/linalg/row_scaling.hpp> 1770baa948SKarl Rupp 1870baa948SKarl Rupp /* 1970baa948SKarl Rupp Private context (data structure) for the ROWSCALINGVIENNACL preconditioner. 2070baa948SKarl Rupp */ 2170baa948SKarl Rupp typedef struct { 2270baa948SKarl Rupp viennacl::linalg::row_scaling< viennacl::compressed_matrix<PetscScalar> > *ROWSCALINGVIENNACL; 2370baa948SKarl Rupp } PC_ROWSCALINGVIENNACL; 2470baa948SKarl Rupp 2570baa948SKarl Rupp 2670baa948SKarl Rupp /* -------------------------------------------------------------------------- */ 2770baa948SKarl Rupp /* 2870baa948SKarl Rupp PCSetUp_ROWSCALINGVIENNACL - Prepares for the use of the ROWSCALINGVIENNACL preconditioner 2970baa948SKarl Rupp by setting data structures and options. 3070baa948SKarl Rupp 3170baa948SKarl Rupp Input Parameter: 3270baa948SKarl Rupp . pc - the preconditioner context 3370baa948SKarl Rupp 3470baa948SKarl Rupp Application Interface Routine: PCSetUp() 3570baa948SKarl Rupp 3670baa948SKarl Rupp Notes: 3770baa948SKarl Rupp The interface routine PCSetUp() is not usually called directly by 3870baa948SKarl Rupp the user, but instead is called by PCApply() if necessary. 3970baa948SKarl Rupp */ 4070baa948SKarl Rupp static PetscErrorCode PCSetUp_ROWSCALINGVIENNACL(PC pc) 4170baa948SKarl Rupp { 4270baa948SKarl Rupp PC_ROWSCALINGVIENNACL *rowscaling = (PC_ROWSCALINGVIENNACL*)pc->data; 4370baa948SKarl Rupp PetscBool flg = PETSC_FALSE; 4470baa948SKarl Rupp PetscErrorCode ierr; 4570baa948SKarl Rupp Mat_SeqAIJViennaCL *gpustruct; 4670baa948SKarl Rupp 4770baa948SKarl Rupp PetscFunctionBegin; 4870baa948SKarl Rupp ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATSEQAIJVIENNACL,&flg);CHKERRQ(ierr); 4970baa948SKarl Rupp if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Currently only handles ViennaCL matrices"); 5070baa948SKarl Rupp if (pc->setupcalled != 0) { 5170baa948SKarl Rupp try { 5270baa948SKarl Rupp delete rowscaling->ROWSCALINGVIENNACL; 5370baa948SKarl Rupp } catch(char *ex) { 5470baa948SKarl Rupp SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex); 5570baa948SKarl Rupp } 5670baa948SKarl Rupp } 5770baa948SKarl Rupp try { 5870baa948SKarl Rupp #if defined(PETSC_USE_COMPLEX) 5970baa948SKarl Rupp gpustruct = NULL; 6070baa948SKarl Rupp SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"No support for complex arithmetic in ROWSCALINGVIENNACL preconditioner"); 6170baa948SKarl Rupp #else 6270baa948SKarl Rupp ierr = MatViennaCLCopyToGPU(pc->pmat);CHKERRQ(ierr); 6370baa948SKarl Rupp gpustruct = (Mat_SeqAIJViennaCL*)(pc->pmat->spptr); 6470baa948SKarl Rupp 6570baa948SKarl Rupp viennacl::linalg::row_scaling_tag pc_tag(1); 6670baa948SKarl Rupp ViennaCLAIJMatrix *mat = (ViennaCLAIJMatrix*)gpustruct->mat; 6770baa948SKarl Rupp rowscaling->ROWSCALINGVIENNACL = new viennacl::linalg::row_scaling<viennacl::compressed_matrix<PetscScalar> >(*mat, pc_tag); 6870baa948SKarl Rupp #endif 6970baa948SKarl Rupp } catch(char *ex) { 7070baa948SKarl Rupp SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex); 7170baa948SKarl Rupp } 7270baa948SKarl Rupp PetscFunctionReturn(0); 7370baa948SKarl Rupp } 7470baa948SKarl Rupp 7570baa948SKarl Rupp /* -------------------------------------------------------------------------- */ 7670baa948SKarl Rupp /* 7770baa948SKarl Rupp PCApply_ROWSCALINGVIENNACL - Applies the ROWSCALINGVIENNACL preconditioner to a vector. 7870baa948SKarl Rupp 7970baa948SKarl Rupp Input Parameters: 8070baa948SKarl Rupp . pc - the preconditioner context 8170baa948SKarl Rupp . x - input vector 8270baa948SKarl Rupp 8370baa948SKarl Rupp Output Parameter: 8470baa948SKarl Rupp . y - output vector 8570baa948SKarl Rupp 8670baa948SKarl Rupp Application Interface Routine: PCApply() 8770baa948SKarl Rupp */ 8870baa948SKarl Rupp static PetscErrorCode PCApply_ROWSCALINGVIENNACL(PC pc,Vec x,Vec y) 8970baa948SKarl Rupp { 9070baa948SKarl Rupp PC_ROWSCALINGVIENNACL *ilu = (PC_ROWSCALINGVIENNACL*)pc->data; 9170baa948SKarl Rupp PetscErrorCode ierr; 9270baa948SKarl Rupp PetscBool flg1,flg2; 9370baa948SKarl Rupp viennacl::vector<PetscScalar> const *xarray=NULL; 9470baa948SKarl Rupp viennacl::vector<PetscScalar> *yarray=NULL; 9570baa948SKarl Rupp 9670baa948SKarl Rupp PetscFunctionBegin; 9770baa948SKarl Rupp /*how to apply a certain fixed number of iterations?*/ 9870baa948SKarl Rupp ierr = PetscObjectTypeCompare((PetscObject)x,VECSEQVIENNACL,&flg1);CHKERRQ(ierr); 9970baa948SKarl Rupp ierr = PetscObjectTypeCompare((PetscObject)y,VECSEQVIENNACL,&flg2);CHKERRQ(ierr); 10070baa948SKarl Rupp if (!(flg1 && flg2)) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP, "Currently only handles ViennaCL vectors"); 10170baa948SKarl Rupp if (!ilu->ROWSCALINGVIENNACL) { 10270baa948SKarl Rupp ierr = PCSetUp_ROWSCALINGVIENNACL(pc);CHKERRQ(ierr); 10370baa948SKarl Rupp } 10470baa948SKarl Rupp ierr = VecSet(y,0.0);CHKERRQ(ierr); 10570baa948SKarl Rupp ierr = VecViennaCLGetArrayRead(x,&xarray);CHKERRQ(ierr); 10670baa948SKarl Rupp ierr = VecViennaCLGetArrayWrite(y,&yarray);CHKERRQ(ierr); 10770baa948SKarl Rupp try { 10870baa948SKarl Rupp #if defined(PETSC_USE_COMPLEX) 10970baa948SKarl Rupp 11070baa948SKarl Rupp #else 11170baa948SKarl Rupp *yarray = *xarray; 11270baa948SKarl Rupp ilu->ROWSCALINGVIENNACL->apply(*yarray); 11370baa948SKarl Rupp #endif 11470baa948SKarl Rupp } catch(char * ex) { 11570baa948SKarl Rupp SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex); 11670baa948SKarl Rupp } 11770baa948SKarl Rupp ierr = VecViennaCLRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 11870baa948SKarl Rupp ierr = VecViennaCLRestoreArrayWrite(y,&yarray);CHKERRQ(ierr); 11970baa948SKarl Rupp ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr); 12070baa948SKarl Rupp PetscFunctionReturn(0); 12170baa948SKarl Rupp } 12270baa948SKarl Rupp /* -------------------------------------------------------------------------- */ 12370baa948SKarl Rupp /* 12470baa948SKarl Rupp PCDestroy_ROWSCALINGVIENNACL - Destroys the private context for the ROWSCALINGVIENNACL preconditioner 12570baa948SKarl Rupp that was created with PCCreate_ROWSCALINGVIENNACL(). 12670baa948SKarl Rupp 12770baa948SKarl Rupp Input Parameter: 12870baa948SKarl Rupp . pc - the preconditioner context 12970baa948SKarl Rupp 13070baa948SKarl Rupp Application Interface Routine: PCDestroy() 13170baa948SKarl Rupp */ 13270baa948SKarl Rupp static PetscErrorCode PCDestroy_ROWSCALINGVIENNACL(PC pc) 13370baa948SKarl Rupp { 13470baa948SKarl Rupp PC_ROWSCALINGVIENNACL *rowscaling = (PC_ROWSCALINGVIENNACL*)pc->data; 13570baa948SKarl Rupp PetscErrorCode ierr; 13670baa948SKarl Rupp 13770baa948SKarl Rupp PetscFunctionBegin; 13870baa948SKarl Rupp if (rowscaling->ROWSCALINGVIENNACL) { 13970baa948SKarl Rupp try { 14070baa948SKarl Rupp delete rowscaling->ROWSCALINGVIENNACL; 14170baa948SKarl Rupp } catch(char *ex) { 14270baa948SKarl Rupp SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex); 14370baa948SKarl Rupp } 14470baa948SKarl Rupp } 14570baa948SKarl Rupp 14670baa948SKarl Rupp /* 14770baa948SKarl Rupp Free the private data structure that was hanging off the PC 14870baa948SKarl Rupp */ 14970baa948SKarl Rupp ierr = PetscFree(pc->data);CHKERRQ(ierr); 15070baa948SKarl Rupp PetscFunctionReturn(0); 15170baa948SKarl Rupp } 15270baa948SKarl Rupp 15370baa948SKarl Rupp static PetscErrorCode PCSetFromOptions_ROWSCALINGVIENNACL(PetscOptionItems *PetscOptionsObject,PC pc) 15470baa948SKarl Rupp { 15570baa948SKarl Rupp PetscErrorCode ierr; 15670baa948SKarl Rupp 15770baa948SKarl Rupp PetscFunctionBegin; 15870baa948SKarl Rupp ierr = PetscOptionsHead(PetscOptionsObject,"ROWSCALINGVIENNACL options");CHKERRQ(ierr); 15970baa948SKarl Rupp ierr = PetscOptionsTail();CHKERRQ(ierr); 16070baa948SKarl Rupp PetscFunctionReturn(0); 16170baa948SKarl Rupp } 16270baa948SKarl Rupp 16370baa948SKarl Rupp /* -------------------------------------------------------------------------- */ 16470baa948SKarl Rupp 16570baa948SKarl Rupp 16670baa948SKarl Rupp /*MC 16770baa948SKarl Rupp PCRowScalingViennaCL - A diagonal preconditioner (scaling rows of matrices by their norm) that can be used via the CUDA, OpenCL, and OpenMP backends of ViennaCL 16870baa948SKarl Rupp 16970baa948SKarl Rupp Level: advanced 17070baa948SKarl Rupp 17170baa948SKarl Rupp .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC 17270baa948SKarl Rupp 17370baa948SKarl Rupp M*/ 17470baa948SKarl Rupp 17570baa948SKarl Rupp PETSC_EXTERN PetscErrorCode PCCreate_ROWSCALINGVIENNACL(PC pc) 17670baa948SKarl Rupp { 17770baa948SKarl Rupp PC_ROWSCALINGVIENNACL *rowscaling; 17870baa948SKarl Rupp PetscErrorCode ierr; 17970baa948SKarl Rupp 18070baa948SKarl Rupp PetscFunctionBegin; 18170baa948SKarl Rupp /* 18270baa948SKarl Rupp Creates the private data structure for this preconditioner and 18370baa948SKarl Rupp attach it to the PC object. 18470baa948SKarl Rupp */ 18570baa948SKarl Rupp ierr = PetscNewLog(pc,&rowscaling);CHKERRQ(ierr); 18670baa948SKarl Rupp pc->data = (void*)rowscaling; 18770baa948SKarl Rupp 18870baa948SKarl Rupp /* 18970baa948SKarl Rupp Initialize the pointer to zero 19070baa948SKarl Rupp Initialize number of v-cycles to default (1) 19170baa948SKarl Rupp */ 19270baa948SKarl Rupp rowscaling->ROWSCALINGVIENNACL = 0; 19370baa948SKarl Rupp 19470baa948SKarl Rupp /* 19570baa948SKarl Rupp Set the pointers for the functions that are provided above. 19670baa948SKarl Rupp Now when the user-level routines (such as PCApply(), PCDestroy(), etc.) 19770baa948SKarl Rupp are called, they will automatically call these functions. Note we 19870baa948SKarl Rupp choose not to provide a couple of these functions since they are 19970baa948SKarl Rupp not needed. 20070baa948SKarl Rupp */ 20170baa948SKarl Rupp pc->ops->apply = PCApply_ROWSCALINGVIENNACL; 20270baa948SKarl Rupp pc->ops->applytranspose = 0; 20370baa948SKarl Rupp pc->ops->setup = PCSetUp_ROWSCALINGVIENNACL; 20470baa948SKarl Rupp pc->ops->destroy = PCDestroy_ROWSCALINGVIENNACL; 20570baa948SKarl Rupp pc->ops->setfromoptions = PCSetFromOptions_ROWSCALINGVIENNACL; 20670baa948SKarl Rupp pc->ops->view = 0; 20770baa948SKarl Rupp pc->ops->applyrichardson = 0; 20870baa948SKarl Rupp pc->ops->applysymmetricleft = 0; 20970baa948SKarl Rupp pc->ops->applysymmetricright = 0; 21070baa948SKarl Rupp PetscFunctionReturn(0); 21170baa948SKarl Rupp } 21270baa948SKarl Rupp 213