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