xref: /petsc/src/ksp/pc/impls/rowscalingviennacl/rowscalingviennacl.cxx (revision d2522c19e8fa9bca20aaca277941d9a63e71db6a)
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