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