1 /* 2 The PC (preconditioner) interface routines, callable by users. 3 */ 4 #include <petsc/private/pcimpl.h> /*I "petscksp.h" I*/ 5 #include <petscdm.h> 6 7 /* Logging support */ 8 PetscClassId PC_CLASSID; 9 PetscLogEvent PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_MatApply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft; 10 PetscLogEvent PC_ApplySymmetricRight, PC_ModifySubMatrices, PC_ApplyOnBlocks, PC_ApplyTransposeOnBlocks; 11 PetscInt PetscMGLevelId; 12 PetscLogStage PCMPIStage; 13 14 PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC pc, const char *type[]) 15 { 16 PetscMPIInt size; 17 PetscBool hasopblock, hasopsolve, flg1, flg2, set, flg3, isnormal; 18 19 PetscFunctionBegin; 20 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 21 if (pc->pmat) { 22 PetscCall(MatHasOperation(pc->pmat, MATOP_GET_DIAGONAL_BLOCK, &hasopblock)); 23 PetscCall(MatHasOperation(pc->pmat, MATOP_SOLVE, &hasopsolve)); 24 if (size == 1) { 25 PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ICC, &flg1)); 26 PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ILU, &flg2)); 27 PetscCall(MatIsSymmetricKnown(pc->pmat, &set, &flg3)); 28 PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &isnormal, MATNORMAL, MATNORMALHERMITIAN, NULL)); 29 if (flg1 && (!flg2 || (set && flg3))) { 30 *type = PCICC; 31 } else if (flg2) { 32 *type = PCILU; 33 } else if (isnormal) { 34 *type = PCNONE; 35 } else if (hasopblock) { /* likely is a parallel matrix run on one processor */ 36 *type = PCBJACOBI; 37 } else if (hasopsolve) { 38 *type = PCMAT; 39 } else { 40 *type = PCNONE; 41 } 42 } else { 43 if (hasopblock) { 44 *type = PCBJACOBI; 45 } else if (hasopsolve) { 46 *type = PCMAT; 47 } else { 48 *type = PCNONE; 49 } 50 } 51 } else *type = NULL; 52 PetscFunctionReturn(PETSC_SUCCESS); 53 } 54 55 /*@ 56 PCReset - Resets a `PC` context to the pcsetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s 57 58 Collective 59 60 Input Parameter: 61 . pc - the preconditioner context 62 63 Level: developer 64 65 Note: 66 This allows a `PC` to be reused for a different sized linear system but using the same options that have been previously set in `pc` 67 68 .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()` 69 @*/ 70 PetscErrorCode PCReset(PC pc) 71 { 72 PetscFunctionBegin; 73 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 74 PetscTryTypeMethod(pc, reset); 75 PetscCall(VecDestroy(&pc->diagonalscaleright)); 76 PetscCall(VecDestroy(&pc->diagonalscaleleft)); 77 PetscCall(MatDestroy(&pc->pmat)); 78 PetscCall(MatDestroy(&pc->mat)); 79 80 pc->setupcalled = 0; 81 PetscFunctionReturn(PETSC_SUCCESS); 82 } 83 84 /*@ 85 PCDestroy - Destroys `PC` context that was created with `PCCreate()`. 86 87 Collective 88 89 Input Parameter: 90 . pc - the preconditioner context 91 92 Level: developer 93 94 .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()` 95 @*/ 96 PetscErrorCode PCDestroy(PC *pc) 97 { 98 PetscFunctionBegin; 99 if (!*pc) PetscFunctionReturn(PETSC_SUCCESS); 100 PetscValidHeaderSpecific(*pc, PC_CLASSID, 1); 101 if (--((PetscObject)*pc)->refct > 0) { 102 *pc = NULL; 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 PetscCall(PCReset(*pc)); 107 108 /* if memory was published with SAWs then destroy it */ 109 PetscCall(PetscObjectSAWsViewOff((PetscObject)*pc)); 110 PetscTryTypeMethod(*pc, destroy); 111 PetscCall(DMDestroy(&(*pc)->dm)); 112 PetscCall(PetscHeaderDestroy(pc)); 113 PetscFunctionReturn(PETSC_SUCCESS); 114 } 115 116 /*@ 117 PCGetDiagonalScale - Indicates if the preconditioner applies an additional left and right 118 scaling as needed by certain time-stepping codes. 119 120 Logically Collective 121 122 Input Parameter: 123 . pc - the preconditioner context 124 125 Output Parameter: 126 . flag - `PETSC_TRUE` if it applies the scaling 127 128 Level: developer 129 130 Note: 131 If this returns `PETSC_TRUE` then the system solved via the Krylov method is, for left and right preconditioning, 132 133 $$ 134 \begin{align*} 135 D M A D^{-1} y = D M b \\ 136 D A M D^{-1} z = D b. 137 \end{align*} 138 $$ 139 140 .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCSetDiagonalScale()` 141 @*/ 142 PetscErrorCode PCGetDiagonalScale(PC pc, PetscBool *flag) 143 { 144 PetscFunctionBegin; 145 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 146 PetscAssertPointer(flag, 2); 147 *flag = pc->diagonalscale; 148 PetscFunctionReturn(PETSC_SUCCESS); 149 } 150 151 /*@ 152 PCSetDiagonalScale - Indicates the left scaling to use to apply an additional left and right 153 scaling as needed by certain time-stepping codes. 154 155 Logically Collective 156 157 Input Parameters: 158 + pc - the preconditioner context 159 - s - scaling vector 160 161 Level: intermediate 162 163 Notes: 164 The system solved via the Krylov method is, for left and right preconditioning, 165 $$ 166 \begin{align*} 167 D M A D^{-1} y = D M b \\ 168 D A M D^{-1} z = D b. 169 \end{align*} 170 $$ 171 172 `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$. 173 174 .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCGetDiagonalScale()` 175 @*/ 176 PetscErrorCode PCSetDiagonalScale(PC pc, Vec s) 177 { 178 PetscFunctionBegin; 179 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 180 PetscValidHeaderSpecific(s, VEC_CLASSID, 2); 181 pc->diagonalscale = PETSC_TRUE; 182 183 PetscCall(PetscObjectReference((PetscObject)s)); 184 PetscCall(VecDestroy(&pc->diagonalscaleleft)); 185 186 pc->diagonalscaleleft = s; 187 188 PetscCall(VecDuplicate(s, &pc->diagonalscaleright)); 189 PetscCall(VecCopy(s, pc->diagonalscaleright)); 190 PetscCall(VecReciprocal(pc->diagonalscaleright)); 191 PetscFunctionReturn(PETSC_SUCCESS); 192 } 193 194 /*@ 195 PCDiagonalScaleLeft - Scales a vector by the left scaling as needed by certain time-stepping codes. 196 197 Logically Collective 198 199 Input Parameters: 200 + pc - the preconditioner context 201 . in - input vector 202 - out - scaled vector (maybe the same as in) 203 204 Level: intermediate 205 206 Notes: 207 The system solved via the Krylov method is, for left and right preconditioning, 208 209 $$ 210 \begin{align*} 211 D M A D^{-1} y = D M b \\ 212 D A M D^{-1} z = D b. 213 \end{align*} 214 $$ 215 216 `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$. 217 218 If diagonal scaling is turned off and `in` is not `out` then `in` is copied to `out` 219 220 .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCSetDiagonalScale()`, `PCDiagonalScaleRight()`, `PCDiagonalScale()` 221 @*/ 222 PetscErrorCode PCDiagonalScaleLeft(PC pc, Vec in, Vec out) 223 { 224 PetscFunctionBegin; 225 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 226 PetscValidHeaderSpecific(in, VEC_CLASSID, 2); 227 PetscValidHeaderSpecific(out, VEC_CLASSID, 3); 228 if (pc->diagonalscale) { 229 PetscCall(VecPointwiseMult(out, pc->diagonalscaleleft, in)); 230 } else if (in != out) { 231 PetscCall(VecCopy(in, out)); 232 } 233 PetscFunctionReturn(PETSC_SUCCESS); 234 } 235 236 /*@ 237 PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes. 238 239 Logically Collective 240 241 Input Parameters: 242 + pc - the preconditioner context 243 . in - input vector 244 - out - scaled vector (maybe the same as in) 245 246 Level: intermediate 247 248 Notes: 249 The system solved via the Krylov method is, for left and right preconditioning, 250 251 $$ 252 \begin{align*} 253 D M A D^{-1} y = D M b \\ 254 D A M D^{-1} z = D b. 255 \end{align*} 256 $$ 257 258 `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$. 259 260 If diagonal scaling is turned off and `in` is not `out` then `in` is copied to `out` 261 262 .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCSetDiagonalScale()`, `PCDiagonalScale()` 263 @*/ 264 PetscErrorCode PCDiagonalScaleRight(PC pc, Vec in, Vec out) 265 { 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 268 PetscValidHeaderSpecific(in, VEC_CLASSID, 2); 269 PetscValidHeaderSpecific(out, VEC_CLASSID, 3); 270 if (pc->diagonalscale) { 271 PetscCall(VecPointwiseMult(out, pc->diagonalscaleright, in)); 272 } else if (in != out) { 273 PetscCall(VecCopy(in, out)); 274 } 275 PetscFunctionReturn(PETSC_SUCCESS); 276 } 277 278 /*@ 279 PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the 280 operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`, 281 `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat. 282 283 Logically Collective 284 285 Input Parameters: 286 + pc - the preconditioner context 287 - flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false) 288 289 Options Database Key: 290 . -pc_use_amat <true,false> - use the amat argument to `KSPSetOperators()` or `PCSetOperators()` to apply the operator 291 292 Level: intermediate 293 294 Note: 295 For the common case in which the linear system matrix and the matrix used to construct the 296 preconditioner are identical, this routine has no affect. 297 298 .seealso: [](ch_ksp), `PC`, `PCGetUseAmat()`, `PCBJACOBI`, `PGMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`, 299 `KSPSetOperators()`, `PCSetOperators()` 300 @*/ 301 PetscErrorCode PCSetUseAmat(PC pc, PetscBool flg) 302 { 303 PetscFunctionBegin; 304 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 305 pc->useAmat = flg; 306 PetscFunctionReturn(PETSC_SUCCESS); 307 } 308 309 /*@ 310 PCSetErrorIfFailure - Causes `PC` to generate an error if a floating point exception, for example a zero pivot, is detected. 311 312 Logically Collective 313 314 Input Parameters: 315 + pc - iterative context obtained from `PCCreate()` 316 - flg - `PETSC_TRUE` indicates you want the error generated 317 318 Level: advanced 319 320 Notes: 321 Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call `KSPGetConvergedReason()` after a `KSPSolve()` 322 to determine if it has converged or failed. Or use -ksp_error_if_not_converged to cause the program to terminate as soon as lack of convergence is 323 detected. 324 325 This is propagated into `KSP`s used by this `PC`, which then propagate it into `PC`s used by those `KSP`s 326 327 .seealso: [](ch_ksp), `PC`, `KSPSetErrorIfNotConverged()`, `PCGetInitialGuessNonzero()`, `PCSetInitialGuessKnoll()`, `PCGetInitialGuessKnoll()` 328 @*/ 329 PetscErrorCode PCSetErrorIfFailure(PC pc, PetscBool flg) 330 { 331 PetscFunctionBegin; 332 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 333 PetscValidLogicalCollectiveBool(pc, flg, 2); 334 pc->erroriffailure = flg; 335 PetscFunctionReturn(PETSC_SUCCESS); 336 } 337 338 /*@ 339 PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the 340 operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`, 341 `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat. 342 343 Logically Collective 344 345 Input Parameter: 346 . pc - the preconditioner context 347 348 Output Parameter: 349 . flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false) 350 351 Level: intermediate 352 353 Note: 354 For the common case in which the linear system matrix and the matrix used to construct the 355 preconditioner are identical, this routine is does nothing. 356 357 .seealso: [](ch_ksp), `PC`, `PCSetUseAmat()`, `PCBJACOBI`, `PGMG`, `PCFIELDSPLIT`, `PCCOMPOSITE` 358 @*/ 359 PetscErrorCode PCGetUseAmat(PC pc, PetscBool *flg) 360 { 361 PetscFunctionBegin; 362 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 363 *flg = pc->useAmat; 364 PetscFunctionReturn(PETSC_SUCCESS); 365 } 366 367 /*@ 368 PCSetKSPNestLevel - sets the amount of nesting the `KSP` that contains this `PC` has 369 370 Collective 371 372 Input Parameters: 373 + pc - the `PC` 374 - level - the nest level 375 376 Level: developer 377 378 .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPGetNestLevel()`, `PCGetKSPNestLevel()`, `KSPSetNestLevel()` 379 @*/ 380 PetscErrorCode PCSetKSPNestLevel(PC pc, PetscInt level) 381 { 382 PetscFunctionBegin; 383 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 384 PetscValidLogicalCollectiveInt(pc, level, 2); 385 pc->kspnestlevel = level; 386 PetscFunctionReturn(PETSC_SUCCESS); 387 } 388 389 /*@ 390 PCGetKSPNestLevel - gets the amount of nesting the `KSP` that contains this `PC` has 391 392 Not Collective 393 394 Input Parameter: 395 . pc - the `PC` 396 397 Output Parameter: 398 . level - the nest level 399 400 Level: developer 401 402 .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPSetNestLevel()`, `PCSetKSPNestLevel()`, `KSPGetNestLevel()` 403 @*/ 404 PetscErrorCode PCGetKSPNestLevel(PC pc, PetscInt *level) 405 { 406 PetscFunctionBegin; 407 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 408 PetscAssertPointer(level, 2); 409 *level = pc->kspnestlevel; 410 PetscFunctionReturn(PETSC_SUCCESS); 411 } 412 413 /*@ 414 PCCreate - Creates a preconditioner context, `PC` 415 416 Collective 417 418 Input Parameter: 419 . comm - MPI communicator 420 421 Output Parameter: 422 . newpc - location to put the preconditioner context 423 424 Level: developer 425 426 Note: 427 The default preconditioner for sparse matrices is `PCILU` or `PCICC` with 0 fill on one process and block Jacobi (`PCBJACOBI`) with `PCILU` or `PCICC` 428 in parallel. For dense matrices it is always `PCNONE`. 429 430 .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCApply()`, `PCDestroy()` 431 @*/ 432 PetscErrorCode PCCreate(MPI_Comm comm, PC *newpc) 433 { 434 PC pc; 435 436 PetscFunctionBegin; 437 PetscAssertPointer(newpc, 2); 438 PetscCall(PCInitializePackage()); 439 440 PetscCall(PetscHeaderCreate(pc, PC_CLASSID, "PC", "Preconditioner", "PC", comm, PCDestroy, PCView)); 441 pc->mat = NULL; 442 pc->pmat = NULL; 443 pc->setupcalled = 0; 444 pc->setfromoptionscalled = 0; 445 pc->data = NULL; 446 pc->diagonalscale = PETSC_FALSE; 447 pc->diagonalscaleleft = NULL; 448 pc->diagonalscaleright = NULL; 449 450 pc->modifysubmatrices = NULL; 451 pc->modifysubmatricesP = NULL; 452 453 *newpc = pc; 454 PetscFunctionReturn(PETSC_SUCCESS); 455 } 456 457 /*@ 458 PCApply - Applies the preconditioner to a vector. 459 460 Collective 461 462 Input Parameters: 463 + pc - the preconditioner context 464 - x - input vector 465 466 Output Parameter: 467 . y - output vector 468 469 Level: developer 470 471 .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`, `PCApplyBAorAB()` 472 @*/ 473 PetscErrorCode PCApply(PC pc, Vec x, Vec y) 474 { 475 PetscInt m, n, mv, nv; 476 477 PetscFunctionBegin; 478 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 479 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 480 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 481 PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 482 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 483 /* use pmat to check vector sizes since for KSPLSQR the pmat may be of a different size than mat */ 484 PetscCall(MatGetLocalSize(pc->pmat, &m, &n)); 485 PetscCall(VecGetLocalSize(x, &mv)); 486 PetscCall(VecGetLocalSize(y, &nv)); 487 /* check pmat * y = x is feasible */ 488 PetscCheck(mv == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Preconditioner number of local rows %" PetscInt_FMT " does not equal input vector size %" PetscInt_FMT, m, mv); 489 PetscCheck(nv == n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Preconditioner number of local columns %" PetscInt_FMT " does not equal output vector size %" PetscInt_FMT, n, nv); 490 PetscCall(VecSetErrorIfLocked(y, 3)); 491 492 PetscCall(PCSetUp(pc)); 493 PetscCall(VecLockReadPush(x)); 494 PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0)); 495 PetscUseTypeMethod(pc, apply, x, y); 496 PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0)); 497 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 498 PetscCall(VecLockReadPop(x)); 499 PetscFunctionReturn(PETSC_SUCCESS); 500 } 501 502 /*@ 503 PCMatApply - Applies the preconditioner to multiple vectors stored as a `MATDENSE`. Like `PCApply()`, `Y` and `X` must be different matrices. 504 505 Collective 506 507 Input Parameters: 508 + pc - the preconditioner context 509 - X - block of input vectors 510 511 Output Parameter: 512 . Y - block of output vectors 513 514 Level: developer 515 516 .seealso: [](ch_ksp), `PC`, `PCApply()`, `KSPMatSolve()` 517 @*/ 518 PetscErrorCode PCMatApply(PC pc, Mat X, Mat Y) 519 { 520 Mat A; 521 Vec cy, cx; 522 PetscInt m1, M1, m2, M2, n1, N1, n2, N2, m3, M3, n3, N3; 523 PetscBool match; 524 525 PetscFunctionBegin; 526 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 527 PetscValidHeaderSpecific(X, MAT_CLASSID, 2); 528 PetscValidHeaderSpecific(Y, MAT_CLASSID, 3); 529 PetscCheckSameComm(pc, 1, X, 2); 530 PetscCheckSameComm(pc, 1, Y, 3); 531 PetscCheck(Y != X, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "Y and X must be different matrices"); 532 PetscCall(PCGetOperators(pc, NULL, &A)); 533 PetscCall(MatGetLocalSize(A, &m3, &n3)); 534 PetscCall(MatGetLocalSize(X, &m2, &n2)); 535 PetscCall(MatGetLocalSize(Y, &m1, &n1)); 536 PetscCall(MatGetSize(A, &M3, &N3)); 537 PetscCall(MatGetSize(X, &M2, &N2)); 538 PetscCall(MatGetSize(Y, &M1, &N1)); 539 PetscCheck(n1 == n2 && N1 == N2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible number of columns between block of input vectors (n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and block of output vectors (n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")", n2, N2, n1, N1); 540 PetscCheck(m2 == m3 && M2 == M3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout between block of input vectors (m,M) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and Pmat (m,M)x(n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")x(%" PetscInt_FMT ",%" PetscInt_FMT ")", m2, M2, m3, M3, n3, N3); 541 PetscCheck(m1 == n3 && M1 == N3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout between block of output vectors (m,M) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and Pmat (m,M)x(n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")x(%" PetscInt_FMT ",%" PetscInt_FMT ")", m1, M1, m3, M3, n3, N3); 542 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)Y, &match, MATSEQDENSE, MATMPIDENSE, "")); 543 PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of output vectors not stored in a dense Mat"); 544 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)X, &match, MATSEQDENSE, MATMPIDENSE, "")); 545 PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of input vectors not stored in a dense Mat"); 546 PetscCall(PCSetUp(pc)); 547 if (pc->ops->matapply) { 548 PetscCall(PetscLogEventBegin(PC_MatApply, pc, X, Y, 0)); 549 PetscUseTypeMethod(pc, matapply, X, Y); 550 PetscCall(PetscLogEventEnd(PC_MatApply, pc, X, Y, 0)); 551 } else { 552 PetscCall(PetscInfo(pc, "PC type %s applying column by column\n", ((PetscObject)pc)->type_name)); 553 for (n1 = 0; n1 < N1; ++n1) { 554 PetscCall(MatDenseGetColumnVecRead(X, n1, &cx)); 555 PetscCall(MatDenseGetColumnVecWrite(Y, n1, &cy)); 556 PetscCall(PCApply(pc, cx, cy)); 557 PetscCall(MatDenseRestoreColumnVecWrite(Y, n1, &cy)); 558 PetscCall(MatDenseRestoreColumnVecRead(X, n1, &cx)); 559 } 560 } 561 PetscFunctionReturn(PETSC_SUCCESS); 562 } 563 564 /*@ 565 PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector. 566 567 Collective 568 569 Input Parameters: 570 + pc - the preconditioner context 571 - x - input vector 572 573 Output Parameter: 574 . y - output vector 575 576 Level: developer 577 578 Note: 579 Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners. 580 581 .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricRight()` 582 @*/ 583 PetscErrorCode PCApplySymmetricLeft(PC pc, Vec x, Vec y) 584 { 585 PetscFunctionBegin; 586 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 587 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 588 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 589 PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 590 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 591 PetscCall(PCSetUp(pc)); 592 PetscCall(VecLockReadPush(x)); 593 PetscCall(PetscLogEventBegin(PC_ApplySymmetricLeft, pc, x, y, 0)); 594 PetscUseTypeMethod(pc, applysymmetricleft, x, y); 595 PetscCall(PetscLogEventEnd(PC_ApplySymmetricLeft, pc, x, y, 0)); 596 PetscCall(VecLockReadPop(x)); 597 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 598 PetscFunctionReturn(PETSC_SUCCESS); 599 } 600 601 /*@ 602 PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector. 603 604 Collective 605 606 Input Parameters: 607 + pc - the preconditioner context 608 - x - input vector 609 610 Output Parameter: 611 . y - output vector 612 613 Level: developer 614 615 Note: 616 Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners. 617 618 .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricLeft()` 619 @*/ 620 PetscErrorCode PCApplySymmetricRight(PC pc, Vec x, Vec y) 621 { 622 PetscFunctionBegin; 623 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 624 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 625 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 626 PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 627 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 628 PetscCall(PCSetUp(pc)); 629 PetscCall(VecLockReadPush(x)); 630 PetscCall(PetscLogEventBegin(PC_ApplySymmetricRight, pc, x, y, 0)); 631 PetscUseTypeMethod(pc, applysymmetricright, x, y); 632 PetscCall(PetscLogEventEnd(PC_ApplySymmetricRight, pc, x, y, 0)); 633 PetscCall(VecLockReadPop(x)); 634 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 635 PetscFunctionReturn(PETSC_SUCCESS); 636 } 637 638 /*@ 639 PCApplyTranspose - Applies the transpose of preconditioner to a vector. 640 641 Collective 642 643 Input Parameters: 644 + pc - the preconditioner context 645 - x - input vector 646 647 Output Parameter: 648 . y - output vector 649 650 Level: developer 651 652 Note: 653 For complex numbers this applies the non-Hermitian transpose. 654 655 Developer Note: 656 We need to implement a `PCApplyHermitianTranspose()` 657 658 .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyBAorAB()`, `PCApplyBAorABTranspose()`, `PCApplyTransposeExists()` 659 @*/ 660 PetscErrorCode PCApplyTranspose(PC pc, Vec x, Vec y) 661 { 662 PetscFunctionBegin; 663 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 664 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 665 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 666 PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 667 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 668 PetscCall(PCSetUp(pc)); 669 PetscCall(VecLockReadPush(x)); 670 PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0)); 671 PetscUseTypeMethod(pc, applytranspose, x, y); 672 PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0)); 673 PetscCall(VecLockReadPop(x)); 674 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 675 PetscFunctionReturn(PETSC_SUCCESS); 676 } 677 678 /*@ 679 PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation 680 681 Collective 682 683 Input Parameter: 684 . pc - the preconditioner context 685 686 Output Parameter: 687 . flg - `PETSC_TRUE` if a transpose operation is defined 688 689 Level: developer 690 691 .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()` 692 @*/ 693 PetscErrorCode PCApplyTransposeExists(PC pc, PetscBool *flg) 694 { 695 PetscFunctionBegin; 696 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 697 PetscAssertPointer(flg, 2); 698 if (pc->ops->applytranspose) *flg = PETSC_TRUE; 699 else *flg = PETSC_FALSE; 700 PetscFunctionReturn(PETSC_SUCCESS); 701 } 702 703 /*@ 704 PCApplyBAorAB - Applies the preconditioner and operator to a vector. $y = B*A*x $ or $ y = A*B*x$. 705 706 Collective 707 708 Input Parameters: 709 + pc - the preconditioner context 710 . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC` 711 . x - input vector 712 - work - work vector 713 714 Output Parameter: 715 . y - output vector 716 717 Level: developer 718 719 Note: 720 If the `PC` has had `PCSetDiagonalScale()` set then $ D M A D^{-1} $ for left preconditioning or $ D A M D^{-1} $ is actually applied. 721 The specific `KSPSolve()` method must also be written to handle the post-solve "correction" for the diagonal scaling. 722 723 .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorABTranspose()` 724 @*/ 725 PetscErrorCode PCApplyBAorAB(PC pc, PCSide side, Vec x, Vec y, Vec work) 726 { 727 PetscFunctionBegin; 728 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 729 PetscValidLogicalCollectiveEnum(pc, side, 2); 730 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 731 PetscValidHeaderSpecific(y, VEC_CLASSID, 4); 732 PetscValidHeaderSpecific(work, VEC_CLASSID, 5); 733 PetscCheckSameComm(pc, 1, x, 3); 734 PetscCheckSameComm(pc, 1, y, 4); 735 PetscCheckSameComm(pc, 1, work, 5); 736 PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 737 PetscCheck(side == PC_LEFT || side == PC_SYMMETRIC || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right, left, or symmetric"); 738 PetscCheck(!pc->diagonalscale || side != PC_SYMMETRIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot include diagonal scaling with symmetric preconditioner application"); 739 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE)); 740 741 PetscCall(PCSetUp(pc)); 742 if (pc->diagonalscale) { 743 if (pc->ops->applyBA) { 744 Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */ 745 PetscCall(VecDuplicate(x, &work2)); 746 PetscCall(PCDiagonalScaleRight(pc, x, work2)); 747 PetscUseTypeMethod(pc, applyBA, side, work2, y, work); 748 PetscCall(PCDiagonalScaleLeft(pc, y, y)); 749 PetscCall(VecDestroy(&work2)); 750 } else if (side == PC_RIGHT) { 751 PetscCall(PCDiagonalScaleRight(pc, x, y)); 752 PetscCall(PCApply(pc, y, work)); 753 PetscCall(MatMult(pc->mat, work, y)); 754 PetscCall(PCDiagonalScaleLeft(pc, y, y)); 755 } else if (side == PC_LEFT) { 756 PetscCall(PCDiagonalScaleRight(pc, x, y)); 757 PetscCall(MatMult(pc->mat, y, work)); 758 PetscCall(PCApply(pc, work, y)); 759 PetscCall(PCDiagonalScaleLeft(pc, y, y)); 760 } else PetscCheck(side != PC_SYMMETRIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot provide diagonal scaling with symmetric application of preconditioner"); 761 } else { 762 if (pc->ops->applyBA) { 763 PetscUseTypeMethod(pc, applyBA, side, x, y, work); 764 } else if (side == PC_RIGHT) { 765 PetscCall(PCApply(pc, x, work)); 766 PetscCall(MatMult(pc->mat, work, y)); 767 } else if (side == PC_LEFT) { 768 PetscCall(MatMult(pc->mat, x, work)); 769 PetscCall(PCApply(pc, work, y)); 770 } else if (side == PC_SYMMETRIC) { 771 /* There's an extra copy here; maybe should provide 2 work vectors instead? */ 772 PetscCall(PCApplySymmetricRight(pc, x, work)); 773 PetscCall(MatMult(pc->mat, work, y)); 774 PetscCall(VecCopy(y, work)); 775 PetscCall(PCApplySymmetricLeft(pc, work, y)); 776 } 777 } 778 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE)); 779 PetscFunctionReturn(PETSC_SUCCESS); 780 } 781 782 /*@ 783 PCApplyBAorABTranspose - Applies the transpose of the preconditioner 784 and operator to a vector. That is, applies $B^T * A^T$ with left preconditioning, 785 NOT $(B*A)^T = A^T*B^T$. 786 787 Collective 788 789 Input Parameters: 790 + pc - the preconditioner context 791 . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC` 792 . x - input vector 793 - work - work vector 794 795 Output Parameter: 796 . y - output vector 797 798 Level: developer 799 800 Note: 801 This routine is used internally so that the same Krylov code can be used to solve $A x = b$ and $A^T x = b$, with a preconditioner 802 defined by $B^T$. This is why this has the funny form that it computes $B^T * A^T$ 803 804 .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorAB()` 805 @*/ 806 PetscErrorCode PCApplyBAorABTranspose(PC pc, PCSide side, Vec x, Vec y, Vec work) 807 { 808 PetscFunctionBegin; 809 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 810 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 811 PetscValidHeaderSpecific(y, VEC_CLASSID, 4); 812 PetscValidHeaderSpecific(work, VEC_CLASSID, 5); 813 PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors"); 814 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE)); 815 if (pc->ops->applyBAtranspose) { 816 PetscUseTypeMethod(pc, applyBAtranspose, side, x, y, work); 817 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE)); 818 PetscFunctionReturn(PETSC_SUCCESS); 819 } 820 PetscCheck(side == PC_LEFT || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right or left"); 821 822 PetscCall(PCSetUp(pc)); 823 if (side == PC_RIGHT) { 824 PetscCall(PCApplyTranspose(pc, x, work)); 825 PetscCall(MatMultTranspose(pc->mat, work, y)); 826 } else if (side == PC_LEFT) { 827 PetscCall(MatMultTranspose(pc->mat, x, work)); 828 PetscCall(PCApplyTranspose(pc, work, y)); 829 } 830 /* add support for PC_SYMMETRIC */ 831 if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE)); 832 PetscFunctionReturn(PETSC_SUCCESS); 833 } 834 835 /*@ 836 PCApplyRichardsonExists - Determines whether a particular preconditioner has a 837 built-in fast application of Richardson's method. 838 839 Not Collective 840 841 Input Parameter: 842 . pc - the preconditioner 843 844 Output Parameter: 845 . exists - `PETSC_TRUE` or `PETSC_FALSE` 846 847 Level: developer 848 849 .seealso: [](ch_ksp), `PC`, `KSPRICHARDSON`, `PCApplyRichardson()` 850 @*/ 851 PetscErrorCode PCApplyRichardsonExists(PC pc, PetscBool *exists) 852 { 853 PetscFunctionBegin; 854 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 855 PetscAssertPointer(exists, 2); 856 if (pc->ops->applyrichardson) *exists = PETSC_TRUE; 857 else *exists = PETSC_FALSE; 858 PetscFunctionReturn(PETSC_SUCCESS); 859 } 860 861 /*@ 862 PCApplyRichardson - Applies several steps of Richardson iteration with 863 the particular preconditioner. This routine is usually used by the 864 Krylov solvers and not the application code directly. 865 866 Collective 867 868 Input Parameters: 869 + pc - the preconditioner context 870 . b - the right-hand side 871 . w - one work vector 872 . rtol - relative decrease in residual norm convergence criteria 873 . abstol - absolute residual norm convergence criteria 874 . dtol - divergence residual norm increase criteria 875 . its - the number of iterations to apply. 876 - guesszero - if the input x contains nonzero initial guess 877 878 Output Parameters: 879 + outits - number of iterations actually used (for SOR this always equals its) 880 . reason - the reason the apply terminated 881 - y - the solution (also contains initial guess if guesszero is `PETSC_FALSE` 882 883 Level: developer 884 885 Notes: 886 Most preconditioners do not support this function. Use the command 887 `PCApplyRichardsonExists()` to determine if one does. 888 889 Except for the `PCMG` this routine ignores the convergence tolerances 890 and always runs for the number of iterations 891 892 .seealso: [](ch_ksp), `PC`, `PCApplyRichardsonExists()` 893 @*/ 894 PetscErrorCode PCApplyRichardson(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason) 895 { 896 PetscFunctionBegin; 897 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 898 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 899 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 900 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 901 PetscCheck(b != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "b and y must be different vectors"); 902 PetscCall(PCSetUp(pc)); 903 PetscUseTypeMethod(pc, applyrichardson, b, y, w, rtol, abstol, dtol, its, guesszero, outits, reason); 904 PetscFunctionReturn(PETSC_SUCCESS); 905 } 906 907 /*@ 908 PCSetFailedReason - Sets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail 909 910 Logically Collective 911 912 Input Parameters: 913 + pc - the preconditioner context 914 - reason - the reason it failedx 915 916 Level: advanced 917 918 .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCFailedReason` 919 @*/ 920 PetscErrorCode PCSetFailedReason(PC pc, PCFailedReason reason) 921 { 922 PetscFunctionBegin; 923 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 924 pc->failedreason = reason; 925 PetscFunctionReturn(PETSC_SUCCESS); 926 } 927 928 /*@ 929 PCGetFailedReason - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail 930 931 Logically Collective 932 933 Input Parameter: 934 . pc - the preconditioner context 935 936 Output Parameter: 937 . reason - the reason it failed 938 939 Level: advanced 940 941 Note: 942 This is the maximum over reason over all ranks in the PC communicator. It is only valid after 943 a call `KSPCheckDot()` or `KSPCheckNorm()` inside a `KSPSolve()` or `PCReduceFailedReason()`. 944 It is not valid immediately after a `PCSetUp()` or `PCApply()`, then use `PCGetFailedReasonRank()` 945 946 .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReasonRank()`, `PCSetFailedReason()` 947 @*/ 948 PetscErrorCode PCGetFailedReason(PC pc, PCFailedReason *reason) 949 { 950 PetscFunctionBegin; 951 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 952 if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled; 953 else *reason = pc->failedreason; 954 PetscFunctionReturn(PETSC_SUCCESS); 955 } 956 957 /*@ 958 PCGetFailedReasonRank - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail on this MPI rank 959 960 Not Collective 961 962 Input Parameter: 963 . pc - the preconditioner context 964 965 Output Parameter: 966 . reason - the reason it failed 967 968 Level: advanced 969 970 Note: 971 Different processes may have different reasons or no reason, see `PCGetFailedReason()` 972 973 .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()`, `PCReduceFailedReason()` 974 @*/ 975 PetscErrorCode PCGetFailedReasonRank(PC pc, PCFailedReason *reason) 976 { 977 PetscFunctionBegin; 978 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 979 if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled; 980 else *reason = pc->failedreason; 981 PetscFunctionReturn(PETSC_SUCCESS); 982 } 983 984 /*@ 985 PCReduceFailedReason - Reduce the failed reason among the MPI processes that share the `PC` 986 987 Collective 988 989 Input Parameter: 990 . pc - the preconditioner context 991 992 Level: advanced 993 994 Note: 995 Different MPI processes may have different reasons or no reason, see `PCGetFailedReason()`. This routine 996 makes them have a common value (failure if any MPI process had a failure). 997 998 .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()` 999 @*/ 1000 PetscErrorCode PCReduceFailedReason(PC pc) 1001 { 1002 PetscInt buf; 1003 1004 PetscFunctionBegin; 1005 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1006 buf = (PetscInt)pc->failedreason; 1007 PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &buf, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc))); 1008 pc->failedreason = (PCFailedReason)buf; 1009 PetscFunctionReturn(PETSC_SUCCESS); 1010 } 1011 1012 /* Next line needed to deactivate KSP_Solve logging */ 1013 #include <petsc/private/kspimpl.h> 1014 1015 /* 1016 a setupcall of 0 indicates never setup, 1017 1 indicates has been previously setup 1018 -1 indicates a PCSetUp() was attempted and failed 1019 */ 1020 /*@ 1021 PCSetUp - Prepares for the use of a preconditioner. 1022 1023 Collective 1024 1025 Input Parameter: 1026 . pc - the preconditioner context 1027 1028 Level: developer 1029 1030 .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()` 1031 @*/ 1032 PetscErrorCode PCSetUp(PC pc) 1033 { 1034 const char *def; 1035 PetscObjectState matstate, matnonzerostate; 1036 1037 PetscFunctionBegin; 1038 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1039 PetscCheck(pc->mat, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be set first"); 1040 1041 if (pc->setupcalled && pc->reusepreconditioner) { 1042 PetscCall(PetscInfo(pc, "Leaving PC with identical preconditioner since reuse preconditioner is set\n")); 1043 PetscFunctionReturn(PETSC_SUCCESS); 1044 } 1045 1046 PetscCall(PetscObjectStateGet((PetscObject)pc->pmat, &matstate)); 1047 PetscCall(MatGetNonzeroState(pc->pmat, &matnonzerostate)); 1048 if (!pc->setupcalled) { 1049 //PetscCall(PetscInfo(pc, "Setting up PC for first time\n")); 1050 pc->flag = DIFFERENT_NONZERO_PATTERN; 1051 } else if (matstate == pc->matstate) PetscFunctionReturn(PETSC_SUCCESS); 1052 else { 1053 if (matnonzerostate != pc->matnonzerostate) { 1054 PetscCall(PetscInfo(pc, "Setting up PC with different nonzero pattern\n")); 1055 pc->flag = DIFFERENT_NONZERO_PATTERN; 1056 } else { 1057 //PetscCall(PetscInfo(pc, "Setting up PC with same nonzero pattern\n")); 1058 pc->flag = SAME_NONZERO_PATTERN; 1059 } 1060 } 1061 pc->matstate = matstate; 1062 pc->matnonzerostate = matnonzerostate; 1063 1064 if (!((PetscObject)pc)->type_name) { 1065 PetscCall(PCGetDefaultType_Private(pc, &def)); 1066 PetscCall(PCSetType(pc, def)); 1067 } 1068 1069 PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure)); 1070 PetscCall(MatSetErrorIfFailure(pc->mat, pc->erroriffailure)); 1071 PetscCall(PetscLogEventBegin(PC_SetUp, pc, 0, 0, 0)); 1072 if (pc->ops->setup) { 1073 /* do not log solves and applications of preconditioners while constructing preconditioners; perhaps they should be logged separately from the regular solves */ 1074 PetscCall(KSPInitializePackage()); 1075 PetscCall(PetscLogEventDeactivatePush(KSP_Solve)); 1076 PetscCall(PetscLogEventDeactivatePush(PC_Apply)); 1077 PetscUseTypeMethod(pc, setup); 1078 PetscCall(PetscLogEventDeactivatePop(KSP_Solve)); 1079 PetscCall(PetscLogEventDeactivatePop(PC_Apply)); 1080 } 1081 PetscCall(PetscLogEventEnd(PC_SetUp, pc, 0, 0, 0)); 1082 if (!pc->setupcalled) pc->setupcalled = 1; 1083 PetscFunctionReturn(PETSC_SUCCESS); 1084 } 1085 1086 /*@ 1087 PCSetUpOnBlocks - Sets up the preconditioner for each block in 1088 the block Jacobi, block Gauss-Seidel, and overlapping Schwarz 1089 methods. 1090 1091 Collective 1092 1093 Input Parameter: 1094 . pc - the preconditioner context 1095 1096 Level: developer 1097 1098 Note: 1099 For nested preconditioners such as `PCBJACOBI` `PCSetUp()` is not called on each sub-`KSP` when `PCSetUp()` is 1100 called on the outer `PC`, this routine ensures it is called. 1101 1102 .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCCreate()`, `PCApply()`, `PCDestroy()` 1103 @*/ 1104 PetscErrorCode PCSetUpOnBlocks(PC pc) 1105 { 1106 PetscFunctionBegin; 1107 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1108 if (!pc->ops->setuponblocks) PetscFunctionReturn(PETSC_SUCCESS); 1109 PetscCall(PetscLogEventBegin(PC_SetUpOnBlocks, pc, 0, 0, 0)); 1110 PetscUseTypeMethod(pc, setuponblocks); 1111 PetscCall(PetscLogEventEnd(PC_SetUpOnBlocks, pc, 0, 0, 0)); 1112 PetscFunctionReturn(PETSC_SUCCESS); 1113 } 1114 1115 /*@C 1116 PCSetModifySubMatrices - Sets a user-defined routine for modifying the 1117 submatrices that arise within certain subdomain-based preconditioners such as `PCASM` 1118 1119 Logically Collective 1120 1121 Input Parameters: 1122 + pc - the preconditioner context 1123 . func - routine for modifying the submatrices 1124 - ctx - optional user-defined context (may be `NULL`) 1125 1126 Calling sequence of `func`: 1127 + pc - the preconditioner context 1128 . nsub - number of index sets 1129 . row - an array of index sets that contain the global row numbers 1130 that comprise each local submatrix 1131 . col - an array of index sets that contain the global column numbers 1132 that comprise each local submatrix 1133 . submat - array of local submatrices 1134 - ctx - optional user-defined context for private data for the 1135 user-defined func routine (may be `NULL`) 1136 1137 Level: advanced 1138 1139 Notes: 1140 The basic submatrices are extracted from the preconditioner matrix as 1141 usual; the user can then alter these (for example, to set different boundary 1142 conditions for each submatrix) before they are used for the local solves. 1143 1144 `PCSetModifySubMatrices()` MUST be called before `KSPSetUp()` and 1145 `KSPSolve()`. 1146 1147 A routine set by `PCSetModifySubMatrices()` is currently called within 1148 the block Jacobi (`PCBJACOBI`) and additive Schwarz (`PCASM`) 1149 preconditioners. All other preconditioners ignore this routine. 1150 1151 .seealso: [](ch_ksp), `PC`, `PCBJACOBI`, `PCASM`, `PCModifySubMatrices()` 1152 @*/ 1153 PetscErrorCode PCSetModifySubMatrices(PC pc, PetscErrorCode (*func)(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx), void *ctx) 1154 { 1155 PetscFunctionBegin; 1156 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1157 pc->modifysubmatrices = func; 1158 pc->modifysubmatricesP = ctx; 1159 PetscFunctionReturn(PETSC_SUCCESS); 1160 } 1161 1162 /*@C 1163 PCModifySubMatrices - Calls an optional user-defined routine within 1164 certain preconditioners if one has been set with `PCSetModifySubMatrices()`. 1165 1166 Collective 1167 1168 Input Parameters: 1169 + pc - the preconditioner context 1170 . nsub - the number of local submatrices 1171 . row - an array of index sets that contain the global row numbers 1172 that comprise each local submatrix 1173 . col - an array of index sets that contain the global column numbers 1174 that comprise each local submatrix 1175 . submat - array of local submatrices 1176 - ctx - optional user-defined context for private data for the 1177 user-defined routine (may be `NULL`) 1178 1179 Output Parameter: 1180 . submat - array of local submatrices (the entries of which may 1181 have been modified) 1182 1183 Level: developer 1184 1185 Note: 1186 The user should NOT generally call this routine, as it will 1187 automatically be called within certain preconditioners. 1188 1189 .seealso: [](ch_ksp), `PC`, `PCSetModifySubMatrices()` 1190 @*/ 1191 PetscErrorCode PCModifySubMatrices(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx) 1192 { 1193 PetscFunctionBegin; 1194 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1195 if (!pc->modifysubmatrices) PetscFunctionReturn(PETSC_SUCCESS); 1196 PetscCall(PetscLogEventBegin(PC_ModifySubMatrices, pc, 0, 0, 0)); 1197 PetscCall((*pc->modifysubmatrices)(pc, nsub, row, col, submat, ctx)); 1198 PetscCall(PetscLogEventEnd(PC_ModifySubMatrices, pc, 0, 0, 0)); 1199 PetscFunctionReturn(PETSC_SUCCESS); 1200 } 1201 1202 /*@ 1203 PCSetOperators - Sets the matrix associated with the linear system and 1204 a (possibly) different one associated with the preconditioner. 1205 1206 Logically Collective 1207 1208 Input Parameters: 1209 + pc - the preconditioner context 1210 . Amat - the matrix that defines the linear system 1211 - Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat. 1212 1213 Level: intermediate 1214 1215 Notes: 1216 Passing a `NULL` for `Amat` or `Pmat` removes the matrix that is currently used. 1217 1218 If you wish to replace either `Amat` or `Pmat` but leave the other one untouched then 1219 first call `KSPGetOperators()` to get the one you wish to keep, call `PetscObjectReference()` 1220 on it and then pass it back in in your call to `KSPSetOperators()`. 1221 1222 More Notes about Repeated Solution of Linear Systems: 1223 PETSc does NOT reset the matrix entries of either `Amat` or `Pmat` 1224 to zero after a linear solve; the user is completely responsible for 1225 matrix assembly. See the routine `MatZeroEntries()` if desiring to 1226 zero all elements of a matrix. 1227 1228 .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()` 1229 @*/ 1230 PetscErrorCode PCSetOperators(PC pc, Mat Amat, Mat Pmat) 1231 { 1232 PetscInt m1, n1, m2, n2; 1233 1234 PetscFunctionBegin; 1235 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1236 if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 1237 if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 1238 if (Amat) PetscCheckSameComm(pc, 1, Amat, 2); 1239 if (Pmat) PetscCheckSameComm(pc, 1, Pmat, 3); 1240 if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) { 1241 PetscCall(MatGetLocalSize(Amat, &m1, &n1)); 1242 PetscCall(MatGetLocalSize(pc->mat, &m2, &n2)); 1243 PetscCheck(m1 == m2 && n1 == n2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot change local size of Amat after use old sizes %" PetscInt_FMT " %" PetscInt_FMT " new sizes %" PetscInt_FMT " %" PetscInt_FMT, m2, n2, m1, n1); 1244 PetscCall(MatGetLocalSize(Pmat, &m1, &n1)); 1245 PetscCall(MatGetLocalSize(pc->pmat, &m2, &n2)); 1246 PetscCheck(m1 == m2 && n1 == n2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Cannot change local size of Pmat after use old sizes %" PetscInt_FMT " %" PetscInt_FMT " new sizes %" PetscInt_FMT " %" PetscInt_FMT, m2, n2, m1, n1); 1247 } 1248 1249 if (Pmat != pc->pmat) { 1250 /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */ 1251 pc->matnonzerostate = -1; 1252 pc->matstate = -1; 1253 } 1254 1255 /* reference first in case the matrices are the same */ 1256 if (Amat) PetscCall(PetscObjectReference((PetscObject)Amat)); 1257 PetscCall(MatDestroy(&pc->mat)); 1258 if (Pmat) PetscCall(PetscObjectReference((PetscObject)Pmat)); 1259 PetscCall(MatDestroy(&pc->pmat)); 1260 pc->mat = Amat; 1261 pc->pmat = Pmat; 1262 PetscFunctionReturn(PETSC_SUCCESS); 1263 } 1264 1265 /*@ 1266 PCSetReusePreconditioner - reuse the current preconditioner even if the operator in the preconditioner has changed. 1267 1268 Logically Collective 1269 1270 Input Parameters: 1271 + pc - the preconditioner context 1272 - flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner 1273 1274 Level: intermediate 1275 1276 Note: 1277 Normally if a matrix inside a `PC` changes the `PC` automatically updates itself using information from the changed matrix. This option 1278 prevents this. 1279 1280 .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCGetReusePreconditioner()`, `KSPSetReusePreconditioner()` 1281 @*/ 1282 PetscErrorCode PCSetReusePreconditioner(PC pc, PetscBool flag) 1283 { 1284 PetscFunctionBegin; 1285 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1286 PetscValidLogicalCollectiveBool(pc, flag, 2); 1287 pc->reusepreconditioner = flag; 1288 PetscFunctionReturn(PETSC_SUCCESS); 1289 } 1290 1291 /*@ 1292 PCGetReusePreconditioner - Determines if the `PC` reuses the current preconditioner even if the operator in the preconditioner has changed. 1293 1294 Not Collective 1295 1296 Input Parameter: 1297 . pc - the preconditioner context 1298 1299 Output Parameter: 1300 . flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner 1301 1302 Level: intermediate 1303 1304 .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCSetReusePreconditioner()` 1305 @*/ 1306 PetscErrorCode PCGetReusePreconditioner(PC pc, PetscBool *flag) 1307 { 1308 PetscFunctionBegin; 1309 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1310 PetscAssertPointer(flag, 2); 1311 *flag = pc->reusepreconditioner; 1312 PetscFunctionReturn(PETSC_SUCCESS); 1313 } 1314 1315 /*@ 1316 PCGetOperators - Gets the matrix associated with the linear system and 1317 possibly a different one associated with the preconditioner. 1318 1319 Not Collective, though parallel `Mat`s are returned if `pc` is parallel 1320 1321 Input Parameter: 1322 . pc - the preconditioner context 1323 1324 Output Parameters: 1325 + Amat - the matrix defining the linear system 1326 - Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat. 1327 1328 Level: intermediate 1329 1330 Note: 1331 Does not increase the reference count of the matrices, so you should not destroy them 1332 1333 Alternative usage: If the operators have NOT been set with `KSPSetOperators()`/`PCSetOperators()` then the operators 1334 are created in `PC` and returned to the user. In this case, if both operators 1335 mat and pmat are requested, two DIFFERENT operators will be returned. If 1336 only one is requested both operators in the PC will be the same (i.e. as 1337 if one had called `KSPSetOperators()`/`PCSetOperators()` with the same argument for both Mats). 1338 The user must set the sizes of the returned matrices and their type etc just 1339 as if the user created them with `MatCreate()`. For example, 1340 1341 .vb 1342 KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to 1343 set size, type, etc of Amat 1344 1345 MatCreate(comm,&mat); 1346 KSP/PCSetOperators(ksp/pc,Amat,Amat); 1347 PetscObjectDereference((PetscObject)mat); 1348 set size, type, etc of Amat 1349 .ve 1350 1351 and 1352 1353 .vb 1354 KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to 1355 set size, type, etc of Amat and Pmat 1356 1357 MatCreate(comm,&Amat); 1358 MatCreate(comm,&Pmat); 1359 KSP/PCSetOperators(ksp/pc,Amat,Pmat); 1360 PetscObjectDereference((PetscObject)Amat); 1361 PetscObjectDereference((PetscObject)Pmat); 1362 set size, type, etc of Amat and Pmat 1363 .ve 1364 1365 The rationale for this support is so that when creating a `TS`, `SNES`, or `KSP` the hierarchy 1366 of underlying objects (i.e. `SNES`, `KSP`, `PC`, `Mat`) and their lifespans can be completely 1367 managed by the top most level object (i.e. the `TS`, `SNES`, or `KSP`). Another way to look 1368 at this is when you create a `SNES` you do not NEED to create a `KSP` and attach it to 1369 the `SNES` object (the `SNES` object manages it for you). Similarly when you create a KSP 1370 you do not need to attach a `PC` to it (the `KSP` object manages the `PC` object for you). 1371 Thus, why should YOU have to create the `Mat` and attach it to the `SNES`/`KSP`/`PC`, when 1372 it can be created for you? 1373 1374 .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperatorsSet()` 1375 @*/ 1376 PetscErrorCode PCGetOperators(PC pc, Mat *Amat, Mat *Pmat) 1377 { 1378 PetscFunctionBegin; 1379 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1380 if (Amat) { 1381 if (!pc->mat) { 1382 if (pc->pmat && !Pmat) { /* Pmat has been set, but user did not request it, so use for Amat */ 1383 pc->mat = pc->pmat; 1384 PetscCall(PetscObjectReference((PetscObject)pc->mat)); 1385 } else { /* both Amat and Pmat are empty */ 1386 PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->mat)); 1387 if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */ 1388 pc->pmat = pc->mat; 1389 PetscCall(PetscObjectReference((PetscObject)pc->pmat)); 1390 } 1391 } 1392 } 1393 *Amat = pc->mat; 1394 } 1395 if (Pmat) { 1396 if (!pc->pmat) { 1397 if (pc->mat && !Amat) { /* Amat has been set but was not requested, so use for pmat */ 1398 pc->pmat = pc->mat; 1399 PetscCall(PetscObjectReference((PetscObject)pc->pmat)); 1400 } else { 1401 PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->pmat)); 1402 if (!Amat) { /* user did NOT request Amat, so make same as Pmat */ 1403 pc->mat = pc->pmat; 1404 PetscCall(PetscObjectReference((PetscObject)pc->mat)); 1405 } 1406 } 1407 } 1408 *Pmat = pc->pmat; 1409 } 1410 PetscFunctionReturn(PETSC_SUCCESS); 1411 } 1412 1413 /*@ 1414 PCGetOperatorsSet - Determines if the matrix associated with the linear system and 1415 possibly a different one associated with the preconditioner have been set in the `PC`. 1416 1417 Not Collective, though the results on all processes should be the same 1418 1419 Input Parameter: 1420 . pc - the preconditioner context 1421 1422 Output Parameters: 1423 + mat - the matrix associated with the linear system was set 1424 - pmat - matrix associated with the preconditioner was set, usually the same 1425 1426 Level: intermediate 1427 1428 .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperators()` 1429 @*/ 1430 PetscErrorCode PCGetOperatorsSet(PC pc, PetscBool *mat, PetscBool *pmat) 1431 { 1432 PetscFunctionBegin; 1433 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1434 if (mat) *mat = (pc->mat) ? PETSC_TRUE : PETSC_FALSE; 1435 if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE; 1436 PetscFunctionReturn(PETSC_SUCCESS); 1437 } 1438 1439 /*@ 1440 PCFactorGetMatrix - Gets the factored matrix from the 1441 preconditioner context. This routine is valid only for the `PCLU`, 1442 `PCILU`, `PCCHOLESKY`, and `PCICC` methods. 1443 1444 Not Collective though `mat` is parallel if `pc` is parallel 1445 1446 Input Parameter: 1447 . pc - the preconditioner context 1448 1449 Output Parameters: 1450 . mat - the factored matrix 1451 1452 Level: advanced 1453 1454 Note: 1455 Does not increase the reference count for `mat` so DO NOT destroy it 1456 1457 .seealso: [](ch_ksp), `PC`, `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 1458 @*/ 1459 PetscErrorCode PCFactorGetMatrix(PC pc, Mat *mat) 1460 { 1461 PetscFunctionBegin; 1462 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1463 PetscAssertPointer(mat, 2); 1464 PetscCall(PCFactorSetUpMatSolverType(pc)); 1465 PetscUseTypeMethod(pc, getfactoredmatrix, mat); 1466 PetscFunctionReturn(PETSC_SUCCESS); 1467 } 1468 1469 /*@ 1470 PCSetOptionsPrefix - Sets the prefix used for searching for all 1471 `PC` options in the database. 1472 1473 Logically Collective 1474 1475 Input Parameters: 1476 + pc - the preconditioner context 1477 - prefix - the prefix string to prepend to all `PC` option requests 1478 1479 Note: 1480 A hyphen (-) must NOT be given at the beginning of the prefix name. 1481 The first character of all runtime options is AUTOMATICALLY the 1482 hyphen. 1483 1484 Level: advanced 1485 1486 .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCAppendOptionsPrefix()`, `PCGetOptionsPrefix()` 1487 @*/ 1488 PetscErrorCode PCSetOptionsPrefix(PC pc, const char prefix[]) 1489 { 1490 PetscFunctionBegin; 1491 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1492 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)pc, prefix)); 1493 PetscFunctionReturn(PETSC_SUCCESS); 1494 } 1495 1496 /*@ 1497 PCAppendOptionsPrefix - Appends to the prefix used for searching for all 1498 `PC` options in the database. 1499 1500 Logically Collective 1501 1502 Input Parameters: 1503 + pc - the preconditioner context 1504 - prefix - the prefix string to prepend to all `PC` option requests 1505 1506 Note: 1507 A hyphen (-) must NOT be given at the beginning of the prefix name. 1508 The first character of all runtime options is AUTOMATICALLY the 1509 hyphen. 1510 1511 Level: advanced 1512 1513 .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCGetOptionsPrefix()` 1514 @*/ 1515 PetscErrorCode PCAppendOptionsPrefix(PC pc, const char prefix[]) 1516 { 1517 PetscFunctionBegin; 1518 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1519 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)pc, prefix)); 1520 PetscFunctionReturn(PETSC_SUCCESS); 1521 } 1522 1523 /*@ 1524 PCGetOptionsPrefix - Gets the prefix used for searching for all 1525 PC options in the database. 1526 1527 Not Collective 1528 1529 Input Parameter: 1530 . pc - the preconditioner context 1531 1532 Output Parameter: 1533 . prefix - pointer to the prefix string used, is returned 1534 1535 Level: advanced 1536 1537 Fortran Note: 1538 The user should pass in a string `prefix` of 1539 sufficient length to hold the prefix. 1540 1541 .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCAppendOptionsPrefix()` 1542 @*/ 1543 PetscErrorCode PCGetOptionsPrefix(PC pc, const char *prefix[]) 1544 { 1545 PetscFunctionBegin; 1546 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1547 PetscAssertPointer(prefix, 2); 1548 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc, prefix)); 1549 PetscFunctionReturn(PETSC_SUCCESS); 1550 } 1551 1552 /* 1553 Indicates the right-hand side will be changed by KSPSolve(), this occurs for a few 1554 preconditioners including BDDC and Eisentat that transform the equations before applying 1555 the Krylov methods 1556 */ 1557 PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC pc, PetscBool *change) 1558 { 1559 PetscFunctionBegin; 1560 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1561 PetscAssertPointer(change, 2); 1562 *change = PETSC_FALSE; 1563 PetscTryMethod(pc, "PCPreSolveChangeRHS_C", (PC, PetscBool *), (pc, change)); 1564 PetscFunctionReturn(PETSC_SUCCESS); 1565 } 1566 1567 /*@ 1568 PCPreSolve - Optional pre-solve phase, intended for any 1569 preconditioner-specific actions that must be performed before 1570 the iterative solve itself. 1571 1572 Collective 1573 1574 Input Parameters: 1575 + pc - the preconditioner context 1576 - ksp - the Krylov subspace context 1577 1578 Level: developer 1579 1580 Example Usage: 1581 .vb 1582 PCPreSolve(pc,ksp); 1583 KSPSolve(ksp,b,x); 1584 PCPostSolve(pc,ksp); 1585 .ve 1586 1587 Notes: 1588 The pre-solve phase is distinct from the `PCSetUp()` phase. 1589 1590 `KSPSolve()` calls this directly, so is rarely called by the user. 1591 1592 .seealso: [](ch_ksp), `PC`, `PCPostSolve()` 1593 @*/ 1594 PetscErrorCode PCPreSolve(PC pc, KSP ksp) 1595 { 1596 Vec x, rhs; 1597 1598 PetscFunctionBegin; 1599 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1600 PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 1601 pc->presolvedone++; 1602 PetscCheck(pc->presolvedone <= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot embed PCPreSolve() more than twice"); 1603 PetscCall(KSPGetSolution(ksp, &x)); 1604 PetscCall(KSPGetRhs(ksp, &rhs)); 1605 1606 if (pc->ops->presolve) PetscUseTypeMethod(pc, presolve, ksp, rhs, x); 1607 else if (pc->presolve) PetscCall(pc->presolve(pc, ksp)); 1608 PetscFunctionReturn(PETSC_SUCCESS); 1609 } 1610 1611 /*@C 1612 PCSetPreSolve - Sets function used by `PCPreSolve()` which is intended for any 1613 preconditioner-specific actions that must be performed before 1614 the iterative solve itself. 1615 1616 Logically Collective 1617 1618 Input Parameters: 1619 + pc - the preconditioner object 1620 - presolve - the function to call before the solve 1621 1622 Calling sequence of `presolve`: 1623 + pc - the `PC` context 1624 - ksp - the `KSP` context 1625 1626 Level: developer 1627 1628 .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCPreSolve()` 1629 @*/ 1630 PetscErrorCode PCSetPreSolve(PC pc, PetscErrorCode (*presolve)(PC pc, KSP ksp)) 1631 { 1632 PetscFunctionBegin; 1633 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1634 pc->presolve = presolve; 1635 PetscFunctionReturn(PETSC_SUCCESS); 1636 } 1637 1638 /*@ 1639 PCPostSolve - Optional post-solve phase, intended for any 1640 preconditioner-specific actions that must be performed after 1641 the iterative solve itself. 1642 1643 Collective 1644 1645 Input Parameters: 1646 + pc - the preconditioner context 1647 - ksp - the Krylov subspace context 1648 1649 Example Usage: 1650 .vb 1651 PCPreSolve(pc,ksp); 1652 KSPSolve(ksp,b,x); 1653 PCPostSolve(pc,ksp); 1654 .ve 1655 1656 Level: developer 1657 1658 Note: 1659 `KSPSolve()` calls this routine directly, so it is rarely called by the user. 1660 1661 .seealso: [](ch_ksp), `PC`, `PCSetPostSolve()`, `PCSetPresolve()`, `PCPreSolve()`, `KSPSolve()` 1662 @*/ 1663 PetscErrorCode PCPostSolve(PC pc, KSP ksp) 1664 { 1665 Vec x, rhs; 1666 1667 PetscFunctionBegin; 1668 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1669 PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 1670 pc->presolvedone--; 1671 PetscCall(KSPGetSolution(ksp, &x)); 1672 PetscCall(KSPGetRhs(ksp, &rhs)); 1673 PetscTryTypeMethod(pc, postsolve, ksp, rhs, x); 1674 PetscFunctionReturn(PETSC_SUCCESS); 1675 } 1676 1677 /*@ 1678 PCLoad - Loads a `PC` that has been stored in binary with `PCView()`. 1679 1680 Collective 1681 1682 Input Parameters: 1683 + newdm - the newly loaded `PC`, this needs to have been created with `PCCreate()` or 1684 some related function before a call to `PCLoad()`. 1685 - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 1686 1687 Level: intermediate 1688 1689 Note: 1690 The type is determined by the data in the file, any `PCType` set into the `PC` before this call is ignored. 1691 1692 .seealso: [](ch_ksp), `PC`, `PetscViewerBinaryOpen()`, `PCView()`, `MatLoad()`, `VecLoad()` 1693 @*/ 1694 PetscErrorCode PCLoad(PC newdm, PetscViewer viewer) 1695 { 1696 PetscBool isbinary; 1697 PetscInt classid; 1698 char type[256]; 1699 1700 PetscFunctionBegin; 1701 PetscValidHeaderSpecific(newdm, PC_CLASSID, 1); 1702 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1703 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 1704 PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 1705 1706 PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 1707 PetscCheck(classid == PC_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not PC next in file"); 1708 PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 1709 PetscCall(PCSetType(newdm, type)); 1710 PetscTryTypeMethod(newdm, load, viewer); 1711 PetscFunctionReturn(PETSC_SUCCESS); 1712 } 1713 1714 #include <petscdraw.h> 1715 #if defined(PETSC_HAVE_SAWS) 1716 #include <petscviewersaws.h> 1717 #endif 1718 1719 /*@ 1720 PCViewFromOptions - View from the `PC` based on options in the options database 1721 1722 Collective 1723 1724 Input Parameters: 1725 + A - the `PC` context 1726 . obj - Optional object that provides the options prefix 1727 - name - command line option 1728 1729 Level: intermediate 1730 1731 .seealso: [](ch_ksp), `PC`, `PCView`, `PetscObjectViewFromOptions()`, `PCCreate()` 1732 @*/ 1733 PetscErrorCode PCViewFromOptions(PC A, PetscObject obj, const char name[]) 1734 { 1735 PetscFunctionBegin; 1736 PetscValidHeaderSpecific(A, PC_CLASSID, 1); 1737 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1738 PetscFunctionReturn(PETSC_SUCCESS); 1739 } 1740 1741 /*@ 1742 PCView - Prints information about the `PC` 1743 1744 Collective 1745 1746 Input Parameters: 1747 + pc - the `PC` context 1748 - viewer - optional visualization context 1749 1750 Level: developer 1751 1752 Notes: 1753 The available visualization contexts include 1754 + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 1755 - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 1756 output where only the first processor opens 1757 the file. All other processors send their 1758 data to the first processor to print. 1759 1760 The user can open an alternative visualization contexts with 1761 `PetscViewerASCIIOpen()` (output to a specified file). 1762 1763 .seealso: [](ch_ksp), `PC`, `PetscViewer`, `KSPView()`, `PetscViewerASCIIOpen()` 1764 @*/ 1765 PetscErrorCode PCView(PC pc, PetscViewer viewer) 1766 { 1767 PCType cstr; 1768 PetscViewerFormat format; 1769 PetscBool iascii, isstring, isbinary, isdraw, pop = PETSC_FALSE; 1770 #if defined(PETSC_HAVE_SAWS) 1771 PetscBool issaws; 1772 #endif 1773 1774 PetscFunctionBegin; 1775 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1776 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer)); 1777 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1778 PetscCheckSameComm(pc, 1, viewer, 2); 1779 1780 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 1781 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1782 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 1783 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 1784 #if defined(PETSC_HAVE_SAWS) 1785 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1786 #endif 1787 1788 if (iascii) { 1789 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pc, viewer)); 1790 if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " PC has not been set up so information may be incomplete\n")); 1791 PetscCall(PetscViewerASCIIPushTab(viewer)); 1792 PetscTryTypeMethod(pc, view, viewer); 1793 PetscCall(PetscViewerASCIIPopTab(viewer)); 1794 if (pc->mat) { 1795 PetscCall(PetscViewerGetFormat(viewer, &format)); 1796 if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) { 1797 PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO)); 1798 pop = PETSC_TRUE; 1799 } 1800 if (pc->pmat == pc->mat) { 1801 PetscCall(PetscViewerASCIIPrintf(viewer, " linear system matrix = precond matrix:\n")); 1802 PetscCall(PetscViewerASCIIPushTab(viewer)); 1803 PetscCall(MatView(pc->mat, viewer)); 1804 PetscCall(PetscViewerASCIIPopTab(viewer)); 1805 } else { 1806 if (pc->pmat) { 1807 PetscCall(PetscViewerASCIIPrintf(viewer, " linear system matrix followed by preconditioner matrix:\n")); 1808 } else { 1809 PetscCall(PetscViewerASCIIPrintf(viewer, " linear system matrix:\n")); 1810 } 1811 PetscCall(PetscViewerASCIIPushTab(viewer)); 1812 PetscCall(MatView(pc->mat, viewer)); 1813 if (pc->pmat) PetscCall(MatView(pc->pmat, viewer)); 1814 PetscCall(PetscViewerASCIIPopTab(viewer)); 1815 } 1816 if (pop) PetscCall(PetscViewerPopFormat(viewer)); 1817 } 1818 } else if (isstring) { 1819 PetscCall(PCGetType(pc, &cstr)); 1820 PetscCall(PetscViewerStringSPrintf(viewer, " PCType: %-7.7s", cstr)); 1821 PetscTryTypeMethod(pc, view, viewer); 1822 if (pc->mat) PetscCall(MatView(pc->mat, viewer)); 1823 if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer)); 1824 } else if (isbinary) { 1825 PetscInt classid = PC_FILE_CLASSID; 1826 MPI_Comm comm; 1827 PetscMPIInt rank; 1828 char type[256]; 1829 1830 PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 1831 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1832 if (rank == 0) { 1833 PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 1834 PetscCall(PetscStrncpy(type, ((PetscObject)pc)->type_name, 256)); 1835 PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR)); 1836 } 1837 PetscTryTypeMethod(pc, view, viewer); 1838 } else if (isdraw) { 1839 PetscDraw draw; 1840 char str[25]; 1841 PetscReal x, y, bottom, h; 1842 PetscInt n; 1843 1844 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 1845 PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 1846 if (pc->mat) { 1847 PetscCall(MatGetSize(pc->mat, &n, NULL)); 1848 PetscCall(PetscSNPrintf(str, 25, "PC: %s (%" PetscInt_FMT ")", ((PetscObject)pc)->type_name, n)); 1849 } else { 1850 PetscCall(PetscSNPrintf(str, 25, "PC: %s", ((PetscObject)pc)->type_name)); 1851 } 1852 PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_RED, PETSC_DRAW_BLACK, str, NULL, &h)); 1853 bottom = y - h; 1854 PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 1855 PetscTryTypeMethod(pc, view, viewer); 1856 PetscCall(PetscDrawPopCurrentPoint(draw)); 1857 #if defined(PETSC_HAVE_SAWS) 1858 } else if (issaws) { 1859 PetscMPIInt rank; 1860 1861 PetscCall(PetscObjectName((PetscObject)pc)); 1862 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1863 if (!((PetscObject)pc)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)pc, viewer)); 1864 if (pc->mat) PetscCall(MatView(pc->mat, viewer)); 1865 if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer)); 1866 #endif 1867 } 1868 PetscFunctionReturn(PETSC_SUCCESS); 1869 } 1870 1871 /*@C 1872 PCRegister - Adds a method (`PCType`) to the preconditioner package. 1873 1874 Not collective. No Fortran Support 1875 1876 Input Parameters: 1877 + sname - name of a new user-defined solver 1878 - function - routine to create method context 1879 1880 Example Usage: 1881 .vb 1882 PCRegister("my_solver", MySolverCreate); 1883 .ve 1884 1885 Then, your solver can be chosen with the procedural interface via 1886 $ PCSetType(pc, "my_solver") 1887 or at runtime via the option 1888 $ -pc_type my_solver 1889 1890 Level: advanced 1891 1892 Note: 1893 `PCRegister()` may be called multiple times to add several user-defined preconditioners. 1894 1895 .seealso: [](ch_ksp), `PC`, `PCType`, `PCRegisterAll()` 1896 @*/ 1897 PetscErrorCode PCRegister(const char sname[], PetscErrorCode (*function)(PC)) 1898 { 1899 PetscFunctionBegin; 1900 PetscCall(PCInitializePackage()); 1901 PetscCall(PetscFunctionListAdd(&PCList, sname, function)); 1902 PetscFunctionReturn(PETSC_SUCCESS); 1903 } 1904 1905 static PetscErrorCode MatMult_PC(Mat A, Vec X, Vec Y) 1906 { 1907 PC pc; 1908 1909 PetscFunctionBegin; 1910 PetscCall(MatShellGetContext(A, &pc)); 1911 PetscCall(PCApply(pc, X, Y)); 1912 PetscFunctionReturn(PETSC_SUCCESS); 1913 } 1914 1915 /*@ 1916 PCComputeOperator - Computes the explicit preconditioned operator. 1917 1918 Collective 1919 1920 Input Parameters: 1921 + pc - the preconditioner object 1922 - mattype - the `MatType` to be used for the operator 1923 1924 Output Parameter: 1925 . mat - the explicit preconditioned operator 1926 1927 Level: advanced 1928 1929 Note: 1930 This computation is done by applying the operators to columns of the identity matrix. 1931 This routine is costly in general, and is recommended for use only with relatively small systems. 1932 Currently, this routine uses a dense matrix format when `mattype` == `NULL` 1933 1934 .seealso: [](ch_ksp), `PC`, `KSPComputeOperator()`, `MatType` 1935 @*/ 1936 PetscErrorCode PCComputeOperator(PC pc, MatType mattype, Mat *mat) 1937 { 1938 PetscInt N, M, m, n; 1939 Mat A, Apc; 1940 1941 PetscFunctionBegin; 1942 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1943 PetscAssertPointer(mat, 3); 1944 PetscCall(PCGetOperators(pc, &A, NULL)); 1945 PetscCall(MatGetLocalSize(A, &m, &n)); 1946 PetscCall(MatGetSize(A, &M, &N)); 1947 PetscCall(MatCreateShell(PetscObjectComm((PetscObject)pc), m, n, M, N, pc, &Apc)); 1948 PetscCall(MatShellSetOperation(Apc, MATOP_MULT, (void (*)(void))MatMult_PC)); 1949 PetscCall(MatComputeOperator(Apc, mattype, mat)); 1950 PetscCall(MatDestroy(&Apc)); 1951 PetscFunctionReturn(PETSC_SUCCESS); 1952 } 1953 1954 /*@ 1955 PCSetCoordinates - sets the coordinates of all the nodes on the local process 1956 1957 Collective 1958 1959 Input Parameters: 1960 + pc - the solver context 1961 . dim - the dimension of the coordinates 1, 2, or 3 1962 . nloc - the blocked size of the coordinates array 1963 - coords - the coordinates array 1964 1965 Level: intermediate 1966 1967 Note: 1968 `coords` is an array of the dim coordinates for the nodes on 1969 the local processor, of size `dim`*`nloc`. 1970 If there are 108 equation on a processor 1971 for a displacement finite element discretization of elasticity (so 1972 that there are nloc = 36 = 108/3 nodes) then the array must have 108 1973 double precision values (ie, 3 * 36). These x y z coordinates 1974 should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x, 1975 ... , N-1.z ]. 1976 1977 .seealso: [](ch_ksp), `PC`, `MatSetNearNullSpace()` 1978 @*/ 1979 PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal coords[]) 1980 { 1981 PetscFunctionBegin; 1982 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1983 PetscValidLogicalCollectiveInt(pc, dim, 2); 1984 PetscTryMethod(pc, "PCSetCoordinates_C", (PC, PetscInt, PetscInt, PetscReal[]), (pc, dim, nloc, coords)); 1985 PetscFunctionReturn(PETSC_SUCCESS); 1986 } 1987 1988 /*@ 1989 PCGetInterpolations - Gets interpolation matrices for all levels (except level 0) 1990 1991 Logically Collective 1992 1993 Input Parameter: 1994 . pc - the precondition context 1995 1996 Output Parameters: 1997 + num_levels - the number of levels 1998 - interpolations - the interpolation matrices (size of `num_levels`-1) 1999 2000 Level: advanced 2001 2002 Developer Note: 2003 Why is this here instead of in `PCMG` etc? 2004 2005 .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetInterpolation()`, `PCGetCoarseOperators()` 2006 @*/ 2007 PetscErrorCode PCGetInterpolations(PC pc, PetscInt *num_levels, Mat *interpolations[]) 2008 { 2009 PetscFunctionBegin; 2010 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 2011 PetscAssertPointer(num_levels, 2); 2012 PetscAssertPointer(interpolations, 3); 2013 PetscUseMethod(pc, "PCGetInterpolations_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, interpolations)); 2014 PetscFunctionReturn(PETSC_SUCCESS); 2015 } 2016 2017 /*@ 2018 PCGetCoarseOperators - Gets coarse operator matrices for all levels (except the finest level) 2019 2020 Logically Collective 2021 2022 Input Parameter: 2023 . pc - the precondition context 2024 2025 Output Parameters: 2026 + num_levels - the number of levels 2027 - coarseOperators - the coarse operator matrices (size of `num_levels`-1) 2028 2029 Level: advanced 2030 2031 Developer Note: 2032 Why is this here instead of in `PCMG` etc? 2033 2034 .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()` 2035 @*/ 2036 PetscErrorCode PCGetCoarseOperators(PC pc, PetscInt *num_levels, Mat *coarseOperators[]) 2037 { 2038 PetscFunctionBegin; 2039 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 2040 PetscAssertPointer(num_levels, 2); 2041 PetscAssertPointer(coarseOperators, 3); 2042 PetscUseMethod(pc, "PCGetCoarseOperators_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, coarseOperators)); 2043 PetscFunctionReturn(PETSC_SUCCESS); 2044 } 2045