Actual source code: parms.c

  1: #define PETSCKSP_DLL

  3: /*
  4:    Provides an interface to pARMS.
  5:    Requires pARMS 3.2 or later.
  6: */

  8: #include <petsc/private/pcimpl.h>

 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>

 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;

 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:   MatInfo            matinfo;
 51:   PetscMPIInt        rank, npro;

 53:   /* Get preconditioner matrix from PETSc and setup pARMS structs */
 54:   PCGetOperators(pc, NULL, &pmat);
 55:   MPI_Comm_size(PetscObjectComm((PetscObject)pmat), &npro);
 56:   MPI_Comm_rank(PetscObjectComm((PetscObject)pmat), &rank);

 58:   MatGetSize(pmat, &n, NULL);
 59:   PetscMalloc1(npro + 1, &mapptr);
 60:   PetscMalloc1(n, &maptmp);
 61:   MatGetOwnershipRanges(pmat, &mapptr0);
 62:   low   = mapptr0[rank];
 63:   high  = mapptr0[rank + 1];
 64:   lsize = high - low;

 66:   for (i = 0; i < npro + 1; i++) mapptr[i] = mapptr0[i] + 1;
 67:   for (i = 0; i < n; i++) maptmp[i] = i + 1;

 69:   /* if created, destroy the previous map */
 70:   if (parms->map) {
 71:     parms_MapFree(&parms->map);
 72:     parms->map = NULL;
 73:   }

 75:   /* create pARMS map object */
 76:   parms_MapCreateFromPtr(&parms->map, (int)n, maptmp, mapptr, PetscObjectComm((PetscObject)pmat), 1, NONINTERLACED);

 78:   /* if created, destroy the previous pARMS matrix */
 79:   if (parms->A) {
 80:     parms_MatFree(&parms->A);
 81:     parms->A = NULL;
 82:   }

 84:   /* create pARMS mat object */
 85:   parms_MatCreate(&parms->A, parms->map);

 87:   /* setup and copy csr data structure for pARMS */
 88:   PetscMalloc1(lsize + 1, &ia);
 89:   ia[0] = 1;
 90:   MatGetInfo(pmat, MAT_LOCAL, &matinfo);
 91:   length = matinfo.nz_used;
 92:   PetscMalloc1(length, &ja);
 93:   PetscMalloc1(length, &aa);

 95:   for (i = low; i < high; i++) {
 96:     pos = ia[i - low] - 1;
 97:     MatGetRow(pmat, i, &ncols, &cols, &values);
 98:     ia[i - low + 1] = ia[i - low] + ncols;

100:     if (ia[i - low + 1] >= length) {
101:       length += ncols;
102:       PetscMalloc1(length, &ja1);
103:       PetscArraycpy(ja1, ja, ia[i - low] - 1);
104:       PetscFree(ja);
105:       ja = ja1;
106:       PetscMalloc1(length, &aa1);
107:       PetscArraycpy(aa1, aa, ia[i - low] - 1);
108:       PetscFree(aa);
109:       aa = aa1;
110:     }
111:     PetscArraycpy(&ja[pos], cols, ncols);
112:     PetscArraycpy(&aa[pos], values, ncols);
113:     MatRestoreRow(pmat, i, &ncols, &cols, &values);
114:   }

116:   /* csr info is for local matrix so initialize im[] locally */
117:   PetscMalloc1(lsize, &im);
118:   PetscArraycpy(im, &maptmp[mapptr[rank] - 1], lsize);

120:   /* 1-based indexing */
121:   for (i = 0; i < ia[lsize] - 1; i++) ja[i] = ja[i] + 1;

123:   /* Now copy csr matrix to parms_mat object */
124:   parms_MatSetValues(parms->A, (int)lsize, im, ia, ja, aa, INSERT);

126:   /* free memory */
127:   PetscFree(maptmp);
128:   PetscFree(mapptr);
129:   PetscFree(aa);
130:   PetscFree(ja);
131:   PetscFree(ia);
132:   PetscFree(im);

134:   /* setup parms matrix */
135:   parms_MatSetup(parms->A);

