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