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