137:   /* if created, destroy the previous pARMS pc */
138:   if (parms->pc) {
139:     parms_PCFree(&parms->pc);
140:     parms->pc = NULL;
141:   }

143:   /* Now create pARMS preconditioner object based on A */
144:   parms_PCCreate(&parms->pc, parms->A);

146:   /* Transfer options from PC to pARMS */
147:   switch (parms->global) {
148:   case 0:
149:     parms_PCSetType(parms->pc, PCRAS);
150:     break;
151:   case 1:
152:     parms_PCSetType(parms->pc, PCSCHUR);
153:     break;
154:   case 2:
155:     parms_PCSetType(parms->pc, PCBJ);
156:     break;
157:   }
158:   switch (parms->local) {
159:   case 0:
160:     parms_PCSetILUType(parms->pc, PCILU0);
161:     break;
162:   case 1:
163:     parms_PCSetILUType(parms->pc, PCILUK);
164:     break;
165:   case 2:
166:     parms_PCSetILUType(parms->pc, PCILUT);
167:     break;
168:   case 3:
169:     parms_PCSetILUType(parms->pc, PCARMS);
170:     break;
171:   }
172:   parms_PCSetInnerEps(parms->pc, parms->solvetol);
173:   parms_PCSetNlevels(parms->pc, parms->levels);
174:   parms_PCSetPermType(parms->pc, parms->nonsymperm ? 1 : 0);
175:   parms_PCSetBsize(parms->pc, parms->blocksize);
176:   parms_PCSetTolInd(parms->pc, parms->indtol);
177:   parms_PCSetInnerKSize(parms->pc, parms->maxdim);
178:   parms_PCSetInnerMaxits(parms->pc, parms->maxits);
179:   for (i = 0; i < 8; i++) meth[i] = parms->meth[i] ? 1 : 0;
180:   parms_PCSetPermScalOptions(parms->pc, &meth[0], 1);
181:   parms_PCSetPermScalOptions(parms->pc, &meth[4], 0);
182:   parms_PCSetFill(parms->pc, parms->lfil);
183:   parms_PCSetTol(parms->pc, parms->droptol);

185:   parms_PCSetup(parms->pc);

187:   /* Allocate two auxiliary vector of length lsize */
188:   if (parms->lvec0) PetscFree(parms->lvec0);
189:   PetscMalloc1(lsize, &parms->lvec0);
190:   if (parms->lvec1) PetscFree(parms->lvec1);
191:   PetscMalloc1(lsize, &parms->lvec1);
192:   return 0;
193: }

