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