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