195: static PetscErrorCode PCView_PARMS(PC pc, PetscViewer viewer)
196: {
197:   PetscBool iascii;
198:   PC_PARMS *parms = (PC_PARMS *)pc->data;
199:   char     *str;
200:   double    fill_fact;

202:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
203:   if (iascii) {
204:     parms_PCGetName(parms->pc, &str);
205:     PetscViewerASCIIPrintf(viewer, "  global preconditioner: %s\n", str);
206:     parms_PCILUGetName(parms->pc, &str);
207:     PetscViewerASCIIPrintf(viewer, "  local preconditioner: %s\n", str);
208:     parms_PCGetRatio(parms->pc, &fill_fact);
209:     PetscViewerASCIIPrintf(viewer, "  non-zero elements/original non-zero entries: %-4.2f\n", fill_fact);
210:     PetscViewerASCIIPrintf(viewer, "  Tolerance for local solve: %g\n", parms->solvetol);
211:     PetscViewerASCIIPrintf(viewer, "  Number of levels: %d\n", parms->levels);
212:     if (parms->nonsymperm) PetscViewerASCIIPrintf(viewer, "  Using nonsymmetric permutation\n");
213:     PetscViewerASCIIPrintf(viewer, "  Block size: %d\n", parms->blocksize);
214:     PetscViewerASCIIPrintf(viewer, "  Tolerance for independent sets: %g\n", parms->indtol);
215:     PetscViewerASCIIPrintf(viewer, "  Inner Krylov dimension: %d\n", parms->maxdim);
216:     PetscViewerASCIIPrintf(viewer, "  Maximum number of inner iterations: %d\n", parms->maxits);
217:     if (parms->meth[0]) PetscViewerASCIIPrintf(viewer, "  Using nonsymmetric permutation for interlevel blocks\n");
218:     if (parms->meth[1]) PetscViewerASCIIPrintf(viewer, "  Using column permutation for interlevel blocks\n");
219:     if (parms->meth[2]) PetscViewerASCIIPrintf(viewer, "  Using row scaling for interlevel blocks\n");
220:     if (parms->meth[3]) PetscViewerASCIIPrintf(viewer, "  Using column scaling for interlevel blocks\n");
221:     if (parms->meth[4]) PetscViewerASCIIPrintf(viewer, "  Using nonsymmetric permutation for last level blocks\n");
222:     if (parms->meth[5]) PetscViewerASCIIPrintf(viewer, "  Using column permutation for last level blocks\n");
223:     if (parms->meth[6]) PetscViewerASCIIPrintf(viewer, "  Using row scaling for last level blocks\n");
224:     if (parms->meth[7]) PetscViewerASCIIPrintf(viewer, "  Using column scaling for last level blocks\n");
225:     PetscViewerASCIIPrintf(viewer, "  amount of fill-in for ilut, iluk and arms: %d\n", parms->lfil[0]);
226:     PetscViewerASCIIPrintf(viewer, "  amount of fill-in for schur: %d\n", parms->lfil[4]);
227:     PetscViewerASCIIPrintf(viewer, "  amount of fill-in for ILUT L and U: %d\n", parms->lfil[5]);
228:     PetscViewerASCIIPrintf(viewer, "  drop tolerance for L, U, L^{-1}F and EU^{-1}: %g\n", parms->droptol[0]);
229:     PetscViewerASCIIPrintf(viewer, "  drop tolerance for schur complement at each level: %g\n", parms->droptol[4]);
230:     PetscViewerASCIIPrintf(viewer, "  drop tolerance for ILUT in last level schur complement: %g\n", parms->droptol[5]);
231:   }
232:   return 0;
233: }

235: static PetscErrorCode PCDestroy_PARMS(PC pc)
236: {
237:   PC_PARMS *parms = (PC_PARMS *)pc->data;

239:   if (parms->map) parms_MapFree(&parms->map);
240:   if (parms->A) parms_MatFree(&parms->A);
241:   if (parms->pc) parms_PCFree(&parms->pc);
242:   if (parms->lvec0) PetscFree(parms->lvec0);
243:   if (parms->lvec1) PetscFree(parms->lvec1);
244:   PetscFree(pc->data);

246:   PetscObjectChangeTypeName((PetscObject)pc, 0);
247:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetGlobal_C", NULL);
248:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetLocal_C", NULL);
249:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetSolveTolerances_C", NULL);
250:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetSolveRestart_C", NULL);
251:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetNonsymPerm_C", NULL);
252:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetFill_C", NULL);
253:   return 0;
254: }

