xref: /petsc/src/ksp/pc/impls/parms/parms.c (revision 84df9cb40eca90ea9b18a456fab7a4ecc7f6c1a4)
1 #define PETSCKSP_DLL
2 
3 /*
4    Provides an interface to pARMS.
5    Requires pARMS 3.2 or later.
6 */
7 
8 #include "private/pcimpl.h"          /*I "petscpc.h" I*/
9 
10 #ifdef PETSC_USE_COMPLEX
11 #define DBL_CMPLX
12 #else
13 #define DBL
14 #endif
15 #define USE_MPI
16 #define REAL double
17 #define HAS_BLAS
18 #define FORTRAN_UNDERSCORE
19 #include "parms_sys.h"
20 #undef FLOAT
21 #define FLOAT PetscScalar
22 #include "parms.h"
23 
24 /*
25    Private context (data structure) for the  preconditioner.
26 */
27 typedef struct {
28   parms_Map         map;
29   parms_Mat         A;
30   parms_PC          pc;
31   PCPARMSGlobalType global;
32   PCPARMSLocalType  local;
33   PetscInt          levels, blocksize, maxdim, maxits, lfil[7];
34   PetscBool         nonsymperm, meth[8];
35   PetscReal         solvetol, indtol, droptol[7];
36   PetscScalar       *lvec0, *lvec1;
37 } PC_PARMS;
38 
39 
40 #undef __FUNCT__
41 #define __FUNCT__ "PCSetUp_PARMS"
42 static PetscErrorCode PCSetUp_PARMS(PC pc)
43 {
44   Mat               pmat;
45   PC_PARMS          *parms = (PC_PARMS*)pc->data;
46   const PetscInt    *mapptr0;
47   PetscInt          n, lsize, low, high, i, pos, ncols, length;
48   int               *maptmp, *mapptr, *ia, *ja, *ja1, *im;
49   PetscScalar       *aa, *aa1;
50   const PetscInt    *cols;
51   PetscInt          meth[8];
52   const PetscScalar *values;
53   PetscErrorCode    ierr;
54   MatInfo           matinfo;
55   PetscMPIInt       rank, npro;
56 
57   PetscFunctionBegin;
58 
59   /* Get preconditioner matrix from PETSc and setup pARMS structs */
60   ierr = PCGetOperators(pc,PETSC_NULL,&pmat,PETSC_NULL);CHKERRQ(ierr);
61   MPI_Comm_size(((PetscObject)pmat)->comm,&npro);
62   MPI_Comm_rank(((PetscObject)pmat)->comm,&rank);
63 
64   ierr = MatGetSize(pmat,&n,PETSC_NULL);CHKERRQ(ierr);
65   ierr = PetscMalloc((npro+1)*sizeof(int),&mapptr);CHKERRQ(ierr);
66   ierr = PetscMalloc(n*sizeof(int),&maptmp);CHKERRQ(ierr);
67   ierr = MatGetOwnershipRanges(pmat,&mapptr0);CHKERRQ(ierr);
68   low = mapptr0[rank];
69   high = mapptr0[rank+1];
70   lsize = high - low;
71 
72   for (i=0; i<npro+1; i++)
73     mapptr[i] = mapptr0[i]+1;
74   for (i = 0; i<n; i++)
75     maptmp[i] = i+1;
76 
77   /* if created, destroy the previous map */
78   if(parms->map) {
79     parms_MapFree(&parms->map);
80     parms->map = PETSC_NULL;
81   }
82 
83   /* create pARMS map object */
84   parms_MapCreateFromPtr(&parms->map,(int)n,maptmp,mapptr,((PetscObject)pmat)->comm,1,NONINTERLACED);
85 
86   /* if created, destroy the previous pARMS matrix */
87   if(parms->A) {
88     parms_MatFree(&parms->A);
89     parms->A = PETSC_NULL;
90   }
91 
92   /* create pARMS mat object */
93   parms_MatCreate(&parms->A,parms->map);
94 
95   /* setup and copy csr data structure for pARMS */
96   ierr = PetscMalloc((lsize+1)*sizeof(int),&ia);CHKERRQ(ierr);
97   ia[0] = 1;
98   ierr = MatGetInfo(pmat,MAT_LOCAL,&matinfo);CHKERRQ(ierr);
99   length = matinfo.nz_used;
100   ierr = PetscMalloc(length*sizeof(int),&ja);CHKERRQ(ierr);
101   ierr = PetscMalloc(length*sizeof(PetscScalar),&aa);CHKERRQ(ierr);
102 
103   for (i = low; i<high; i++) {
104     pos = ia[i-low]-1;
105     ierr = MatGetRow(pmat,i,&ncols,&cols,&values);CHKERRQ(ierr);
106     ia[i-low+1] = ia[i-low] + ncols;
107 
108     if (ia[i-low+1] >= length) {
109       length += ncols;
110       ierr = PetscMalloc(length*sizeof(int),&ja1);CHKERRQ(ierr);
111       ierr = PetscMemcpy(ja1,ja,(ia[i-low]-1)*sizeof(int));CHKERRQ(ierr);
112       ierr = PetscFree(ja);CHKERRQ(ierr);
113       ja = ja1;
114       ierr = PetscMalloc(length*sizeof(PetscScalar),&aa1);CHKERRQ(ierr);
115       ierr = PetscMemcpy(aa1,aa,(ia[i-low]-1)*sizeof(PetscScalar));CHKERRQ(ierr);
116       ierr = PetscFree(aa);CHKERRQ(ierr);
117       aa = aa1;
118     }
119     ierr = PetscMemcpy(&ja[pos],cols,ncols*sizeof(int));CHKERRQ(ierr);
120     ierr = PetscMemcpy(&aa[pos],values,ncols*sizeof(PetscScalar));CHKERRQ(ierr);
121     ierr = MatRestoreRow(pmat,i,&ncols,&cols,&values);CHKERRQ(ierr);
122   }
123 
124   /* csr info is for local matrix so initialize im[] locally */
125   ierr = PetscMalloc(lsize*sizeof(int),&im);CHKERRQ(ierr);
126   ierr = PetscMemcpy(im,&maptmp[mapptr[rank]-1],lsize*sizeof(int));CHKERRQ(ierr);
127 
128   /* 1-based indexing */
129   for(i=0; i<ia[lsize]-1; i++)
130     ja[i] = ja[i]+1;
131 
132   /* Now copy csr matrix to parms_mat object */
133   parms_MatSetValues(parms->A,(int)lsize,im,ia,ja,aa,INSERT);
134 
135   /* free memory */
136   ierr = PetscFree(maptmp);CHKERRQ(ierr);
137   ierr = PetscFree(mapptr);CHKERRQ(ierr);
138   ierr = PetscFree(aa);CHKERRQ(ierr);
139   ierr = PetscFree(ja);CHKERRQ(ierr);
140   ierr = PetscFree(ia);CHKERRQ(ierr);
141   ierr = PetscFree(im);CHKERRQ(ierr);
142 
143   /* setup parms matrix */
144   parms_MatSetup(parms->A);
145 
146   /* if created, destroy the previous pARMS pc */
147   if(parms->pc) {
148     parms_PCFree(&parms->pc);
149     parms->pc = PETSC_NULL;
150   }
151 
152   /* Now create pARMS preconditioner object based on A */
153   parms_PCCreate(&parms->pc,parms->A);
154 
155   /* Transfer options from PC to pARMS */
156   switch(parms->global) {
157     case 0: parms_PCSetType(parms->pc, PCRAS); break;
158     case 1: parms_PCSetType(parms->pc, PCSCHUR); break;
159     case 2: parms_PCSetType(parms->pc, PCBJ); break;
160   }
161   switch(parms->local) {
162     case 0: parms_PCSetILUType(parms->pc, PCILU0); break;
163     case 1: parms_PCSetILUType(parms->pc, PCILUK); break;
164     case 2: parms_PCSetILUType(parms->pc, PCILUT); break;
165     case 3: parms_PCSetILUType(parms->pc, PCARMS); break;
166   }
167   parms_PCSetInnerEps(parms->pc, parms->solvetol);
168   parms_PCSetNlevels(parms->pc, parms->levels);
169   parms_PCSetPermType(parms->pc, parms->nonsymperm?1:0);
170   parms_PCSetBsize(parms->pc, parms->blocksize);
171   parms_PCSetTolInd(parms->pc, parms->indtol);
172   parms_PCSetInnerKSize(parms->pc, parms->maxdim);
173   parms_PCSetInnerMaxits(parms->pc, parms->maxits);
174   for(i=0; i<8; i++) meth[i] = parms->meth[i]?1:0;
175   parms_PCSetPermScalOptions(parms->pc, &meth[0], 1);
176   parms_PCSetPermScalOptions(parms->pc, &meth[4], 0);
177   parms_PCSetFill(parms->pc, parms->lfil);
178   parms_PCSetTol(parms->pc, parms->droptol);
179 
180   parms_PCSetup(parms->pc);
181 
182   /* Allocate two auxiliary vector of length lsize */
183   if (parms->lvec0) { ierr = PetscFree(parms->lvec0);CHKERRQ(ierr); }
184   ierr = PetscMalloc(lsize*sizeof(PetscScalar), &parms->lvec0);CHKERRQ(ierr);
185   if (parms->lvec1) { ierr = PetscFree(parms->lvec1);CHKERRQ(ierr); }
186   ierr = PetscMalloc(lsize*sizeof(PetscScalar), &parms->lvec1);CHKERRQ(ierr);
187   PetscFunctionReturn(0);
188 }
189 
190 #undef __FUNCT__
191 #define __FUNCT__ "PCView_PARMS"
192 static PetscErrorCode PCView_PARMS(PC pc,PetscViewer viewer)
193 {
194   PetscErrorCode       ierr;
195   PetscBool            iascii;
196   PC_PARMS             *parms = (PC_PARMS*)pc->data;
197   char                 *str;
198   double               fill_fact;
199 
200   PetscFunctionBegin;
201   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
202   if (iascii) {
203     parms_PCGetName(parms->pc,&str);
204     ierr = PetscViewerASCIIPrintf(viewer,"  global preconditioner: %s\n",str);CHKERRQ(ierr);
205     parms_PCILUGetName(parms->pc,&str);
206     ierr = PetscViewerASCIIPrintf(viewer,"  local preconditioner: %s\n",str);CHKERRQ(ierr);
207     parms_PCGetRatio(parms->pc,&fill_fact);
208     ierr = PetscViewerASCIIPrintf(viewer,"  non-zero elements/original non-zero entries: %-4.2f\n",fill_fact);CHKERRQ(ierr);
209     ierr = PetscViewerASCIIPrintf(viewer,"  Tolerance for local solve: %g\n",parms->solvetol);CHKERRQ(ierr);
210     ierr = PetscViewerASCIIPrintf(viewer,"  Number of levels: %d\n",parms->levels);CHKERRQ(ierr);
211     if (parms->nonsymperm) {
212       ierr = PetscViewerASCIIPrintf(viewer,"  Using nonsymmetric permutation\n");CHKERRQ(ierr);
213     }
214     ierr = PetscViewerASCIIPrintf(viewer,"  Block size: %d\n",parms->blocksize);CHKERRQ(ierr);
215     ierr = PetscViewerASCIIPrintf(viewer,"  Tolerance for independent sets: %g\n",parms->indtol);CHKERRQ(ierr);
216     ierr = PetscViewerASCIIPrintf(viewer,"  Inner Krylov dimension: %d\n",parms->maxdim);CHKERRQ(ierr);
217     ierr = PetscViewerASCIIPrintf(viewer,"  Maximum number of inner iterations: %d\n",parms->maxits);CHKERRQ(ierr);
218     if (parms->meth[0]) {
219       ierr = PetscViewerASCIIPrintf(viewer,"  Using nonsymmetric permutation for interlevel blocks\n");CHKERRQ(ierr);
220     }
221     if (parms->meth[1]) {
222       ierr = PetscViewerASCIIPrintf(viewer,"  Using column permutation for interlevel blocks\n");CHKERRQ(ierr);
223     }
224     if (parms->meth[2]) {
225       ierr = PetscViewerASCIIPrintf(viewer,"  Using row scaling for interlevel blocks\n");CHKERRQ(ierr);
226     }
227     if (parms->meth[3]) {
228       ierr = PetscViewerASCIIPrintf(viewer,"  Using column scaling for interlevel blocks\n");CHKERRQ(ierr);
229     }
230     if (parms->meth[4]) {
231       ierr = PetscViewerASCIIPrintf(viewer,"  Using nonsymmetric permutation for last level blocks\n");CHKERRQ(ierr);
232     }
233     if (parms->meth[5]) {
234       ierr = PetscViewerASCIIPrintf(viewer,"  Using column permutation for last level blocks\n");CHKERRQ(ierr);
235     }
236     if (parms->meth[6]) {
237       ierr = PetscViewerASCIIPrintf(viewer,"  Using row scaling for last level blocks\n");CHKERRQ(ierr);
238     }
239     if (parms->meth[7]) {
240       ierr = PetscViewerASCIIPrintf(viewer,"  Using column scaling for last level blocks\n");CHKERRQ(ierr);
241     }
242     ierr = PetscViewerASCIIPrintf(viewer,"  amount of fill-in for ilut, iluk and arms: %d\n",parms->lfil[0]);CHKERRQ(ierr);
243     ierr = PetscViewerASCIIPrintf(viewer,"  amount of fill-in for schur: %d\n",parms->lfil[4]);CHKERRQ(ierr);
244     ierr = PetscViewerASCIIPrintf(viewer,"  amount of fill-in for ILUT L and U: %d\n",parms->lfil[5]);CHKERRQ(ierr);
245     ierr = PetscViewerASCIIPrintf(viewer,"  drop tolerance for L, U, L^{-1}F and EU^{-1}: %g\n",parms->droptol[0]);CHKERRQ(ierr);
246     ierr = PetscViewerASCIIPrintf(viewer,"  drop tolerance for schur complement at each level: %g\n",parms->droptol[4]);CHKERRQ(ierr);
247     ierr = PetscViewerASCIIPrintf(viewer,"  drop tolerance for ILUT in last level schur complement: %g\n",parms->droptol[5]);CHKERRQ(ierr);
248   }
249 
250   PetscFunctionReturn(0);
251 }
252 
253 #undef __FUNCT__
254 #define __FUNCT__ "PCDestroy_PARMS"
255 static PetscErrorCode PCDestroy_PARMS(PC pc)
256 {
257   PC_PARMS       *parms = (PC_PARMS*)pc->data;
258   PetscErrorCode ierr;
259 
260   PetscFunctionBegin;
261   if(parms->map) {
262     parms_MapFree(&parms->map);
263   }
264    if(parms->A) {
265     parms_MatFree(&parms->A);
266   }
267   if(parms->pc) {
268     parms_PCFree(&parms->pc);
269   }
270   if(parms->lvec0) {
271     ierr = PetscFree(parms->lvec0); CHKERRQ(ierr);
272   }
273   if(parms->lvec1) {
274     ierr = PetscFree(parms->lvec1); CHKERRQ(ierr);
275   }
276   ierr = PetscFree(pc->data);CHKERRQ(ierr);
277 
278   ierr = PetscObjectChangeTypeName((PetscObject)pc,0);CHKERRQ(ierr);
279   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetGlobal_C","",PETSC_NULL);CHKERRQ(ierr);
280   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetLocal_C","",PETSC_NULL);CHKERRQ(ierr);
281   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetSolveTolerances_C","",PETSC_NULL);CHKERRQ(ierr);
282   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetSolveRestart_C","",PETSC_NULL);CHKERRQ(ierr);
283   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetNonsymPerm_C","",PETSC_NULL);CHKERRQ(ierr);
284   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetFill_C","",PETSC_NULL);CHKERRQ(ierr);
285   PetscFunctionReturn(0);
286 }
287 
288 #undef __FUNCT__
289 #define __FUNCT__ "PCSetFromOptions_PARMS"
290 static PetscErrorCode PCSetFromOptions_PARMS(PC pc)
291 {
292   PC_PARMS          *parms = (PC_PARMS*)pc->data;
293   PetscBool         flag;
294   PCPARMSGlobalType global;
295   PCPARMSLocalType  local;
296   PetscErrorCode    ierr;
297 
298   PetscFunctionBegin;
299   ierr = PetscOptionsHead("PARMS Options");CHKERRQ(ierr);
300   ierr = PetscOptionsEnum("-pc_parms_global","Global preconditioner","PCPARMSSetGlobal",PCPARMSGlobalTypes,(PetscEnum)parms->global,(PetscEnum*)&global,&flag);CHKERRQ(ierr);
301   if (flag) { ierr = PCPARMSSetGlobal(pc,global);CHKERRQ(ierr); }
302   ierr = PetscOptionsEnum("-pc_parms_local","Local preconditioner","PCPARMSSetLocal",PCPARMSLocalTypes,(PetscEnum)parms->local,(PetscEnum*)&local,&flag);CHKERRQ(ierr);
303   if (flag) { ierr = PCPARMSSetLocal(pc,local);CHKERRQ(ierr); }
304   ierr = PetscOptionsReal("-pc_parms_solve_tol","Tolerance for local solve","PCPARMSSetSolveTolerances",parms->solvetol,&parms->solvetol,&flag);CHKERRQ(ierr);
305   ierr = PetscOptionsInt("-pc_parms_levels","Number of levels","None",parms->levels,&parms->levels,&flag);CHKERRQ(ierr);
306   ierr = PetscOptionsBool("-pc_parms_nonsymmetric_perm","Use nonsymmetric permutation","PCPARMSSetNonsymPerm",parms->nonsymperm,&parms->nonsymperm,&flag);CHKERRQ(ierr);
307   ierr = PetscOptionsInt("-pc_parms_blocksize","Block size","None",parms->blocksize,&parms->blocksize,&flag);CHKERRQ(ierr);
308   ierr = PetscOptionsReal("-pc_parms_ind_tol","Tolerance for independent sets","None",parms->indtol,&parms->indtol,&flag);CHKERRQ(ierr);
309   ierr = PetscOptionsInt("-pc_parms_max_dim","Inner Krylov dimension","PCPARMSSetSolveRestart",parms->maxdim,&parms->maxdim,&flag);CHKERRQ(ierr);
310   ierr = PetscOptionsInt("-pc_parms_max_it","Maximum number of inner iterations","PCPARMSSetSolveTolerances",parms->maxits,&parms->maxits,&flag);CHKERRQ(ierr);
311   ierr = PetscOptionsBool("-pc_parms_inter_nonsymmetric_perm","nonsymmetric permutation for interlevel blocks","None",parms->meth[0],&parms->meth[0],&flag);CHKERRQ(ierr);
312   ierr = PetscOptionsBool("-pc_parms_inter_column_perm","column permutation for interlevel blocks","None",parms->meth[1],&parms->meth[1],&flag);CHKERRQ(ierr);
313   ierr = PetscOptionsBool("-pc_parms_inter_row_scaling","row scaling for interlevel blocks","None",parms->meth[2],&parms->meth[2],&flag);CHKERRQ(ierr);
314   ierr = PetscOptionsBool("-pc_parms_inter_column_scaling","column scaling for interlevel blocks","None",parms->meth[3],&parms->meth[3],&flag);CHKERRQ(ierr);
315   ierr = PetscOptionsBool("-pc_parms_last_nonsymmetric_perm","nonsymmetric permutation for last level blocks","None",parms->meth[4],&parms->meth[4],&flag);CHKERRQ(ierr);
316   ierr = PetscOptionsBool("-pc_parms_last_column_perm","column permutation for last level blocks","None",parms->meth[5],&parms->meth[5],&flag);CHKERRQ(ierr);
317   ierr = PetscOptionsBool("-pc_parms_last_row_scaling","row scaling for last level blocks","None",parms->meth[6],&parms->meth[6],&flag);CHKERRQ(ierr);
318   ierr = PetscOptionsBool("-pc_parms_last_column_scaling","column scaling for last level blocks","None",parms->meth[7],&parms->meth[7],&flag);CHKERRQ(ierr);
319   ierr = PetscOptionsInt("-pc_parms_lfil_ilu_arms","amount of fill-in for ilut, iluk and arms","PCPARMSSetFill",parms->lfil[0],&parms->lfil[0],&flag);CHKERRQ(ierr);
320   if(flag) parms->lfil[1] = parms->lfil[2] = parms->lfil[3] = parms->lfil[0];
321   ierr = PetscOptionsInt("-pc_parms_lfil_schur","amount of fill-in for schur","PCPARMSSetFill",parms->lfil[4],&parms->lfil[4],&flag);CHKERRQ(ierr);
322   ierr = PetscOptionsInt("-pc_parms_lfil_ilut_L_U","amount of fill-in for ILUT L and U","PCPARMSSetFill",parms->lfil[5],&parms->lfil[5],&flag);CHKERRQ(ierr);
323   if(flag) parms->lfil[6] = parms->lfil[5];
324   ierr = PetscOptionsReal("-pc_parms_droptol_factors","drop tolerance for L, U, L^{-1}F and EU^{-1}","None",parms->droptol[0],&parms->droptol[0],&flag);CHKERRQ(ierr);
325   ierr = PetscOptionsReal("-pc_parms_droptol_schur_compl","drop tolerance for schur complement at each level","None",parms->droptol[4],&parms->droptol[4],&flag);CHKERRQ(ierr);
326   if(flag) parms->droptol[1] = parms->droptol[2] = parms->droptol[3] = parms->droptol[0];
327   ierr = PetscOptionsReal("-pc_parms_droptol_last_schur","drop tolerance for ILUT in last level schur complement","None",parms->droptol[5],&parms->droptol[5],&flag);CHKERRQ(ierr);
328   if(flag) parms->droptol[6] = parms->droptol[5];
329   ierr = PetscOptionsTail();CHKERRQ(ierr);
330   PetscFunctionReturn(0);
331 }
332 
333 #undef __FUNCT__
334 #define __FUNCT__ "PCApply_PARMS"
335 static PetscErrorCode PCApply_PARMS(PC pc,Vec b,Vec x)
336 {
337   PetscErrorCode    ierr;
338   PC_PARMS          *parms = (PC_PARMS*)pc->data;
339   const PetscScalar *b1;
340   PetscScalar       *x1;
341 
342   PetscFunctionBegin;
343   ierr = VecGetArrayRead(b,&b1);CHKERRQ(ierr);
344   ierr = VecGetArray(x,&x1);CHKERRQ(ierr);
345   parms_VecPermAux((PetscScalar*)b1,parms->lvec0,parms->map);
346   parms_PCApply(parms->pc,parms->lvec0,parms->lvec1);
347   parms_VecInvPermAux(parms->lvec1,x1,parms->map);
348   ierr = VecRestoreArrayRead(b,&b1);CHKERRQ(ierr);
349   ierr = VecRestoreArray(x,&x1);CHKERRQ(ierr);
350   PetscFunctionReturn(0);
351 }
352 
353 EXTERN_C_BEGIN
354 #undef __FUNCT__
355 #define __FUNCT__ "PCPARMSSetGlobal_PARMS"
356 PetscErrorCode PCPARMSSetGlobal_PARMS(PC pc,PCPARMSGlobalType type)
357 {
358   PC_PARMS *parms = (PC_PARMS*)pc->data;
359 
360   PetscFunctionBegin;
361   if (type != parms->global) {
362     parms->global = type;
363     pc->setupcalled = 0;
364   }
365   PetscFunctionReturn(0);
366 }
367 EXTERN_C_END
368 
369 #undef __FUNCT__
370 #define __FUNCT__ "PCPARMSSetGlobal"
371 /*@
372    PCPARMSSetGlobal - Sets the global preconditioner to be used in PARMS.
373 
374    Collective on PC
375 
376    Input Parameters:
377 +  pc - the preconditioner context
378 -  type - the global preconditioner type, one of
379 .vb
380      PC_PARMS_GLOBAL_RAS   - Restricted additive Schwarz
381      PC_PARMS_GLOBAL_SCHUR - Schur complement
382      PC_PARMS_GLOBAL_BJ    - Block Jacobi
383 .ve
384 
385    Options Database Keys:
386    -pc_parms_global [ras,schur,bj] - Sets global preconditioner
387 
388    Level: intermediate
389 
390    Notes:
391    See the pARMS function parms_PCSetType for more information.
392 
393 .seealso: PCPARMS, PCPARMSSetLocal()
394 @*/
395 PetscErrorCode PCPARMSSetGlobal(PC pc,PCPARMSGlobalType type)
396 {
397   PetscErrorCode ierr;
398 
399   PetscFunctionBegin;
400   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
401   PetscValidLogicalCollectiveEnum(pc,type,2);
402   ierr = PetscTryMethod(pc,"PCPARMSSetGlobal_C",(PC,PCPARMSGlobalType),(pc,type));CHKERRQ(ierr);
403   PetscFunctionReturn(0);
404 }
405 
406 EXTERN_C_BEGIN
407 #undef __FUNCT__
408 #define __FUNCT__ "PCPARMSSetLocal_PARMS"
409 PetscErrorCode PCPARMSSetLocal_PARMS(PC pc,PCPARMSLocalType type)
410 {
411   PC_PARMS *parms = (PC_PARMS*)pc->data;
412 
413   PetscFunctionBegin;
414   if (type != parms->local) {
415     parms->local = type;
416     pc->setupcalled = 0;
417   }
418   PetscFunctionReturn(0);
419 }
420 EXTERN_C_END
421 
422 #undef __FUNCT__
423 #define __FUNCT__ "PCPARMSSetLocal"
424 /*@
425    PCPARMSSetLocal - Sets the local preconditioner to be used in PARMS.
426 
427    Collective on PC
428 
429    Input Parameters:
430 +  pc - the preconditioner context
431 -  type - the local preconditioner type, one of
432 .vb
433      PC_PARMS_LOCAL_ILU0   - ILU0 preconditioner
434      PC_PARMS_LOCAL_ILUK   - ILU(k) preconditioner
435      PC_PARMS_LOCAL_ILUT   - ILUT preconditioner
436      PC_PARMS_LOCAL_ARMS   - ARMS preconditioner
437 .ve
438 
439    Options Database Keys:
440    -pc_parms_local [ilu0,iluk,ilut,arms] - Sets local preconditioner
441 
442    Level: intermediate
443 
444    Notes:
445    For the ARMS preconditioner, one can use either the symmetric ARMS or the non-symmetric
446    variant (ARMS-ddPQ) by setting the permutation type with PCPARMSSetNonsymPerm().
447 
448    See the pARMS function parms_PCILUSetType for more information.
449 
450 .seealso: PCPARMS, PCPARMSSetGlobal(), PCPARMSSetNonsymPerm()
451 
452 @*/
453 PetscErrorCode PCPARMSSetLocal(PC pc,PCPARMSLocalType type)
454 {
455   PetscErrorCode ierr;
456 
457   PetscFunctionBegin;
458   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
459   PetscValidLogicalCollectiveEnum(pc,type,2);
460   ierr = PetscTryMethod(pc,"PCPARMSSetLocal_C",(PC,PCPARMSLocalType),(pc,type));CHKERRQ(ierr);
461   PetscFunctionReturn(0);
462 }
463 
464 EXTERN_C_BEGIN
465 #undef __FUNCT__
466 #define __FUNCT__ "PCPARMSSetSolveTolerances_PARMS"
467 PetscErrorCode PCPARMSSetSolveTolerances_PARMS(PC pc,PetscReal tol,PetscInt maxits)
468 {
469   PC_PARMS *parms = (PC_PARMS*)pc->data;
470 
471   PetscFunctionBegin;
472 
473   if (tol != parms->solvetol) {
474     parms->solvetol = tol;
475     pc->setupcalled = 0;
476   }
477   if (maxits != parms->maxits) {
478     parms->maxits = maxits;
479     pc->setupcalled = 0;
480   }
481 
482   PetscFunctionReturn(0);
483 }
484 EXTERN_C_END
485 
486 #undef __FUNCT__
487 #define __FUNCT__ "PCPARMSSetSolveTolerances"
488 /*@
489    PCPARMSSetSolveTolerances - Sets the convergence tolerance and the maximum iterations for the
490    inner GMRES solver, when the Schur global preconditioner is used.
491 
492    Collective on PC
493 
494    Input Parameters:
495 +  pc - the preconditioner context
496 .  tol - the convergence tolerance
497 -  maxits - the maximum number of iterations to use
498 
499    Options Database Keys:
500 +  -pc_parms_solve_tol - set the tolerance for local solve
501 -  -pc_parms_max_it - set the maximum number of inner iterations
502 
503    Level: intermediate
504 
505    Notes:
506    See the pARMS functions parms_PCSetInnerEps and parms_PCSetInnerMaxits for more information.
507 
508 .seealso: PCPARMS, PCPARMSSetSolveRestart()
509 @*/
510 PetscErrorCode PCPARMSSetSolveTolerances(PC pc,PetscReal tol,PetscInt maxits)
511 {
512   PetscErrorCode ierr;
513 
514   PetscFunctionBegin;
515   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
516   ierr = PetscTryMethod(pc,"PCPARMSSetSolveTolerances_C",(PC,PetscReal,PetscInt),(pc,tol,maxits));CHKERRQ(ierr);
517   PetscFunctionReturn(0);
518 }
519 
520 EXTERN_C_BEGIN
521 #undef __FUNCT__
522 #define __FUNCT__ "PCPARMSSetSolveRestart_PARMS"
523 PetscErrorCode PCPARMSSetSolveRestart_PARMS(PC pc,PetscInt restart)
524 {
525   PC_PARMS *parms = (PC_PARMS*)pc->data;
526 
527   PetscFunctionBegin;
528 
529   if (restart != parms->maxdim) {
530     parms->maxdim = restart;
531     pc->setupcalled = 0;
532   }
533 
534   PetscFunctionReturn(0);
535 }
536 EXTERN_C_END
537 
538 #undef __FUNCT__
539 #define __FUNCT__ "PCPARMSSetSolveRestart"
540 /*@
541    PCPARMSSetSolveRestart - Sets the number of iterations at which the
542    inner GMRES solver restarts.
543 
544    Collective on PC
545 
546    Input Parameters:
547 +  pc - the preconditioner context
548 -  restart - maximum dimension of the Krylov subspace
549 
550    Options Database Keys:
551 .  -pc_parms_max_dim - sets the inner Krylov dimension
552 
553    Level: intermediate
554 
555    Notes:
556    See the pARMS function parms_PCSetInnerKSize for more information.
557 
558 .seealso: PCPARMS, PCPARMSSetSolveTolerances()
559 @*/
560 PetscErrorCode PCPARMSSetSolveRestart(PC pc,PetscInt restart)
561 {
562   PetscErrorCode ierr;
563 
564   PetscFunctionBegin;
565   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
566   ierr = PetscTryMethod(pc,"PCPARMSSetSolveRestart_C",(PC,PetscInt),(pc,restart));CHKERRQ(ierr);
567   PetscFunctionReturn(0);
568 }
569 
570 EXTERN_C_BEGIN
571 #undef __FUNCT__
572 #define __FUNCT__ "PCPARMSSetNonsymPerm_PARMS"
573 PetscErrorCode PCPARMSSetNonsymPerm_PARMS(PC pc,PetscBool nonsym)
574 {
575   PC_PARMS *parms = (PC_PARMS*)pc->data;
576 
577   PetscFunctionBegin;
578   if ((nonsym && !parms->nonsymperm) || (!nonsym && parms->nonsymperm)) {
579     parms->nonsymperm = nonsym;
580     pc->setupcalled = 0;
581   }
582   PetscFunctionReturn(0);
583 }
584 EXTERN_C_END
585 
586 #undef __FUNCT__
587 #define __FUNCT__ "PCPARMSSetNonsymPerm"
588 /*@
589    PCPARMSSetNonsymPerm - Sets the type of permutation for the ARMS preconditioner: the standard
590    symmetric ARMS or the non-symmetric ARMS (ARMS-ddPQ).
591 
592    Collective on PC
593 
594    Input Parameters:
595 +  pc - the preconditioner context
596 -  nonsym - PETSC_TRUE indicates the non-symmetric ARMS is used;
597             PETSC_FALSE indicates the symmetric ARMS is used
598 
599    Options Database Keys:
600 .  -pc_parms_nonsymmetric_perm - sets the use of nonsymmetric permutation
601 
602    Level: intermediate
603 
604    Notes:
605    See the pARMS function parms_PCSetPermType for more information.
606 
607 .seealso: PCPARMS
608 @*/
609 PetscErrorCode PCPARMSSetNonsymPerm(PC pc,PetscBool nonsym)
610 {
611   PetscErrorCode ierr;
612 
613   PetscFunctionBegin;
614   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
615   ierr = PetscTryMethod(pc,"PCPARMSSetNonsymPerm_C",(PC,PetscBool),(pc,nonsym));CHKERRQ(ierr);
616   PetscFunctionReturn(0);
617 }
618 
619 EXTERN_C_BEGIN
620 #undef __FUNCT__
621 #define __FUNCT__ "PCPARMSSetFill_PARMS"
622 PetscErrorCode PCPARMSSetFill_PARMS(PC pc,PetscInt lfil0,PetscInt lfil1,PetscInt lfil2)
623 {
624   PC_PARMS *parms = (PC_PARMS*)pc->data;
625 
626   PetscFunctionBegin;
627   if (lfil0 != parms->lfil[0] || lfil0 != parms->lfil[1] || lfil0 != parms->lfil[2] || lfil0 != parms->lfil[3]) {
628     parms->lfil[1] = parms->lfil[2] = parms->lfil[3] = parms->lfil[0] = lfil0;
629     pc->setupcalled = 0;
630   }
631   if (lfil1 != parms->lfil[4]) {
632     parms->lfil[4] = lfil1;
633     pc->setupcalled = 0;
634   }
635   if (lfil2 != parms->lfil[5] || lfil2 != parms->lfil[6]) {
636     parms->lfil[5] = parms->lfil[6] = lfil2;
637     pc->setupcalled = 0;
638   }
639   PetscFunctionReturn(0);
640 }
641 EXTERN_C_END
642 
643 #undef __FUNCT__
644 #define __FUNCT__ "PCPARMSSetFill"
645 /*@
646    PCPARMSSetFill - Sets the fill-in parameters for ILUT, ILUK and ARMS preconditioners.
647    Consider the original matrix A = [B F; E C] and the approximate version
648    M = [LB 0; E/UB I]*[UB LB\F; 0 S].
649 
650    Collective on PC
651 
652    Input Parameters:
653 +  pc - the preconditioner context
654 .  fil0 - the level of fill-in kept in LB, UB, E/UB and LB\F
655 .  fil1 - the level of fill-in kept in S
656 -  fil2 - the level of fill-in kept in the L and U parts of the LU factorization of S
657 
658    Options Database Keys:
659 +  -pc_parms_lfil_ilu_arms - set the amount of fill-in for ilut, iluk and arms
660 .  -pc_parms_lfil_schur - set the amount of fill-in for schur
661 -  -pc_parms_lfil_ilut_L_U - set the amount of fill-in for ILUT L and U
662 
663    Level: intermediate
664 
665    Notes:
666    See the pARMS function parms_PCSetFill for more information.
667 
668 .seealso: PCPARMS
669 @*/
670 PetscErrorCode PCPARMSSetFill(PC pc,PetscInt lfil0,PetscInt lfil1,PetscInt lfil2)
671 {
672   PetscErrorCode ierr;
673 
674   PetscFunctionBegin;
675   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
676   ierr = PetscTryMethod(pc,"PCPARMSSetFill_C",(PC,PetscInt,PetscInt,PetscInt),(pc,lfil0,lfil1,lfil2));CHKERRQ(ierr);
677   PetscFunctionReturn(0);
678 }
679 
680 /*MC
681    PCPARMS - Allows the use of the parallel Algebraic Recursive Multilevel Solvers
682       available in the package pARMS
683 
684    Options Database Keys:
685 +  -pc_parms_global - one of ras, schur, bj
686 .  -pc_parms_local - one of ilu0, iluk, ilut, arms
687 .  -pc_parms_solve_tol - set the tolerance for local solve
688 .  -pc_parms_levels - set the number of levels
689 .  -pc_parms_nonsymmetric_perm - set the use of nonsymmetric permutation
690 .  -pc_parms_blocksize - set the block size
691 .  -pc_parms_ind_tol - set the tolerance for independent sets
692 .  -pc_parms_max_dim - set the inner krylov dimension
693 .  -pc_parms_max_it - set the maximum number of inner iterations
694 .  -pc_parms_inter_nonsymmetric_perm - set the use of nonsymmetric permutation for interlevel blocks
695 .  -pc_parms_inter_column_perm - set the use of column permutation for interlevel blocks
696 .  -pc_parms_inter_row_scaling - set the use of row scaling for interlevel blocks
697 .  -pc_parms_inter_column_scaling - set the use of column scaling for interlevel blocks
698 .  -pc_parms_last_nonsymmetric_perm - set the use of nonsymmetric permutation for last level blocks
699 .  -pc_parms_last_column_perm - set the use of column permutation for last level blocks
700 .  -pc_parms_last_row_scaling - set the use of row scaling for last level blocks
701 .  -pc_parms_last_column_scaling - set the use of column scaling for last level blocks
702 .  -pc_parms_lfil_ilu_arms - set the amount of fill-in for ilut, iluk and arms
703 .  -pc_parms_lfil_schur - set the amount of fill-in for schur
704 .  -pc_parms_lfil_ilut_L_U - set the amount of fill-in for ILUT L and U
705 .  -pc_parms_droptol_factors - set the drop tolerance for L, U, L^{-1}F and EU^{-1}
706 .  -pc_parms_droptol_schur_compl - set the drop tolerance for schur complement at each level
707 -  -pc_parms_droptol_last_schur - set the drop tolerance for ILUT in last level schur complement
708 
709    IMPORTANT:
710    Unless configured appropriately, this preconditioner performs an inexact solve
711    as part of the preconditioner application. Therefore, it must be used in combination
712    with flexible variants of iterative solvers, such as KSPFGMRES or KSPCGR.
713 
714    Level: intermediate
715 
716 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
717 M*/
718 
719 EXTERN_C_BEGIN
720 #undef __FUNCT__
721 #define __FUNCT__ "PCCreate_PARMS"
722 PetscErrorCode PCCreate_PARMS(PC pc)
723 {
724   PC_PARMS *parms;
725   PetscErrorCode       ierr;
726 
727   PetscFunctionBegin;
728   ierr = PetscNewLog(pc,PC_PARMS,&parms);CHKERRQ(ierr);
729   parms->map  = 0;
730   parms->A    = 0;
731   parms->pc   = 0;
732   parms->global = PC_PARMS_GLOBAL_RAS;
733   parms->local = PC_PARMS_LOCAL_ARMS;
734   parms->levels = 10;
735   parms->nonsymperm = PETSC_TRUE;
736   parms->blocksize = 250;
737   parms->maxdim = 0;
738   parms->maxits = 0;
739   parms->meth[0] = PETSC_FALSE;
740   parms->meth[1] = PETSC_FALSE;
741   parms->meth[2] = PETSC_FALSE;
742   parms->meth[3] = PETSC_FALSE;
743   parms->meth[4] = PETSC_FALSE;
744   parms->meth[5] = PETSC_FALSE;
745   parms->meth[6] = PETSC_FALSE;
746   parms->meth[7] = PETSC_FALSE;
747   parms->solvetol = 0.01;
748   parms->indtol = 0.4;
749   parms->lfil[0] = parms->lfil[1] = parms->lfil[2] = parms->lfil[3] = 20;
750   parms->lfil[4] = parms->lfil[5] = parms->lfil[6] = 20;
751   parms->droptol[0] = parms->droptol[1] = parms->droptol[2] = parms->droptol[3] = 0.00001;
752   parms->droptol[4] = 0.001;
753   parms->droptol[5] = parms->droptol[6] = 0.001;
754   pc->data                 = parms;
755   pc->ops->destroy         = PCDestroy_PARMS;
756   pc->ops->setfromoptions  = PCSetFromOptions_PARMS;
757   pc->ops->setup           = PCSetUp_PARMS;
758   pc->ops->apply           = PCApply_PARMS;
759   pc->ops->view            = PCView_PARMS;
760   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetGlobal_C","PCPARMSSetGlobal_PARMS",PCPARMSSetGlobal_PARMS);CHKERRQ(ierr);
761   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetLocal_C","PCPARMSSetLocal_PARMS",PCPARMSSetLocal_PARMS);CHKERRQ(ierr);
762   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetSolveTolerances_C","PCPARMSSetSolveTolerances_PARMS",PCPARMSSetSolveTolerances_PARMS);CHKERRQ(ierr);
763   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetSolveRestart_C","PCPARMSSetSolveRestart_PARMS",PCPARMSSetSolveRestart_PARMS);CHKERRQ(ierr);
764   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetNonsymPerm_C","PCPARMSSetNonsymPerm_PARMS",PCPARMSSetNonsymPerm_PARMS);CHKERRQ(ierr);
765   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPARMSSetFill_C","PCPARMSSetFill_PARMS",PCPARMSSetFill_PARMS);CHKERRQ(ierr);
766 
767   PetscFunctionReturn(0);
768 }
769 EXTERN_C_END
770