1 /* 2 Provides an interface to pARMS. 3 Requires pARMS 3.2 or later. 4 */ 5 6 #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 7 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> 21 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; 36 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; 50 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)); 56 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; 64 65 for (i = 0; i < npro + 1; i++) mapptr[i] = mapptr0[i] + 1; 66 for (i = 0; i < n; i++) maptmp[i] = i + 1; 67 68 /* if created, destroy the previous map */ 69 if (parms->map) { 70 parms_MapFree(&parms->map); 71 parms->map = NULL; 72 } 73 74 /* create pARMS map object */ 75 parms_MapCreateFromPtr(&parms->map, (int)n, maptmp, mapptr, PetscObjectComm((PetscObject)pmat), 1, NONINTERLACED); 76 77 /* if created, destroy the previous pARMS matrix */ 78 if (parms->A) { 79 parms_MatFree(&parms->A); 80 parms->A = NULL; 81 } 82 83 /* create pARMS mat object */ 84 parms_MatCreate(&parms->A, parms->map); 85 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)); 93 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; 98 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 } 114 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)); 118 119 /* 1-based indexing */ 120 for (i = 0; i < ia[lsize] - 1; i++) ja[i] = ja[i] + 1; 121 122 /* Now copy csr matrix to parms_mat object */ 123 parms_MatSetValues(parms->A, (int)lsize, im, ia, ja, aa, INSERT); 124 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)); 132 133 /* setup parms matrix */ 134 parms_MatSetup(parms->A); 135 136 /* if created, destroy the previous pARMS pc */ 137 if (parms->pc) { 138 parms_PCFree(&parms->pc); 139 parms->pc = NULL; 140 } 141 142 /* Now create pARMS preconditioner object based on A */ 143 parms_PCCreate(&parms->pc, parms->A); 144 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); 183 184 parms_PCSetup(parms->pc); 185 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 } 193 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; 200 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 } 234 235 static PetscErrorCode PCDestroy_PARMS(PC pc) 236 { 237 PC_PARMS *parms = (PC_PARMS *)pc->data; 238 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)); 246 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 } 256 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; 263 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 } 298 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; 304 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 } 315 316 static PetscErrorCode PCPARMSSetGlobal_PARMS(PC pc, PCPARMSGlobalType type) 317 { 318 PC_PARMS *parms = (PC_PARMS *)pc->data; 319 320 PetscFunctionBegin; 321 if (type != parms->global) { 322 parms->global = type; 323 pc->setupcalled = PETSC_FALSE; 324 } 325 PetscFunctionReturn(PETSC_SUCCESS); 326 } 327 328 /*@ 329 PCPARMSSetGlobal - Sets the global preconditioner to be used in `PCPARMS`. 330 331 Collective 332 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 341 342 Options Database Key: 343 . -pc_parms_global [ras,schur,bj] - Sets global preconditioner 344 345 Level: intermediate 346 347 Note: 348 See the pARMS function `parms_PCSetType()` for more information. 349 350 .seealso: [](ch_ksp), `PCPARMS`, `PCPARMSSetLocal()` 351 @*/ 352 PetscErrorCode PCPARMSSetGlobal(PC pc, PCPARMSGlobalType type) 353 { 354 PetscFunctionBegin; 355 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 356 PetscValidLogicalCollectiveEnum(pc, type, 2); 357 PetscTryMethod(pc, "PCPARMSSetGlobal_C", (PC, PCPARMSGlobalType), (pc, type)); 358 PetscFunctionReturn(PETSC_SUCCESS); 359 } 360 361 static PetscErrorCode PCPARMSSetLocal_PARMS(PC pc, PCPARMSLocalType type) 362 { 363 PC_PARMS *parms = (PC_PARMS *)pc->data; 364 365 PetscFunctionBegin; 366 if (type != parms->local) { 367 parms->local = type; 368 pc->setupcalled = PETSC_FALSE; 369 } 370 PetscFunctionReturn(PETSC_SUCCESS); 371 } 372 373 /*@ 374 PCPARMSSetLocal - Sets the local preconditioner to be used in `PCPARMS`. 375 376 Collective 377 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 387 388 Options Database Keys: 389 . pc_parms_local [ilu0,iluk,ilut,arms] - Sets local preconditioner 390 391 Level: intermediate 392 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(). 396 397 See the pARMS function `parms_PCILUSetType()` for more information. 398 399 .seealso: [](ch_ksp), `PCPARMS`, `PCPARMSSetGlobal()`, `PCPARMSSetNonsymPerm()` 400 401 @*/ 402 PetscErrorCode PCPARMSSetLocal(PC pc, PCPARMSLocalType type) 403 { 404 PetscFunctionBegin; 405 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 406 PetscValidLogicalCollectiveEnum(pc, type, 2); 407 PetscTryMethod(pc, "PCPARMSSetLocal_C", (PC, PCPARMSLocalType), (pc, type)); 408 PetscFunctionReturn(PETSC_SUCCESS); 409 } 410 411 static PetscErrorCode PCPARMSSetSolveTolerances_PARMS(PC pc, PetscReal tol, PetscInt maxits) 412 { 413 PC_PARMS *parms = (PC_PARMS *)pc->data; 414 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 } 426 427 /*@ 428 PCPARMSSetSolveTolerances - Sets the convergence tolerance and the maximum iterations for the 429 inner GMRES solver, when the Schur global preconditioner is used. 430 431 Collective 432 433 Input Parameters: 434 + pc - the preconditioner context 435 . tol - the convergence tolerance 436 - maxits - the maximum number of iterations to use 437 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 441 442 Level: intermediate 443 444 Note: 445 See the pARMS functions `parms_PCSetInnerEps()` and `parms_PCSetInnerMaxits()` for more information. 446 447 .seealso: [](ch_ksp), `PCPARMS`, `PCPARMSSetSolveRestart()` 448 @*/ 449 PetscErrorCode PCPARMSSetSolveTolerances(PC pc, PetscReal tol, PetscInt maxits) 450 { 451 PetscFunctionBegin; 452 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 453 PetscTryMethod(pc, "PCPARMSSetSolveTolerances_C", (PC, PetscReal, PetscInt), (pc, tol, maxits)); 454 PetscFunctionReturn(PETSC_SUCCESS); 455 } 456 457 static PetscErrorCode PCPARMSSetSolveRestart_PARMS(PC pc, PetscInt restart) 458 { 459 PC_PARMS *parms = (PC_PARMS *)pc->data; 460 461 PetscFunctionBegin; 462 if (restart != parms->maxdim) { 463 parms->maxdim = restart; 464 pc->setupcalled = PETSC_FALSE; 465 } 466 PetscFunctionReturn(PETSC_SUCCESS); 467 } 468 469 /*@ 470 PCPARMSSetSolveRestart - Sets the number of iterations at which the 471 inner GMRES solver restarts. 472 473 Collective 474 475 Input Parameters: 476 + pc - the preconditioner context 477 - restart - maximum dimension of the Krylov subspace 478 479 Options Database Key: 480 . -pc_parms_max_dim - sets the inner Krylov dimension 481 482 Level: intermediate 483 484 Note: 485 See the pARMS function parms_PCSetInnerKSize for more information. 486 487 .seealso: [](ch_ksp), `PCPARMS`, `PCPARMSSetSolveTolerances()` 488 @*/ 489 PetscErrorCode PCPARMSSetSolveRestart(PC pc, PetscInt restart) 490 { 491 PetscFunctionBegin; 492 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 493 PetscTryMethod(pc, "PCPARMSSetSolveRestart_C", (PC, PetscInt), (pc, restart)); 494 PetscFunctionReturn(PETSC_SUCCESS); 495 } 496 497 static PetscErrorCode PCPARMSSetNonsymPerm_PARMS(PC pc, PetscBool nonsym) 498 { 499 PC_PARMS *parms = (PC_PARMS *)pc->data; 500 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 } 508 509 /*@ 510 PCPARMSSetNonsymPerm - Sets the type of permutation for the ARMS preconditioner: the standard 511 symmetric ARMS or the non-symmetric ARMS (ARMS-ddPQ). 512 513 Collective 514 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 519 520 Options Database Key: 521 . -pc_parms_nonsymmetric_perm - sets the use of nonsymmetric permutation 522 523 Level: intermediate 524 525 Note: 526 See the pARMS function `parms_PCSetPermType()` for more information. 527 528 .seealso: [](ch_ksp), `PCPARMS` 529 @*/ 530 PetscErrorCode PCPARMSSetNonsymPerm(PC pc, PetscBool nonsym) 531 { 532 PetscFunctionBegin; 533 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 534 PetscTryMethod(pc, "PCPARMSSetNonsymPerm_C", (PC, PetscBool), (pc, nonsym)); 535 PetscFunctionReturn(PETSC_SUCCESS); 536 } 537 538 static PetscErrorCode PCPARMSSetFill_PARMS(PC pc, PetscInt lfil0, PetscInt lfil1, PetscInt lfil2) 539 { 540 PC_PARMS *parms = (PC_PARMS *)pc->data; 541 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 } 557 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]. 562 563 Collective 564 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 570 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 575 576 Level: intermediate 577 578 Note: 579 See the pARMS function `parms_PCSetFill()` for more information. 580 581 .seealso: [](ch_ksp), `PCPARMS` 582 @*/ 583 PetscErrorCode PCPARMSSetFill(PC pc, PetscInt lfil0, PetscInt lfil1, PetscInt lfil2) 584 { 585 PetscFunctionBegin; 586 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 587 PetscTryMethod(pc, "PCPARMSSetFill_C", (PC, PetscInt, PetscInt, PetscInt), (pc, lfil0, lfil1, lfil2)); 588 PetscFunctionReturn(PETSC_SUCCESS); 589 } 590 591 /*MC 592 PCPARMS - Allows the use of the parallel Algebraic Recursive Multilevel Solvers 593 available in the package pARMS 594 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 619 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`. 624 625 Level: intermediate 626 627 .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCMG`, `PCGAMG`, `PCHYPRE`, `PCPARMSSetGlobal()`, 628 `PCPARMSSetLocal()`, `PCPARMSSetSolveTolerances()`, `PCPARMSSetSolveRestart()`, `PCPARMSSetNonsymPerm()`, 629 `PCPARMSSetFill()` 630 M*/ 631 632 PETSC_EXTERN PetscErrorCode PCCreate_PARMS(PC pc) 633 { 634 PC_PARMS *parms; 635 636 PetscFunctionBegin; 637 PetscCall(PetscNew(&parms)); 638 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; 664 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; 671 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 } 680