256: static PetscErrorCode PCSetFromOptions_PARMS(PC pc, PetscOptionItems *PetscOptionsObject)
257: {
258:   PC_PARMS         *parms = (PC_PARMS *)pc->data;
259:   PetscBool         flag;
260:   PCPARMSGlobalType global;
261:   PCPARMSLocalType  local;

263:   PetscOptionsHeadBegin(PetscOptionsObject, "PARMS Options");
264:   PetscOptionsEnum("-pc_parms_global", "Global preconditioner", "PCPARMSSetGlobal", PCPARMSGlobalTypes, (PetscEnum)parms->global, (PetscEnum *)&global, &flag);
265:   if (flag) PCPARMSSetGlobal(pc, global);
266:   PetscOptionsEnum("-pc_parms_local", "Local preconditioner", "PCPARMSSetLocal", PCPARMSLocalTypes, (PetscEnum)parms->local, (PetscEnum *)&local, &flag);
267:   if (flag) PCPARMSSetLocal(pc, local);
268:   PetscOptionsReal("-pc_parms_solve_tol", "Tolerance for local solve", "PCPARMSSetSolveTolerances", parms->solvetol, &parms->solvetol, NULL);
269:   PetscOptionsInt("-pc_parms_levels", "Number of levels", "None", parms->levels, &parms->levels, NULL);
270:   PetscOptionsBool("-pc_parms_nonsymmetric_perm", "Use nonsymmetric permutation", "PCPARMSSetNonsymPerm", parms->nonsymperm, &parms->nonsymperm, NULL);
271:   PetscOptionsInt("-pc_parms_blocksize", "Block size", "None", parms->blocksize, &parms->blocksize, NULL);
272:   PetscOptionsReal("-pc_parms_ind_tol", "Tolerance for independent sets", "None", parms->indtol, &parms->indtol, NULL);
273:   PetscOptionsInt("-pc_parms_max_dim", "Inner Krylov dimension", "PCPARMSSetSolveRestart", parms->maxdim, &parms->maxdim, NULL);
274:   PetscOptionsInt("-pc_parms_max_it", "Maximum number of inner iterations", "PCPARMSSetSolveTolerances", parms->maxits, &parms->maxits, NULL);
275:   PetscOptionsBool("-pc_parms_inter_nonsymmetric_perm", "nonsymmetric permutation for interlevel blocks", "None", parms->meth[0], &parms->meth[0], NULL);
276:   PetscOptionsBool("-pc_parms_inter_column_perm", "column permutation for interlevel blocks", "None", parms->meth[1], &parms->meth[1], NULL);
277:   PetscOptionsBool("-pc_parms_inter_row_scaling", "row scaling for interlevel blocks", "None", parms->meth[2], &parms->meth[2], NULL);
278:   PetscOptionsBool("-pc_parms_inter_column_scaling", "column scaling for interlevel blocks", "None", parms->meth[3], &parms->meth[3], NULL);
279:   PetscOptionsBool("-pc_parms_last_nonsymmetric_perm", "nonsymmetric permutation for last level blocks", "None", parms->meth[4], &parms->meth[4], NULL);
280:   PetscOptionsBool("-pc_parms_last_column_perm", "column permutation for last level blocks", "None", parms->meth[5], &parms->meth[5], NULL);
281:   PetscOptionsBool("-pc_parms_last_row_scaling", "row scaling for last level blocks", "None", parms->meth[6], &parms->meth[6], NULL);
282:   PetscOptionsBool("-pc_parms_last_column_scaling", "column scaling for last level blocks", "None", parms->meth[7], &parms->meth[7], NULL);
283:   PetscOptionsInt("-pc_parms_lfil_ilu_arms", "amount of fill-in for ilut, iluk and arms", "PCPARMSSetFill", parms->lfil[0], &parms->lfil[0], &flag);
284:   if (flag) parms->lfil[1] = parms->lfil[2] = parms->lfil[3] = parms->lfil[0];
285:   PetscOptionsInt("-pc_parms_lfil_schur", "amount of fill-in for schur", "PCPARMSSetFill", parms->lfil[4], &parms->lfil[4], NULL);
286:   PetscOptionsInt("-pc_parms_lfil_ilut_L_U", "amount of fill-in for ILUT L and U", "PCPARMSSetFill", parms->lfil[5], &parms->lfil[5], &flag);
287:   if (flag) parms->lfil[6] = parms->lfil[5];
288:   PetscOptionsReal("-pc_parms_droptol_factors", "drop tolerance for L, U, L^{-1}F and EU^{-1}", "None", parms->droptol[0], &parms->droptol[0], NULL);
289:   PetscOptionsReal("-pc_parms_droptol_schur_compl", "drop tolerance for schur complement at each level", "None", parms->droptol[4], &parms->droptol[4], &flag);
290:   if (flag) parms->droptol[1] = parms->droptol[2] = parms->droptol[3] = parms->droptol[0];
291:   PetscOptionsReal("-pc_parms_droptol_last_schur", "drop tolerance for ILUT in last level schur complement", "None", parms->droptol[5], &parms->droptol[5], &flag);
292:   if (flag) parms->droptol[6] = parms->droptol[5];
293:   PetscOptionsHeadEnd();
294:   return 0;
295: }

