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