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