297: static PetscErrorCode PCApply_PARMS(PC pc, Vec b, Vec x)
298: {
299:   PC_PARMS          *parms = (PC_PARMS *)pc->data;
300:   const PetscScalar *b1;
301:   PetscScalar       *x1;

303:   VecGetArrayRead(b, &b1);
304:   VecGetArray(x, &x1);
305:   parms_VecPermAux((PetscScalar *)b1, parms->lvec0, parms->map);
306:   parms_PCApply(parms->pc, parms->lvec0, parms->lvec1);
307:   parms_VecInvPermAux(parms->lvec1, x1, parms->map);
308:   VecRestoreArrayRead(b, &b1);
309:   VecRestoreArray(x, &x1);
310:   return 0;
311: }

313: static PetscErrorCode PCPARMSSetGlobal_PARMS(PC pc, PCPARMSGlobalType type)
314: {
315:   PC_PARMS *parms = (PC_PARMS *)pc->data;

317:   if (type != parms->global) {
318:     parms->global   = type;
319:     pc->setupcalled = 0;
320:   }
321:   return 0;
322: }

324: /*@
325:    PCPARMSSetGlobal - Sets the global preconditioner to be used in `PCPARMS`.

327:    Collective

329:    Input Parameters:
330: +  pc - the preconditioner context
331: -  type - the global preconditioner type, one of
332: .vb
333:      PC_PARMS_GLOBAL_RAS   - Restricted additive Schwarz
334:      PC_PARMS_GLOBAL_SCHUR - Schur complement
335:      PC_PARMS_GLOBAL_BJ    - Block Jacobi
336: .ve

338:    Options Database Key:
339: .   -pc_parms_global [ras,schur,bj] - Sets global preconditioner

341:    Level: intermediate

343:    Note:
344:    See the pARMS function `parms_PCSetType()` for more information.

346: .seealso: `PCPARMS`, `PCPARMSSetLocal()`
347: @*/
348: PetscErrorCode PCPARMSSetGlobal(PC pc, PCPARMSGlobalType type)
349: {
352:   PetscTryMethod(pc, "PCPARMSSetGlobal_C", (PC, PCPARMSGlobalType), (pc, type));
353:   return 0;
354: }

356: static PetscErrorCode PCPARMSSetLocal_PARMS(PC pc, PCPARMSLocalType type)
357: {
358:   PC_PARMS *parms = (PC_PARMS *)pc->data;

360:   if (type != parms->local) {
361:     parms->local    = type;
362:     pc->setupcalled = 0;
363:   }
364:   return 0;
365: }

367: /*@
368:    PCPARMSSetLocal - Sets the local preconditioner to be used in `PCPARMS`.

370:    Collective

372:    Input Parameters:
373: +  pc - the preconditioner context
374: -  type - the local preconditioner type, one of
375: .vb
376:      PC_PARMS_LOCAL_ILU0   - ILU0 preconditioner
377:      PC_PARMS_LOCAL_ILUK   - ILU(k) preconditioner
378:      PC_PARMS_LOCAL_ILUT   - ILUT preconditioner
379:      PC_PARMS_LOCAL_ARMS   - ARMS preconditioner
380: .ve

382:    Options Database Keys:
383:    -pc_parms_local [ilu0,iluk,ilut,arms] - Sets local preconditioner

385:    Level: intermediate

387:    Notes:
388:    For the ARMS preconditioner, one can use either the symmetric ARMS or the non-symmetric
389:    variant (ARMS-ddPQ) by setting the permutation type with PCPARMSSetNonsymPerm().

391:    See the pARMS function `parms_PCILUSetType()` for more information.

393: .seealso: `PCPARMS`, `PCPARMSSetGlobal()`, `PCPARMSSetNonsymPerm()`

395: @*/
396: PetscErrorCode PCPARMSSetLocal(PC pc, PCPARMSLocalType type)
397: {
400:   PetscTryMethod(pc, "PCPARMSSetLocal_C", (PC, PCPARMSLocalType), (pc, type));
401:   return 0;
402: }

