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