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