404: static PetscErrorCode PCPARMSSetSolveTolerances_PARMS(PC pc, PetscReal tol, PetscInt maxits)
405: {
406:   PC_PARMS *parms = (PC_PARMS *)pc->data;

408:   if (tol != parms->solvetol) {
409:     parms->solvetol = tol;
410:     pc->setupcalled = 0;
411:   }
412:   if (maxits != parms->maxits) {
413:     parms->maxits   = maxits;
414:     pc->setupcalled = 0;
415:   }
416:   return 0;
417: }

419: /*@
420:    PCPARMSSetSolveTolerances - Sets the convergence tolerance and the maximum iterations for the
421:    inner GMRES solver, when the Schur global preconditioner is used.

423:    Collective

425:    Input Parameters:
426: +  pc - the preconditioner context
427: .  tol - the convergence tolerance
428: -  maxits - the maximum number of iterations to use

430:    Options Database Keys:
431: +  -pc_parms_solve_tol - set the tolerance for local solve
432: -  -pc_parms_max_it - set the maximum number of inner iterations

434:    Level: intermediate

436:    Note:
437:    See the pARMS functions `parms_PCSetInnerEps()` and `parms_PCSetInnerMaxits()` for more information.

439: .seealso: `PCPARMS`, `PCPARMSSetSolveRestart()`
440: @*/
441: PetscErrorCode PCPARMSSetSolveTolerances(PC pc, PetscReal tol, PetscInt maxits)
442: {
444:   PetscTryMethod(pc, "PCPARMSSetSolveTolerances_C", (PC, PetscReal, PetscInt), (pc, tol, maxits));
445:   return 0;
446: }

448: static PetscErrorCode PCPARMSSetSolveRestart_PARMS(PC pc, PetscInt restart)
449: {
450:   PC_PARMS *parms = (PC_PARMS *)pc->data;

452:   if (restart != parms->maxdim) {
453:     parms->maxdim   = restart;
454:     pc->setupcalled = 0;
455:   }
456:   return 0;
457: }

459: /*@
460:    PCPARMSSetSolveRestart - Sets the number of iterations at which the
461:    inner GMRES solver restarts.

463:    Collective

465:    Input Parameters:
466: +  pc - the preconditioner context
467: -  restart - maximum dimension of the Krylov subspace

469:    Options Database Key:
470: .  -pc_parms_max_dim - sets the inner Krylov dimension

472:    Level: intermediate

474:    Note:
475:    See the pARMS function parms_PCSetInnerKSize for more information.

477: .seealso: `PCPARMS`, `PCPARMSSetSolveTolerances()`
478: @*/
479: PetscErrorCode PCPARMSSetSolveRestart(PC pc, PetscInt restart)
480: {
482:   PetscTryMethod(pc, "PCPARMSSetSolveRestart_C", (PC, PetscInt), (pc, restart));
483:   return 0;
484: }

486: static PetscErrorCode PCPARMSSetNonsymPerm_PARMS(PC pc, PetscBool nonsym)
487: {
488:   PC_PARMS *parms = (PC_PARMS *)pc->data;

490:   if ((nonsym && !parms->nonsymperm) || (!nonsym && parms->nonsymperm)) {
491:     parms->nonsymperm = nonsym;
492:     pc->setupcalled   = 0;
493:   }
494:   return 0;
495: }

497: /*@
498:    PCPARMSSetNonsymPerm - Sets the type of permutation for the ARMS preconditioner: the standard
499:    symmetric ARMS or the non-symmetric ARMS (ARMS-ddPQ).

501:    Collective

503:    Input Parameters:
504: +  pc - the preconditioner context
505: -  nonsym - `PETSC_TRUE` indicates the non-symmetric ARMS is used;
506:             `PETSC_FALSE` indicates the symmetric ARMS is used

508:    Options Database Key:
509: .  -pc_parms_nonsymmetric_perm - sets the use of nonsymmetric permutation

511:    Level: intermediate

513:    Note:
514:    See the pARMS function `parms_PCSetPermType()` for more information.

516: .seealso: `PCPARMS`
517: @*/
518: PetscErrorCode PCPARMSSetNonsymPerm(PC pc, PetscBool nonsym)
519: {
521:   PetscTryMethod(pc, "PCPARMSSetNonsymPerm_C", (PC, PetscBool), (pc, nonsym));
522:   return 0;
523: }

