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