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