525: static PetscErrorCode PCPARMSSetFill_PARMS(PC pc, PetscInt lfil0, PetscInt lfil1, PetscInt lfil2)
526: {
527:   PC_PARMS *parms = (PC_PARMS *)pc->data;

529:   if (lfil0 != parms->lfil[0] || lfil0 != parms->lfil[1] || lfil0 != parms->lfil[2] || lfil0 != parms->lfil[3]) {
530:     parms->lfil[1] = parms->lfil[2] = parms->lfil[3] = parms->lfil[0] = lfil0;
531:     pc->setupcalled                                                   = 0;
532:   }
533:   if (lfil1 != parms->lfil[4]) {
534:     parms->lfil[4]  = lfil1;
535:     pc->setupcalled = 0;
536:   }
537:   if (lfil2 != parms->lfil[5] || lfil2 != parms->lfil[6]) {
538:     parms->lfil[5] = parms->lfil[6] = lfil2;
539:     pc->setupcalled                 = 0;
540:   }
541:   return 0;
542: }

544: /*@
545:    PCPARMSSetFill - Sets the fill-in parameters for ILUT, ILUK and ARMS preconditioners.
546:    Consider the original matrix A = [B F; E C] and the approximate version
547:    M = [LB 0; E/UB I]*[UB LB\F; 0 S].

549:    Collective

551:    Input Parameters:
552: +  pc - the preconditioner context
553: .  fil0 - the level of fill-in kept in LB, UB, E/UB and LB\F
554: .  fil1 - the level of fill-in kept in S
555: -  fil2 - the level of fill-in kept in the L and U parts of the LU factorization of S

557:    Options Database Keys:
558: +  -pc_parms_lfil_ilu_arms - set the amount of fill-in for ilut, iluk and arms
559: .  -pc_parms_lfil_schur - set the amount of fill-in for schur
560: -  -pc_parms_lfil_ilut_L_U - set the amount of fill-in for ILUT L and U

562:    Level: intermediate

564:    Note:
565:    See the pARMS function `parms_PCSetFill()` for more information.

567: .seealso: `PCPARMS`
568: @*/
569: PetscErrorCode PCPARMSSetFill(PC pc, PetscInt lfil0, PetscInt lfil1, PetscInt lfil2)
570: {
572:   PetscTryMethod(pc, "PCPARMSSetFill_C", (PC, PetscInt, PetscInt, PetscInt), (pc, lfil0, lfil1, lfil2));
573:   return 0;
574: }

