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