576: /*MC
577:    PCPARMS - Allows the use of the parallel Algebraic Recursive Multilevel Solvers
578:       available in the package pARMS

580:    Options Database Keys:
581: +  -pc_parms_global - one of ras, schur, bj
582: .  -pc_parms_local - one of ilu0, iluk, ilut, arms
583: .  -pc_parms_solve_tol - set the tolerance for local solve
584: .  -pc_parms_levels - set the number of levels
585: .  -pc_parms_nonsymmetric_perm - set the use of nonsymmetric permutation
586: .  -pc_parms_blocksize - set the block size
587: .  -pc_parms_ind_tol - set the tolerance for independent sets
588: .  -pc_parms_max_dim - set the inner krylov dimension
589: .  -pc_parms_max_it - set the maximum number of inner iterations
590: .  -pc_parms_inter_nonsymmetric_perm - set the use of nonsymmetric permutation for interlevel blocks
591: .  -pc_parms_inter_column_perm - set the use of column permutation for interlevel blocks
592: .  -pc_parms_inter_row_scaling - set the use of row scaling for interlevel blocks
593: .  -pc_parms_inter_column_scaling - set the use of column scaling for interlevel blocks
594: .  -pc_parms_last_nonsymmetric_perm - set the use of nonsymmetric permutation for last level blocks
595: .  -pc_parms_last_column_perm - set the use of column permutation for last level blocks
596: .  -pc_parms_last_row_scaling - set the use of row scaling for last level blocks
597: .  -pc_parms_last_column_scaling - set the use of column scaling for last level blocks
598: .  -pc_parms_lfil_ilu_arms - set the amount of fill-in for ilut, iluk and arms
599: .  -pc_parms_lfil_schur - set the amount of fill-in for schur
600: .  -pc_parms_lfil_ilut_L_U - set the amount of fill-in for ILUT L and U
601: .  -pc_parms_droptol_factors - set the drop tolerance for L, U, L^{-1}F and EU^{-1}
602: .  -pc_parms_droptol_schur_compl - set the drop tolerance for schur complement at each level
603: -  -pc_parms_droptol_last_schur - set the drop tolerance for ILUT in last level schur complement

605:    Note:
606:    Unless configured appropriately, this preconditioner performs an inexact solve
607:    as part of the preconditioner application. Therefore, it must be used in combination
608:    with flexible variants of iterative solvers, such as `KSPFGMRES` or `KSPGCR`.

610:    Level: intermediate

612: .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCMG`, `PCGAMG`, `PCHYPRE`, `PCPARMSSetGlobal()`,
613:           `PCPARMSSetLocal()`, `PCPARMSSetSolveTolerances()`, `PCPARMSSetSolveRestart()`, `PCPARMSSetNonsymPerm()`,
614:           `PCPARMSSetFill()`
615: M*/

617: PETSC_EXTERN PetscErrorCode PCCreate_PARMS(PC pc)
618: {
619:   PC_PARMS *parms;

621:   PetscNew(&parms);

623:   parms->map        = 0;
624:   parms->A          = 0;
625:   parms->pc         = 0;
626:   parms->global     = PC_PARMS_GLOBAL_RAS;
627:   parms->local      = PC_PARMS_LOCAL_ARMS;
628:   parms->levels     = 10;
629:   parms->nonsymperm = PETSC_TRUE;
630:   parms->blocksize  = 250;
631:   parms->maxdim     = 0;
632:   parms->maxits     = 0;
633:   parms->meth[0]    = PETSC_FALSE;
634:   parms->meth[1]    = PETSC_FALSE;
635:   parms->meth[2]    = PETSC_FALSE;
636:   parms->meth[3]    = PETSC_FALSE;
637:   parms->meth[4]    = PETSC_FALSE;
638:   parms->meth[5]    = PETSC_FALSE;
639:   parms->meth[6]    = PETSC_FALSE;
640:   parms->meth[7]    = PETSC_FALSE;
641:   parms->solvetol   = 0.01;
642:   parms->indtol     = 0.4;
643:   parms->lfil[0] = parms->lfil[1] = parms->lfil[2] = parms->lfil[3] = 20;
644:   parms->lfil[4] = parms->lfil[5] = parms->lfil[6] = 20;
645:   parms->droptol[0] = parms->droptol[1] = parms->droptol[2] = parms->droptol[3] = 0.00001;
646:   parms->droptol[4]                                                             = 0.001;
647:   parms->droptol[5] = parms->droptol[6] = 0.001;

649:   pc->data                = parms;
650:   pc->ops->destroy        = PCDestroy_PARMS;
651:   pc->ops->setfromoptions = PCSetFromOptions_PARMS;
652:   pc->ops->setup          = PCSetUp_PARMS;
653:   pc->ops->apply          = PCApply_PARMS;
654:   pc->ops->view           = PCView_PARMS;

656:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetGlobal_C", PCPARMSSetGlobal_PARMS);
657:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetLocal_C", PCPARMSSetLocal_PARMS);
658:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetSolveTolerances_C", PCPARMSSetSolveTolerances_PARMS);
659:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetSolveRestart_C", PCPARMSSetSolveRestart_PARMS);
660:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetNonsymPerm_C", PCPARMSSetNonsymPerm_PARMS);
661:   PetscObjectComposeFunction((PetscObject)pc, "PCPARMSSetFill_C", PCPARMSSetFill_PARMS);
662:   return 0;
663: }