Date: 2025-03-29T05:58:31+00:00

Actual source code: precon.c

      1: /*
      2:     The PC (preconditioner) interface routines, callable by users.
      3: */
      4: #include <petsc/private/pcimpl.h>
      5: #include <petscdm.h>

      7: /* Logging support */
      8: PetscClassId  PC_CLASSID;
      9: PetscLogEvent PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_MatApply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft;
     10: PetscLogEvent PC_ApplySymmetricRight, PC_ModifySubMatrices, PC_ApplyOnBlocks, PC_ApplyTransposeOnBlocks;
     11: PetscInt      PetscMGLevelId;
     12: PetscLogStage PCMPIStage;

     14: PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC pc, const char *type[])
     15: {
     16:   PetscMPIInt size;
     17:   PetscBool   hasopblock, hasopsolve, flg1, flg2, set, flg3, isnormal;

     19:   PetscFunctionBegin;
     20:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
     21:   if (pc->pmat) {
     22:     PetscCall(MatHasOperation(pc->pmat, MATOP_GET_DIAGONAL_BLOCK, &hasopblock));
     23:     PetscCall(MatHasOperation(pc->pmat, MATOP_SOLVE, &hasopsolve));
     24:     if (size == 1) {
     25:       PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ICC, &flg1));
     26:       PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ILU, &flg2));
     27:       PetscCall(MatIsSymmetricKnown(pc->pmat, &set, &flg3));
     28:       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &isnormal, MATNORMAL, MATNORMALHERMITIAN, NULL));
     29:       if (flg1 && (!flg2 || (set && flg3))) {
     30:         *type = PCICC;
     31:       } else if (flg2) {
     32:         *type = PCILU;
     33:       } else if (isnormal) {
     34:         *type = PCNONE;
     35:       } else if (hasopblock) { /* likely is a parallel matrix run on one processor */
     36:         *type = PCBJACOBI;
     37:       } else if (hasopsolve) {
     38:         *type = PCMAT;
     39:       } else {
     40:         *type = PCNONE;
     41:       }
     42:     } else {
     43:       if (hasopblock) {
     44:         *type = PCBJACOBI;
     45:       } else if (hasopsolve) {
     46:         *type = PCMAT;
     47:       } else {
     48:         *type = PCNONE;
     49:       }
     50:     }
     51:   } else *type = NULL;
     52:   PetscFunctionReturn(PETSC_SUCCESS);
     53: }

     55: /* do not log solves, setup and applications of preconditioners while constructing preconditioners; perhaps they should be logged separately from the regular solves */
     56: PETSC_EXTERN PetscLogEvent KSP_Solve, KSP_SetUp;

     58: static PetscErrorCode PCLogEventsDeactivatePush(void)
     59: {
     60:   PetscFunctionBegin;
     61:   PetscCall(KSPInitializePackage());
     62:   PetscCall(PetscLogEventDeactivatePush(KSP_Solve));
     63:   PetscCall(PetscLogEventDeactivatePush(KSP_SetUp));
     64:   PetscCall(PetscLogEventDeactivatePush(PC_Apply));
     65:   PetscCall(PetscLogEventDeactivatePush(PC_SetUp));
     66:   PetscCall(PetscLogEventDeactivatePush(PC_SetUpOnBlocks));
     67:   PetscFunctionReturn(PETSC_SUCCESS);
     68: }

     70: static PetscErrorCode PCLogEventsDeactivatePop(void)
     71: {
     72:   PetscFunctionBegin;
     73:   PetscCall(KSPInitializePackage());
     74:   PetscCall(PetscLogEventDeactivatePop(KSP_Solve));
     75:   PetscCall(PetscLogEventDeactivatePop(KSP_SetUp));
     76:   PetscCall(PetscLogEventDeactivatePop(PC_Apply));
     77:   PetscCall(PetscLogEventDeactivatePop(PC_SetUp));
     78:   PetscCall(PetscLogEventDeactivatePop(PC_SetUpOnBlocks));
     79:   PetscFunctionReturn(PETSC_SUCCESS);
     80: }

     82: /*@
     83:   PCReset - Resets a `PC` context to the state it was in before `PCSetUp()` was called, and removes any allocated `Vec` and `Mat` from its data structure

     85:   Collective

     87:   Input Parameter:
     88: . pc - the `PC` preconditioner context

     90:   Level: developer

     92:   Notes:
     93:   Any options set, including those set with `KSPSetFromOptions()` remain.

     95:   This allows a `PC` to be reused for a different sized linear system but using the same options that have been previously set in `pc`

     97: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`
     98: @*/
     99: PetscErrorCode PCReset(PC pc)
    100: {
    101:   PetscFunctionBegin;
    103:   PetscTryTypeMethod(pc, reset);
    104:   PetscCall(VecDestroy(&pc->diagonalscaleright));
    105:   PetscCall(VecDestroy(&pc->diagonalscaleleft));
    106:   PetscCall(MatDestroy(&pc->pmat));
    107:   PetscCall(MatDestroy(&pc->mat));

    109:   pc->setupcalled = 0;
    110:   PetscFunctionReturn(PETSC_SUCCESS);
    111: }

    113: /*@
    114:   PCDestroy - Destroys `PC` context that was created with `PCCreate()`.

    116:   Collective

    118:   Input Parameter:
    119: . pc - the `PC` preconditioner context

    121:   Level: developer

    123: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`
    124: @*/
    125: PetscErrorCode PCDestroy(PC *pc)
    126: {
    127:   PetscFunctionBegin;
    128:   if (!*pc) PetscFunctionReturn(PETSC_SUCCESS);
    130:   if (--((PetscObject)*pc)->refct > 0) {
    131:     *pc = NULL;
    132:     PetscFunctionReturn(PETSC_SUCCESS);
    133:   }

    135:   PetscCall(PCReset(*pc));

    137:   /* if memory was published with SAWs then destroy it */
    138:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*pc));
    139:   PetscTryTypeMethod(*pc, destroy);
    140:   PetscCall(DMDestroy(&(*pc)->dm));
    141:   PetscCall(PetscHeaderDestroy(pc));
    142:   PetscFunctionReturn(PETSC_SUCCESS);
    143: }

    145: /*@
    146:   PCGetDiagonalScale - Indicates if the preconditioner applies an additional left and right
    147:   scaling as needed by certain time-stepping codes.

    149:   Logically Collective

    151:   Input Parameter:
    152: . pc - the `PC` preconditioner context

    154:   Output Parameter:
    155: . flag - `PETSC_TRUE` if it applies the scaling

    157:   Level: developer

    159:   Note:
    160:   If this returns `PETSC_TRUE` then the system solved via the Krylov method is, for left and right preconditioning,

    162:   $$
    163:   \begin{align*}
    164:   D M A D^{-1} y = D M b  \\
    165:   D A M D^{-1} z = D b.
    166:   \end{align*}
    167:   $$

    169: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCSetDiagonalScale()`
    170: @*/
    171: PetscErrorCode PCGetDiagonalScale(PC pc, PetscBool *flag)
    172: {
    173:   PetscFunctionBegin;
    175:   PetscAssertPointer(flag, 2);
    176:   *flag = pc->diagonalscale;
    177:   PetscFunctionReturn(PETSC_SUCCESS);
    178: }

    180: /*@
    181:   PCSetDiagonalScale - Indicates the left scaling to use to apply an additional left and right
    182:   scaling as needed by certain time-stepping codes.

    184:   Logically Collective

    186:   Input Parameters:
    187: + pc - the `PC` preconditioner context
    188: - s  - scaling vector

    190:   Level: intermediate

    192:   Notes:
    193:   The system solved via the Krylov method is, for left and right preconditioning,
    194:   $$
    195:   \begin{align*}
    196:   D M A D^{-1} y = D M b \\
    197:   D A M D^{-1} z = D b.
    198:   \end{align*}
    199:   $$

    201:   `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$.

    203: .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCGetDiagonalScale()`
    204: @*/
    205: PetscErrorCode PCSetDiagonalScale(PC pc, Vec s)
    206: {
    207:   PetscFunctionBegin;
    210:   pc->diagonalscale = PETSC_TRUE;

    212:   PetscCall(PetscObjectReference((PetscObject)s));
    213:   PetscCall(VecDestroy(&pc->diagonalscaleleft));

    215:   pc->diagonalscaleleft = s;

    217:   PetscCall(VecDuplicate(s, &pc->diagonalscaleright));
    218:   PetscCall(VecCopy(s, pc->diagonalscaleright));
    219:   PetscCall(VecReciprocal(pc->diagonalscaleright));
    220:   PetscFunctionReturn(PETSC_SUCCESS);
    221: }

    223: /*@
    224:   PCDiagonalScaleLeft - Scales a vector by the left scaling as needed by certain time-stepping codes.

    226:   Logically Collective

    228:   Input Parameters:
    229: + pc  - the `PC` preconditioner context
    230: . in  - input vector
    231: - out - scaled vector (maybe the same as in)

    233:   Level: intermediate

    235:   Notes:
    236:   The system solved via the Krylov method is, for left and right preconditioning,

    238:   $$
    239:   \begin{align*}
    240:   D M A D^{-1} y = D M b  \\
    241:   D A M D^{-1} z = D b.
    242:   \end{align*}
    243:   $$

    245:   `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$.

    247:   If diagonal scaling is turned off and `in` is not `out` then `in` is copied to `out`

    249: .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCSetDiagonalScale()`, `PCDiagonalScaleRight()`, `MatDiagonalScale()`
    250: @*/
    251: PetscErrorCode PCDiagonalScaleLeft(PC pc, Vec in, Vec out)
    252: {
    253:   PetscFunctionBegin;
    257:   if (pc->diagonalscale) {
    258:     PetscCall(VecPointwiseMult(out, pc->diagonalscaleleft, in));
    259:   } else if (in != out) {
    260:     PetscCall(VecCopy(in, out));
    261:   }
    262:   PetscFunctionReturn(PETSC_SUCCESS);
    263: }

    265: /*@
    266:   PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.

    268:   Logically Collective

    270:   Input Parameters:
    271: + pc  - the `PC` preconditioner context
    272: . in  - input vector
    273: - out - scaled vector (maybe the same as in)

    275:   Level: intermediate

    277:   Notes:
    278:   The system solved via the Krylov method is, for left and right preconditioning,

    280:   $$
    281:   \begin{align*}
    282:   D M A D^{-1} y = D M b  \\
    283:   D A M D^{-1} z = D b.
    284:   \end{align*}
    285:   $$

    287:   `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$.

    289:   If diagonal scaling is turned off and `in` is not `out` then `in` is copied to `out`

    291: .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCSetDiagonalScale()`, `MatDiagonalScale()`
    292: @*/
    293: PetscErrorCode PCDiagonalScaleRight(PC pc, Vec in, Vec out)
    294: {
    295:   PetscFunctionBegin;
    299:   if (pc->diagonalscale) {
    300:     PetscCall(VecPointwiseMult(out, pc->diagonalscaleright, in));
    301:   } else if (in != out) {
    302:     PetscCall(VecCopy(in, out));
    303:   }
    304:   PetscFunctionReturn(PETSC_SUCCESS);
    305: }

    307: /*@
    308:   PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the
    309:   operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`,
    310:   `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat.

    312:   Logically Collective

    314:   Input Parameters:
    315: + pc  - the `PC` preconditioner context
    316: - flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false)

    318:   Options Database Key:
    319: . -pc_use_amat <true,false> - use the amat argument to `KSPSetOperators()` or `PCSetOperators()` to apply the operator

    321:   Level: intermediate

    323:   Note:
    324:   For the common case in which the linear system matrix and the matrix used to construct the
    325:   preconditioner are identical, this routine has no affect.

    327: .seealso: [](ch_ksp), `PC`, `PCGetUseAmat()`, `PCBJACOBI`, `PCMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`,
    328:           `KSPSetOperators()`, `PCSetOperators()`
    329: @*/
    330: PetscErrorCode PCSetUseAmat(PC pc, PetscBool flg)
    331: {
    332:   PetscFunctionBegin;
    334:   pc->useAmat = flg;
    335:   PetscFunctionReturn(PETSC_SUCCESS);
    336: }

    338: /*@
    339:   PCSetErrorIfFailure - Causes `PC` to generate an error if a floating point exception, for example a zero pivot, is detected.

    341:   Logically Collective

    343:   Input Parameters:
    344: + pc  - iterative context obtained from `PCCreate()`
    345: - flg - `PETSC_TRUE` indicates you want the error generated

    347:   Level: advanced

    349:   Notes:
    350:   Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call `KSPGetConvergedReason()` after a `KSPSolve()`
    351:   to determine if it has converged or failed. Or use -ksp_error_if_not_converged to cause the program to terminate as soon as lack of convergence is
    352:   detected.

    354:   This is propagated into `KSP`s used by this `PC`, which then propagate it into `PC`s used by those `KSP`s

    356: .seealso: [](ch_ksp), `PC`, `KSPSetErrorIfNotConverged()`, `PCGetInitialGuessNonzero()`, `PCSetInitialGuessKnoll()`, `PCGetInitialGuessKnoll()`
    357: @*/
    358: PetscErrorCode PCSetErrorIfFailure(PC pc, PetscBool flg)
    359: {
    360:   PetscFunctionBegin;
    363:   pc->erroriffailure = flg;
    364:   PetscFunctionReturn(PETSC_SUCCESS);
    365: }

    367: /*@
    368:   PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the
    369:   operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`,
    370:   `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat.

    372:   Logically Collective

    374:   Input Parameter:
    375: . pc - the `PC` preconditioner context

    377:   Output Parameter:
    378: . flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false)

    380:   Level: intermediate

    382:   Note:
    383:   For the common case in which the linear system matrix and the matrix used to construct the
    384:   preconditioner are identical, this routine is does nothing.

    386: .seealso: [](ch_ksp), `PC`, `PCSetUseAmat()`, `PCBJACOBI`, `PCMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`
    387: @*/
    388: PetscErrorCode PCGetUseAmat(PC pc, PetscBool *flg)
    389: {
    390:   PetscFunctionBegin;
    392:   *flg = pc->useAmat;
    393:   PetscFunctionReturn(PETSC_SUCCESS);
    394: }

    396: /*@
    397:   PCSetKSPNestLevel - sets the amount of nesting the `KSP` that contains this `PC` has

    399:   Collective

    401:   Input Parameters:
    402: + pc    - the `PC`
    403: - level - the nest level

    405:   Level: developer

    407: .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPGetNestLevel()`, `PCGetKSPNestLevel()`, `KSPSetNestLevel()`
    408: @*/
    409: PetscErrorCode PCSetKSPNestLevel(PC pc, PetscInt level)
    410: {
    411:   PetscFunctionBegin;
    414:   pc->kspnestlevel = level;
    415:   PetscFunctionReturn(PETSC_SUCCESS);
    416: }

    418: /*@
    419:   PCGetKSPNestLevel - gets the amount of nesting the `KSP` that contains this `PC` has

    421:   Not Collective

    423:   Input Parameter:
    424: . pc - the `PC`

    426:   Output Parameter:
    427: . level - the nest level

    429:   Level: developer

    431: .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPSetNestLevel()`, `PCSetKSPNestLevel()`, `KSPGetNestLevel()`
    432: @*/
    433: PetscErrorCode PCGetKSPNestLevel(PC pc, PetscInt *level)
    434: {
    435:   PetscFunctionBegin;
    437:   PetscAssertPointer(level, 2);
    438:   *level = pc->kspnestlevel;
    439:   PetscFunctionReturn(PETSC_SUCCESS);
    440: }

    442: /*@
    443:   PCCreate - Creates a preconditioner context, `PC`

    445:   Collective

    447:   Input Parameter:
    448: . comm - MPI communicator

    450:   Output Parameter:
    451: . newpc - location to put the `PC` preconditioner context

    453:   Level: developer

    455:   Notes:
    456:   This is rarely called directly by users since `KSP` manages the `PC` objects it uses. Use `KSPGetPC()` to access the `PC` used by a `KSP`.

    458:   Use `PCSetType()` or `PCSetFromOptions()` with the option `-pc_type pctype` to set the `PCType` for this `PC`

    460:   The default preconditioner type `PCType` for sparse matrices is `PCILU` or `PCICC` with 0 fill on one process and block Jacobi (`PCBJACOBI`) with `PCILU` or `PCICC`
    461:   in parallel. For dense matrices it is always `PCNONE`.

    463: .seealso: [](ch_ksp), `PC`, `PCType`, `PCSetType`, `PCSetUp()`, `PCApply()`, `PCDestroy()`, `KSP`, `KSPGetPC()`
    464: @*/
    465: PetscErrorCode PCCreate(MPI_Comm comm, PC *newpc)
    466: {
    467:   PC pc;

    469:   PetscFunctionBegin;
    470:   PetscAssertPointer(newpc, 2);
    471:   PetscCall(PCInitializePackage());

    473:   PetscCall(PetscHeaderCreate(pc, PC_CLASSID, "PC", "Preconditioner", "PC", comm, PCDestroy, PCView));
    474:   pc->mat                  = NULL;
    475:   pc->pmat                 = NULL;
    476:   pc->setupcalled          = 0;
    477:   pc->setfromoptionscalled = 0;
    478:   pc->data                 = NULL;
    479:   pc->diagonalscale        = PETSC_FALSE;
    480:   pc->diagonalscaleleft    = NULL;
    481:   pc->diagonalscaleright   = NULL;

    483:   pc->modifysubmatrices  = NULL;
    484:   pc->modifysubmatricesP = NULL;

    486:   *newpc = pc;
    487:   PetscFunctionReturn(PETSC_SUCCESS);
    488: }

    490: /*@
    491:   PCApply - Applies the preconditioner to a vector.

    493:   Collective

    495:   Input Parameters:
    496: + pc - the `PC` preconditioner context
    497: - x  - input vector

    499:   Output Parameter:
    500: . y - output vector

    502:   Level: developer

    504: .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`, `PCApplyBAorAB()`
    505: @*/
    506: PetscErrorCode PCApply(PC pc, Vec x, Vec y)
    507: {
    508:   PetscInt m, n, mv, nv;

    510:   PetscFunctionBegin;
    514:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
    515:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
    516:   /* use pmat to check vector sizes since for KSPLSQR the pmat may be of a different size than mat */
    517:   PetscCall(MatGetLocalSize(pc->pmat, &m, &n));
    518:   PetscCall(VecGetLocalSize(x, &mv));
    519:   PetscCall(VecGetLocalSize(y, &nv));
    520:   /* check pmat * y = x is feasible */
    521:   PetscCheck(mv == m, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Preconditioner number of local rows %" PetscInt_FMT " does not equal input vector size %" PetscInt_FMT, m, mv);
    522:   PetscCheck(nv == n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Preconditioner number of local columns %" PetscInt_FMT " does not equal output vector size %" PetscInt_FMT, n, nv);
    523:   PetscCall(VecSetErrorIfLocked(y, 3));

    525:   PetscCall(PCSetUp(pc));
    526:   PetscCall(VecLockReadPush(x));
    527:   PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0));
    528:   PetscUseTypeMethod(pc, apply, x, y);
    529:   PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0));
    530:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
    531:   PetscCall(VecLockReadPop(x));
    532:   PetscFunctionReturn(PETSC_SUCCESS);
    533: }

    535: /*@
    536:   PCMatApply - Applies the preconditioner to multiple vectors stored as a `MATDENSE`. Like `PCApply()`, `Y` and `X` must be different matrices.

    538:   Collective

    540:   Input Parameters:
    541: + pc - the `PC` preconditioner context
    542: - X  - block of input vectors

    544:   Output Parameter:
    545: . Y - block of output vectors

    547:   Level: developer

    549: .seealso: [](ch_ksp), `PC`, `PCApply()`, `KSPMatSolve()`
    550: @*/
    551: PetscErrorCode PCMatApply(PC pc, Mat X, Mat Y)
    552: {
    553:   Mat       A;
    554:   Vec       cy, cx;
    555:   PetscInt  m1, M1, m2, M2, n1, N1, n2, N2, m3, M3, n3, N3;
    556:   PetscBool match;

    558:   PetscFunctionBegin;
    562:   PetscCheckSameComm(pc, 1, X, 2);
    563:   PetscCheckSameComm(pc, 1, Y, 3);
    564:   PetscCheck(Y != X, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "Y and X must be different matrices");
    565:   PetscCall(PCGetOperators(pc, NULL, &A));
    566:   PetscCall(MatGetLocalSize(A, &m3, &n3));
    567:   PetscCall(MatGetLocalSize(X, &m2, &n2));
    568:   PetscCall(MatGetLocalSize(Y, &m1, &n1));
    569:   PetscCall(MatGetSize(A, &M3, &N3));
    570:   PetscCall(MatGetSize(X, &M2, &N2));
    571:   PetscCall(MatGetSize(Y, &M1, &N1));
    572:   PetscCheck(n1 == n2 && N1 == N2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible number of columns between block of input vectors (n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and block of output vectors (n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")", n2, N2, n1, N1);
    573:   PetscCheck(m2 == m3 && M2 == M3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout between block of input vectors (m,M) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and Pmat (m,M)x(n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")x(%" PetscInt_FMT ",%" PetscInt_FMT ")", m2, M2, m3, M3, n3, N3);
    574:   PetscCheck(m1 == n3 && M1 == N3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout between block of output vectors (m,M) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and Pmat (m,M)x(n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")x(%" PetscInt_FMT ",%" PetscInt_FMT ")", m1, M1, m3, M3, n3, N3);
    575:   PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)Y, &match, MATSEQDENSE, MATMPIDENSE, ""));
    576:   PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of output vectors not stored in a dense Mat");
    577:   PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)X, &match, MATSEQDENSE, MATMPIDENSE, ""));
    578:   PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of input vectors not stored in a dense Mat");
    579:   PetscCall(PCSetUp(pc));
    580:   if (pc->ops->matapply) {
    581:     PetscCall(PetscLogEventBegin(PC_MatApply, pc, X, Y, 0));
    582:     PetscUseTypeMethod(pc, matapply, X, Y);
    583:     PetscCall(PetscLogEventEnd(PC_MatApply, pc, X, Y, 0));
    584:   } else {
    585:     PetscCall(PetscInfo(pc, "PC type %s applying column by column\n", ((PetscObject)pc)->type_name));
    586:     for (n1 = 0; n1 < N1; ++n1) {
    587:       PetscCall(MatDenseGetColumnVecRead(X, n1, &cx));
    588:       PetscCall(MatDenseGetColumnVecWrite(Y, n1, &cy));
    589:       PetscCall(PCApply(pc, cx, cy));
    590:       PetscCall(MatDenseRestoreColumnVecWrite(Y, n1, &cy));
    591:       PetscCall(MatDenseRestoreColumnVecRead(X, n1, &cx));
    592:     }
    593:   }
    594:   PetscFunctionReturn(PETSC_SUCCESS);
    595: }

    597: /*@
    598:   PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.

    600:   Collective

    602:   Input Parameters:
    603: + pc - the `PC` preconditioner context
    604: - x  - input vector

    606:   Output Parameter:
    607: . y - output vector

    609:   Level: developer

    611:   Note:
    612:   Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners.

    614: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricRight()`
    615: @*/
    616: PetscErrorCode PCApplySymmetricLeft(PC pc, Vec x, Vec y)
    617: {
    618:   PetscFunctionBegin;
    622:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
    623:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
    624:   PetscCall(PCSetUp(pc));
    625:   PetscCall(VecLockReadPush(x));
    626:   PetscCall(PetscLogEventBegin(PC_ApplySymmetricLeft, pc, x, y, 0));
    627:   PetscUseTypeMethod(pc, applysymmetricleft, x, y);
    628:   PetscCall(PetscLogEventEnd(PC_ApplySymmetricLeft, pc, x, y, 0));
    629:   PetscCall(VecLockReadPop(x));
    630:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
    631:   PetscFunctionReturn(PETSC_SUCCESS);
    632: }

    634: /*@
    635:   PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.

    637:   Collective

    639:   Input Parameters:
    640: + pc - the `PC` preconditioner context
    641: - x  - input vector

    643:   Output Parameter:
    644: . y - output vector

    646:   Level: developer

    648:   Note:
    649:   Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners.

    651: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricLeft()`
    652: @*/
    653: PetscErrorCode PCApplySymmetricRight(PC pc, Vec x, Vec y)
    654: {
    655:   PetscFunctionBegin;
    659:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
    660:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
    661:   PetscCall(PCSetUp(pc));
    662:   PetscCall(VecLockReadPush(x));
    663:   PetscCall(PetscLogEventBegin(PC_ApplySymmetricRight, pc, x, y, 0));
    664:   PetscUseTypeMethod(pc, applysymmetricright, x, y);
    665:   PetscCall(PetscLogEventEnd(PC_ApplySymmetricRight, pc, x, y, 0));
    666:   PetscCall(VecLockReadPop(x));
    667:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
    668:   PetscFunctionReturn(PETSC_SUCCESS);
    669: }

    671: /*@
    672:   PCApplyTranspose - Applies the transpose of preconditioner to a vector.

    674:   Collective

    676:   Input Parameters:
    677: + pc - the `PC` preconditioner context
    678: - x  - input vector

    680:   Output Parameter:
    681: . y - output vector

    683:   Level: developer

    685:   Note:
    686:   For complex numbers this applies the non-Hermitian transpose.

    688:   Developer Note:
    689:   We need to implement a `PCApplyHermitianTranspose()`

    691: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyBAorAB()`, `PCApplyBAorABTranspose()`, `PCApplyTransposeExists()`
    692: @*/
    693: PetscErrorCode PCApplyTranspose(PC pc, Vec x, Vec y)
    694: {
    695:   PetscFunctionBegin;
    699:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
    700:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
    701:   PetscCall(PCSetUp(pc));
    702:   PetscCall(VecLockReadPush(x));
    703:   PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0));
    704:   PetscUseTypeMethod(pc, applytranspose, x, y);
    705:   PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0));
    706:   PetscCall(VecLockReadPop(x));
    707:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
    708:   PetscFunctionReturn(PETSC_SUCCESS);
    709: }

    711: /*@
    712:   PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation

    714:   Collective

    716:   Input Parameter:
    717: . pc - the `PC` preconditioner context

    719:   Output Parameter:
    720: . flg - `PETSC_TRUE` if a transpose operation is defined

    722:   Level: developer

    724: .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`
    725: @*/
    726: PetscErrorCode PCApplyTransposeExists(PC pc, PetscBool *flg)
    727: {
    728:   PetscFunctionBegin;
    730:   PetscAssertPointer(flg, 2);
    731:   if (pc->ops->applytranspose) *flg = PETSC_TRUE;
    732:   else *flg = PETSC_FALSE;
    733:   PetscFunctionReturn(PETSC_SUCCESS);
    734: }

    736: /*@
    737:   PCApplyBAorAB - Applies the preconditioner and operator to a vector. $y = B*A*x $ or $ y = A*B*x$.

    739:   Collective

    741:   Input Parameters:
    742: + pc   - the `PC` preconditioner context
    743: . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
    744: . x    - input vector
    745: - work - work vector

    747:   Output Parameter:
    748: . y - output vector

    750:   Level: developer

    752:   Note:
    753:   If the `PC` has had `PCSetDiagonalScale()` set then $ D M A D^{-1} $ for left preconditioning or $ D A M D^{-1} $ is actually applied.
    754:   The specific `KSPSolve()` method must also be written to handle the post-solve "correction" for the diagonal scaling.

    756: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorABTranspose()`
    757: @*/
    758: PetscErrorCode PCApplyBAorAB(PC pc, PCSide side, Vec x, Vec y, Vec work)
    759: {
    760:   PetscFunctionBegin;
    766:   PetscCheckSameComm(pc, 1, x, 3);
    767:   PetscCheckSameComm(pc, 1, y, 4);
    768:   PetscCheckSameComm(pc, 1, work, 5);
    769:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
    770:   PetscCheck(side == PC_LEFT || side == PC_SYMMETRIC || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right, left, or symmetric");
    771:   PetscCheck(!pc->diagonalscale || side != PC_SYMMETRIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot include diagonal scaling with symmetric preconditioner application");
    772:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE));

    774:   PetscCall(PCSetUp(pc));
    775:   if (pc->diagonalscale) {
    776:     if (pc->ops->applyBA) {
    777:       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
    778:       PetscCall(VecDuplicate(x, &work2));
    779:       PetscCall(PCDiagonalScaleRight(pc, x, work2));
    780:       PetscUseTypeMethod(pc, applyBA, side, work2, y, work);
    781:       PetscCall(PCDiagonalScaleLeft(pc, y, y));
    782:       PetscCall(VecDestroy(&work2));
    783:     } else if (side == PC_RIGHT) {
    784:       PetscCall(PCDiagonalScaleRight(pc, x, y));
    785:       PetscCall(PCApply(pc, y, work));
    786:       PetscCall(MatMult(pc->mat, work, y));
    787:       PetscCall(PCDiagonalScaleLeft(pc, y, y));
    788:     } else if (side == PC_LEFT) {
    789:       PetscCall(PCDiagonalScaleRight(pc, x, y));
    790:       PetscCall(MatMult(pc->mat, y, work));
    791:       PetscCall(PCApply(pc, work, y));
    792:       PetscCall(PCDiagonalScaleLeft(pc, y, y));
    793:     } else PetscCheck(side != PC_SYMMETRIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot provide diagonal scaling with symmetric application of preconditioner");
    794:   } else {
    795:     if (pc->ops->applyBA) {
    796:       PetscUseTypeMethod(pc, applyBA, side, x, y, work);
    797:     } else if (side == PC_RIGHT) {
    798:       PetscCall(PCApply(pc, x, work));
    799:       PetscCall(MatMult(pc->mat, work, y));
    800:     } else if (side == PC_LEFT) {
    801:       PetscCall(MatMult(pc->mat, x, work));
    802:       PetscCall(PCApply(pc, work, y));
    803:     } else if (side == PC_SYMMETRIC) {
    804:       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
    805:       PetscCall(PCApplySymmetricRight(pc, x, work));
    806:       PetscCall(MatMult(pc->mat, work, y));
    807:       PetscCall(VecCopy(y, work));
    808:       PetscCall(PCApplySymmetricLeft(pc, work, y));
    809:     }
    810:   }
    811:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
    812:   PetscFunctionReturn(PETSC_SUCCESS);
    813: }

    815: /*@
    816:   PCApplyBAorABTranspose - Applies the transpose of the preconditioner
    817:   and operator to a vector. That is, applies $B^T * A^T$ with left preconditioning,
    818:   NOT $(B*A)^T = A^T*B^T$.

    820:   Collective

    822:   Input Parameters:
    823: + pc   - the `PC` preconditioner context
    824: . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
    825: . x    - input vector
    826: - work - work vector

    828:   Output Parameter:
    829: . y - output vector

    831:   Level: developer

    833:   Note:
    834:   This routine is used internally so that the same Krylov code can be used to solve $A x = b$ and $A^T x = b$, with a preconditioner
    835:   defined by $B^T$. This is why this has the funny form that it computes $B^T * A^T$

    837: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorAB()`
    838: @*/
    839: PetscErrorCode PCApplyBAorABTranspose(PC pc, PCSide side, Vec x, Vec y, Vec work)
    840: {
    841:   PetscFunctionBegin;
    846:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
    847:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE));
    848:   if (pc->ops->applyBAtranspose) {
    849:     PetscUseTypeMethod(pc, applyBAtranspose, side, x, y, work);
    850:     if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
    851:     PetscFunctionReturn(PETSC_SUCCESS);
    852:   }
    853:   PetscCheck(side == PC_LEFT || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right or left");

    855:   PetscCall(PCSetUp(pc));
    856:   if (side == PC_RIGHT) {
    857:     PetscCall(PCApplyTranspose(pc, x, work));
    858:     PetscCall(MatMultTranspose(pc->mat, work, y));
    859:   } else if (side == PC_LEFT) {
    860:     PetscCall(MatMultTranspose(pc->mat, x, work));
    861:     PetscCall(PCApplyTranspose(pc, work, y));
    862:   }
    863:   /* add support for PC_SYMMETRIC */
    864:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
    865:   PetscFunctionReturn(PETSC_SUCCESS);
    866: }

    868: /*@
    869:   PCApplyRichardsonExists - Determines whether a particular preconditioner has a
    870:   built-in fast application of Richardson's method.

    872:   Not Collective

    874:   Input Parameter:
    875: . pc - the preconditioner

    877:   Output Parameter:
    878: . exists - `PETSC_TRUE` or `PETSC_FALSE`

    880:   Level: developer

    882: .seealso: [](ch_ksp), `PC`, `KSPRICHARDSON`, `PCApplyRichardson()`
    883: @*/
    884: PetscErrorCode PCApplyRichardsonExists(PC pc, PetscBool *exists)
    885: {
    886:   PetscFunctionBegin;
    888:   PetscAssertPointer(exists, 2);
    889:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
    890:   else *exists = PETSC_FALSE;
    891:   PetscFunctionReturn(PETSC_SUCCESS);
    892: }

    894: /*@
    895:   PCApplyRichardson - Applies several steps of Richardson iteration with
    896:   the particular preconditioner. This routine is usually used by the
    897:   Krylov solvers and not the application code directly.

    899:   Collective

    901:   Input Parameters:
    902: + pc        - the `PC` preconditioner context
    903: . b         - the right-hand side
    904: . w         - one work vector
    905: . rtol      - relative decrease in residual norm convergence criteria
    906: . abstol    - absolute residual norm convergence criteria
    907: . dtol      - divergence residual norm increase criteria
    908: . its       - the number of iterations to apply.
    909: - guesszero - if the input x contains nonzero initial guess

    911:   Output Parameters:
    912: + outits - number of iterations actually used (for SOR this always equals its)
    913: . reason - the reason the apply terminated
    914: - y      - the solution (also contains initial guess if guesszero is `PETSC_FALSE`

    916:   Level: developer

    918:   Notes:
    919:   Most preconditioners do not support this function. Use the command
    920:   `PCApplyRichardsonExists()` to determine if one does.

    922:   Except for the `PCMG` this routine ignores the convergence tolerances
    923:   and always runs for the number of iterations

    925: .seealso: [](ch_ksp), `PC`, `PCApplyRichardsonExists()`
    926: @*/
    927: PetscErrorCode PCApplyRichardson(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
    928: {
    929:   PetscFunctionBegin;
    934:   PetscCheck(b != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "b and y must be different vectors");
    935:   PetscCall(PCSetUp(pc));
    936:   PetscUseTypeMethod(pc, applyrichardson, b, y, w, rtol, abstol, dtol, its, guesszero, outits, reason);
    937:   PetscFunctionReturn(PETSC_SUCCESS);
    938: }

    940: /*@
    941:   PCSetFailedReason - Sets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail

    943:   Logically Collective

    945:   Input Parameters:
    946: + pc     - the `PC` preconditioner context
    947: - reason - the reason it failed

    949:   Level: advanced

    951: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCFailedReason`
    952: @*/
    953: PetscErrorCode PCSetFailedReason(PC pc, PCFailedReason reason)
    954: {
    955:   PetscFunctionBegin;
    957:   pc->failedreason = reason;
    958:   PetscFunctionReturn(PETSC_SUCCESS);
    959: }

    961: /*@
    962:   PCGetFailedReason - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail

    964:   Not Collective

    966:   Input Parameter:
    967: . pc - the `PC` preconditioner context

    969:   Output Parameter:
    970: . reason - the reason it failed

    972:   Level: advanced

    974:   Note:
    975:   After a call to `KSPCheckDot()` or  `KSPCheckNorm()` inside a `KSPSolve()` or a call to `PCReduceFailedReason()`
    976:   this is the maximum reason over all MPI processes in the `PC` communicator and hence logically collective.
    977:   Otherwise it returns the local value.

    979: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCSetFailedReason()`, `PCFailedReason`
    980: @*/
    981: PetscErrorCode PCGetFailedReason(PC pc, PCFailedReason *reason)
    982: {
    983:   PetscFunctionBegin;
    985:   if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled;
    986:   else *reason = pc->failedreason;
    987:   PetscFunctionReturn(PETSC_SUCCESS);
    988: }

    990: /*@
    991:   PCReduceFailedReason - Reduce the failed reason among the MPI processes that share the `PC`

    993:   Collective

    995:   Input Parameter:
    996: . pc - the `PC` preconditioner context

    998:   Level: advanced

    1000:   Note:
    1001:   Different MPI processes may have different reasons or no reason, see `PCGetFailedReason()`. This routine
    1002:   makes them have a common value (failure if any MPI process had a failure).

    1004: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()`, `PCFailedReason`
    1005: @*/
    1006: PetscErrorCode PCReduceFailedReason(PC pc)
    1007: {
    1008:   PetscInt buf;

    1010:   PetscFunctionBegin;
    1012:   buf = (PetscInt)pc->failedreason;
    1013:   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &buf, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc)));
    1014:   pc->failedreason = (PCFailedReason)buf;
    1015:   PetscFunctionReturn(PETSC_SUCCESS);
    1016: }

    1018: /*
    1019:       a setupcall of 0 indicates never setup,
    1020:                      1 indicates has been previously setup
    1021:                     -1 indicates a PCSetUp() was attempted and failed
    1022: */
    1023: /*@
    1024:   PCSetUp - Prepares for the use of a preconditioner. Performs all the one-time operations needed before the preconditioner
    1025:   can be used with `PCApply()`

    1027:   Collective

    1029:   Input Parameter:
    1030: . pc - the `PC` preconditioner context

    1032:   Level: developer

    1034:   Notes:
    1035:   For example, for `PCLU` this will compute the factorization.

    1037:   This is called automatically by `KSPSetUp()` or `PCApply()` so rarely needs to be called directly.

    1039:   For nested preconditioners, such as `PCFIELDSPLIT` or `PCBJACOBI` this may not finish the construction of the preconditioner
    1040:   on the inner levels, the routine `PCSetUpOnBlocks()` may compute more of the preconditioner in those situations.

    1042: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `KSPSetUp()`, `PCSetUpOnBlocks()`
    1043: @*/
    1044: PetscErrorCode PCSetUp(PC pc)
    1045: {
    1046:   const char      *def;
    1047:   PetscObjectState matstate, matnonzerostate;

    1049:   PetscFunctionBegin;
    1051:   PetscCheck(pc->mat, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be set first");

    1053:   if (pc->setupcalled && pc->reusepreconditioner) {
    1054:     PetscCall(PetscInfo(pc, "Leaving PC with identical preconditioner since reuse preconditioner is set\n"));
    1055:     PetscFunctionReturn(PETSC_SUCCESS);
    1056:   }

    1058:   PetscCall(PetscObjectStateGet((PetscObject)pc->pmat, &matstate));
    1059:   PetscCall(MatGetNonzeroState(pc->pmat, &matnonzerostate));
    1060:   if (!pc->setupcalled) {
    1061:     //PetscCall(PetscInfo(pc, "Setting up PC for first time\n"));
    1062:     pc->flag = DIFFERENT_NONZERO_PATTERN;
    1063:   } else if (matstate == pc->matstate) PetscFunctionReturn(PETSC_SUCCESS);
    1064:   else {
    1065:     if (matnonzerostate != pc->matnonzerostate) {
    1066:       PetscCall(PetscInfo(pc, "Setting up PC with different nonzero pattern\n"));
    1067:       pc->flag = DIFFERENT_NONZERO_PATTERN;
    1068:     } else {
    1069:       //PetscCall(PetscInfo(pc, "Setting up PC with same nonzero pattern\n"));
    1070:       pc->flag = SAME_NONZERO_PATTERN;
    1071:     }
    1072:   }
    1073:   pc->matstate        = matstate;
    1074:   pc->matnonzerostate = matnonzerostate;

    1076:   if (!((PetscObject)pc)->type_name) {
    1077:     PetscCall(PCGetDefaultType_Private(pc, &def));
    1078:     PetscCall(PCSetType(pc, def));
    1079:   }

    1081:   PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure));
    1082:   PetscCall(MatSetErrorIfFailure(pc->mat, pc->erroriffailure));
    1083:   PetscCall(PetscLogEventBegin(PC_SetUp, pc, 0, 0, 0));
    1084:   if (pc->ops->setup) {
    1085:     PetscCall(PCLogEventsDeactivatePush());
    1086:     PetscUseTypeMethod(pc, setup);
    1087:     PetscCall(PCLogEventsDeactivatePop());
    1088:   }
    1089:   PetscCall(PetscLogEventEnd(PC_SetUp, pc, 0, 0, 0));
    1090:   if (!pc->setupcalled) pc->setupcalled = 1;
    1091:   PetscFunctionReturn(PETSC_SUCCESS);
    1092: }

    1094: /*@
    1095:   PCSetUpOnBlocks - Sets up the preconditioner for each block in
    1096:   the block Jacobi, overlapping Schwarz, and fieldsplit methods.

    1098:   Collective

    1100:   Input Parameter:
    1101: . pc - the `PC` preconditioner context

    1103:   Level: developer

    1105:   Notes:
    1106:   For nested preconditioners such as `PCBJACOBI`, `PCSetUp()` is not called on each sub-`KSP` when `PCSetUp()` is
    1107:   called on the outer `PC`, this routine ensures it is called.

    1109:   It calls `PCSetUp()` if not yet called.

    1111: .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCCreate()`, `PCApply()`, `PCDestroy()`
    1112: @*/
    1113: PetscErrorCode PCSetUpOnBlocks(PC pc)
    1114: {
    1115:   PetscFunctionBegin;
    1117:   if (!pc->setupcalled) PetscCall(PCSetUp(pc)); /* "if" to prevent -info extra prints */
    1118:   if (!pc->ops->setuponblocks) PetscFunctionReturn(PETSC_SUCCESS);
    1119:   PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure));
    1120:   PetscCall(PetscLogEventBegin(PC_SetUpOnBlocks, pc, 0, 0, 0));
    1121:   PetscCall(PCLogEventsDeactivatePush());
    1122:   PetscUseTypeMethod(pc, setuponblocks);
    1123:   PetscCall(PCLogEventsDeactivatePop());
    1124:   PetscCall(PetscLogEventEnd(PC_SetUpOnBlocks, pc, 0, 0, 0));
    1125:   PetscFunctionReturn(PETSC_SUCCESS);
    1126: }

    1128: /*@C
    1129:   PCSetModifySubMatrices - Sets a user-defined routine for modifying the
    1130:   submatrices that arise within certain subdomain-based preconditioners such as `PCASM`

    1132:   Logically Collective

    1134:   Input Parameters:
    1135: + pc   - the `PC` preconditioner context
    1136: . func - routine for modifying the submatrices
    1137: - ctx  - optional user-defined context (may be `NULL`)

    1139:   Calling sequence of `func`:
    1140: + pc     - the `PC` preconditioner context
    1141: . nsub   - number of index sets
    1142: . row    - an array of index sets that contain the global row numbers
    1143:          that comprise each local submatrix
    1144: . col    - an array of index sets that contain the global column numbers
    1145:          that comprise each local submatrix
    1146: . submat - array of local submatrices
    1147: - ctx    - optional user-defined context for private data for the
    1148:          user-defined func routine (may be `NULL`)

    1150:   Level: advanced

    1152:   Notes:
    1153:   The basic submatrices are extracted from the preconditioner matrix as
    1154:   usual; the user can then alter these (for example, to set different boundary
    1155:   conditions for each submatrix) before they are used for the local solves.

    1157:   `PCSetModifySubMatrices()` MUST be called before `KSPSetUp()` and
    1158:   `KSPSolve()`.

    1160:   A routine set by `PCSetModifySubMatrices()` is currently called within
    1161:   the block Jacobi (`PCBJACOBI`) and additive Schwarz (`PCASM`)
    1162:   preconditioners.  All other preconditioners ignore this routine.

    1164: .seealso: [](ch_ksp), `PC`, `PCBJACOBI`, `PCASM`, `PCModifySubMatrices()`
    1165: @*/
    1166: PetscErrorCode PCSetModifySubMatrices(PC pc, PetscErrorCode (*func)(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx), void *ctx)
    1167: {
    1168:   PetscFunctionBegin;
    1170:   pc->modifysubmatrices  = func;
    1171:   pc->modifysubmatricesP = ctx;
    1172:   PetscFunctionReturn(PETSC_SUCCESS);
    1173: }

    1175: /*@C
    1176:   PCModifySubMatrices - Calls an optional user-defined routine within
    1177:   certain preconditioners if one has been set with `PCSetModifySubMatrices()`.

    1179:   Collective

    1181:   Input Parameters:
    1182: + pc     - the `PC` preconditioner context
    1183: . nsub   - the number of local submatrices
    1184: . row    - an array of index sets that contain the global row numbers
    1185:          that comprise each local submatrix
    1186: . col    - an array of index sets that contain the global column numbers
    1187:          that comprise each local submatrix
    1188: . submat - array of local submatrices
    1189: - ctx    - optional user-defined context for private data for the
    1190:          user-defined routine (may be `NULL`)

    1192:   Output Parameter:
    1193: . submat - array of local submatrices (the entries of which may
    1194:             have been modified)

    1196:   Level: developer

    1198:   Note:
    1199:   The user should NOT generally call this routine, as it will
    1200:   automatically be called within certain preconditioners.

    1202: .seealso: [](ch_ksp), `PC`, `PCSetModifySubMatrices()`
    1203: @*/
    1204: PetscErrorCode PCModifySubMatrices(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx)
    1205: {
    1206:   PetscFunctionBegin;
    1208:   if (!pc->modifysubmatrices) PetscFunctionReturn(PETSC_SUCCESS);
    1209:   PetscCall(PetscLogEventBegin(PC_ModifySubMatrices, pc, 0, 0, 0));
    1210:   PetscCall((*pc->modifysubmatrices)(pc, nsub, row, col, submat, ctx));
    1211:   PetscCall(PetscLogEventEnd(PC_ModifySubMatrices, pc, 0, 0, 0));
    1212:   PetscFunctionReturn(PETSC_SUCCESS);
    1213: }

    1215: /*@
    1216:   PCSetOperators - Sets the matrix associated with the linear system and
    1217:   a (possibly) different one associated with the preconditioner.

    1219:   Logically Collective

    1221:   Input Parameters:
    1222: + pc   - the `PC` preconditioner context
    1223: . Amat - the matrix that defines the linear system
    1224: - Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.

    1226:   Level: intermediate

    1228:   Notes:
    1229:   Passing a `NULL` for `Amat` or `Pmat` removes the matrix that is currently used.

    1231:   If you wish to replace either `Amat` or `Pmat` but leave the other one untouched then
    1232:   first call `KSPGetOperators()` to get the one you wish to keep, call `PetscObjectReference()`
    1233:   on it and then pass it back in in your call to `KSPSetOperators()`.

    1235:   More Notes about Repeated Solution of Linear Systems:
    1236:   PETSc does NOT reset the matrix entries of either `Amat` or `Pmat`
    1237:   to zero after a linear solve; the user is completely responsible for
    1238:   matrix assembly.  See the routine `MatZeroEntries()` if desiring to
    1239:   zero all elements of a matrix.

    1241: .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`
    1242:  @*/
    1243: PetscErrorCode PCSetOperators(PC pc, Mat Amat, Mat Pmat)
    1244: {
    1245:   PetscInt m1, n1, m2, n2;

    1247:   PetscFunctionBegin;
    1251:   if (Amat) PetscCheckSameComm(pc, 1, Amat, 2);
    1252:   if (Pmat) PetscCheckSameComm(pc, 1, Pmat, 3);
    1253:   if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) {
    1254:     PetscCall(MatGetLocalSize(Amat, &m1, &n1));
    1255:     PetscCall(MatGetLocalSize(pc->mat, &m2, &n2));
    1256:     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);
    1257:     PetscCall(MatGetLocalSize(Pmat, &m1, &n1));
    1258:     PetscCall(MatGetLocalSize(pc->pmat, &m2, &n2));
    1259:     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);
    1260:   }

    1262:   if (Pmat != pc->pmat) {
    1263:     /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */
    1264:     pc->matnonzerostate = -1;
    1265:     pc->matstate        = -1;
    1266:   }

    1268:   /* reference first in case the matrices are the same */
    1269:   if (Amat) PetscCall(PetscObjectReference((PetscObject)Amat));
    1270:   PetscCall(MatDestroy(&pc->mat));
    1271:   if (Pmat) PetscCall(PetscObjectReference((PetscObject)Pmat));
    1272:   PetscCall(MatDestroy(&pc->pmat));
    1273:   pc->mat  = Amat;
    1274:   pc->pmat = Pmat;
    1275:   PetscFunctionReturn(PETSC_SUCCESS);
    1276: }

    1278: /*@
    1279:   PCSetReusePreconditioner - reuse the current preconditioner even if the operator in the preconditioner `PC` has changed.

    1281:   Logically Collective

    1283:   Input Parameters:
    1284: + pc   - the `PC` preconditioner context
    1285: - flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner

    1287:   Level: intermediate

    1289:   Note:
    1290:   Normally if a matrix inside a `PC` changes the `PC` automatically updates itself using information from the changed matrix. This option
    1291:   prevents this.

    1293: .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCGetReusePreconditioner()`, `KSPSetReusePreconditioner()`
    1294:  @*/
    1295: PetscErrorCode PCSetReusePreconditioner(PC pc, PetscBool flag)
    1296: {
    1297:   PetscFunctionBegin;
    1300:   pc->reusepreconditioner = flag;
    1301:   PetscFunctionReturn(PETSC_SUCCESS);
    1302: }

    1304: /*@
    1305:   PCGetReusePreconditioner - Determines if the `PC` reuses the current preconditioner even if the operator in the preconditioner has changed.

    1307:   Not Collective

    1309:   Input Parameter:
    1310: . pc - the `PC` preconditioner context

    1312:   Output Parameter:
    1313: . flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner

    1315:   Level: intermediate

    1317: .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCSetReusePreconditioner()`
    1318:  @*/
    1319: PetscErrorCode PCGetReusePreconditioner(PC pc, PetscBool *flag)
    1320: {
    1321:   PetscFunctionBegin;
    1323:   PetscAssertPointer(flag, 2);
    1324:   *flag = pc->reusepreconditioner;
    1325:   PetscFunctionReturn(PETSC_SUCCESS);
    1326: }

    1328: /*@
    1329:   PCGetOperators - Gets the matrix associated with the linear system and
    1330:   possibly a different one which is used to construct the preconditioner.

    1332:   Not Collective, though parallel `Mat`s are returned if `pc` is parallel

    1334:   Input Parameter:
    1335: . pc - the `PC` preconditioner context

    1337:   Output Parameters:
    1338: + Amat - the matrix defining the linear system
    1339: - Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat.

    1341:   Level: intermediate

    1343:   Note:
    1344:   Does not increase the reference count of the matrices, so you should not destroy them

    1346:   Alternative usage: If the operators have NOT been set with `KSPSetOperators()`/`PCSetOperators()` then the operators
    1347:   are created in `PC` and returned to the user. In this case, if both operators
    1348:   mat and pmat are requested, two DIFFERENT operators will be returned. If
    1349:   only one is requested both operators in the PC will be the same (i.e. as
    1350:   if one had called `KSPSetOperators()`/`PCSetOperators()` with the same argument for both Mats).
    1351:   The user must set the sizes of the returned matrices and their type etc just
    1352:   as if the user created them with `MatCreate()`. For example,

    1354: .vb
    1355:          KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to
    1356:            set size, type, etc of Amat

    1358:          MatCreate(comm,&mat);
    1359:          KSP/PCSetOperators(ksp/pc,Amat,Amat);
    1360:          PetscObjectDereference((PetscObject)mat);
    1361:            set size, type, etc of Amat
    1362: .ve

    1364:   and

    1366: .vb
    1367:          KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to
    1368:            set size, type, etc of Amat and Pmat

    1370:          MatCreate(comm,&Amat);
    1371:          MatCreate(comm,&Pmat);
    1372:          KSP/PCSetOperators(ksp/pc,Amat,Pmat);
    1373:          PetscObjectDereference((PetscObject)Amat);
    1374:          PetscObjectDereference((PetscObject)Pmat);
    1375:            set size, type, etc of Amat and Pmat
    1376: .ve

    1378:   The rationale for this support is so that when creating a `TS`, `SNES`, or `KSP` the hierarchy
    1379:   of underlying objects (i.e. `SNES`, `KSP`, `PC`, `Mat`) and their lifespans can be completely
    1380:   managed by the top most level object (i.e. the `TS`, `SNES`, or `KSP`). Another way to look
    1381:   at this is when you create a `SNES` you do not NEED to create a `KSP` and attach it to
    1382:   the `SNES` object (the `SNES` object manages it for you). Similarly when you create a KSP
    1383:   you do not need to attach a `PC` to it (the `KSP` object manages the `PC` object for you).
    1384:   Thus, why should YOU have to create the `Mat` and attach it to the `SNES`/`KSP`/`PC`, when
    1385:   it can be created for you?

    1387: .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperatorsSet()`
    1388: @*/
    1389: PetscErrorCode PCGetOperators(PC pc, Mat *Amat, Mat *Pmat)
    1390: {
    1391:   PetscFunctionBegin;
    1393:   if (Amat) {
    1394:     if (!pc->mat) {
    1395:       if (pc->pmat && !Pmat) { /* Pmat has been set, but user did not request it, so use for Amat */
    1396:         pc->mat = pc->pmat;
    1397:         PetscCall(PetscObjectReference((PetscObject)pc->mat));
    1398:       } else { /* both Amat and Pmat are empty */
    1399:         PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->mat));
    1400:         if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */
    1401:           pc->pmat = pc->mat;
    1402:           PetscCall(PetscObjectReference((PetscObject)pc->pmat));
    1403:         }
    1404:       }
    1405:     }
    1406:     *Amat = pc->mat;
    1407:   }
    1408:   if (Pmat) {
    1409:     if (!pc->pmat) {
    1410:       if (pc->mat && !Amat) { /* Amat has been set but was not requested, so use for pmat */
    1411:         pc->pmat = pc->mat;
    1412:         PetscCall(PetscObjectReference((PetscObject)pc->pmat));
    1413:       } else {
    1414:         PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->pmat));
    1415:         if (!Amat) { /* user did NOT request Amat, so make same as Pmat */
    1416:           pc->mat = pc->pmat;
    1417:           PetscCall(PetscObjectReference((PetscObject)pc->mat));
    1418:         }
    1419:       }
    1420:     }
    1421:     *Pmat = pc->pmat;
    1422:   }
    1423:   PetscFunctionReturn(PETSC_SUCCESS);
    1424: }

    1426: /*@
    1427:   PCGetOperatorsSet - Determines if the matrix associated with the linear system and
    1428:   possibly a different one associated with the preconditioner have been set in the `PC`.

    1430:   Not Collective, though the results on all processes should be the same

    1432:   Input Parameter:
    1433: . pc - the `PC` preconditioner context

    1435:   Output Parameters:
    1436: + mat  - the matrix associated with the linear system was set
    1437: - pmat - matrix associated with the preconditioner was set, usually the same

    1439:   Level: intermediate

    1441: .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperators()`
    1442: @*/
    1443: PetscErrorCode PCGetOperatorsSet(PC pc, PetscBool *mat, PetscBool *pmat)
    1444: {
    1445:   PetscFunctionBegin;
    1447:   if (mat) *mat = (pc->mat) ? PETSC_TRUE : PETSC_FALSE;
    1448:   if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE;
    1449:   PetscFunctionReturn(PETSC_SUCCESS);
    1450: }

    1452: /*@
    1453:   PCFactorGetMatrix - Gets the factored matrix from the
    1454:   preconditioner context.  This routine is valid only for the `PCLU`,
    1455:   `PCILU`, `PCCHOLESKY`, and `PCICC` methods.

    1457:   Not Collective though `mat` is parallel if `pc` is parallel

    1459:   Input Parameter:
    1460: . pc - the `PC` preconditioner context

    1462:   Output Parameters:
    1463: . mat - the factored matrix

    1465:   Level: advanced

    1467:   Note:
    1468:   Does not increase the reference count for `mat` so DO NOT destroy it

    1470: .seealso: [](ch_ksp), `PC`, `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
    1471: @*/
    1472: PetscErrorCode PCFactorGetMatrix(PC pc, Mat *mat)
    1473: {
    1474:   PetscFunctionBegin;
    1476:   PetscAssertPointer(mat, 2);
    1477:   PetscCall(PCFactorSetUpMatSolverType(pc));
    1478:   PetscUseTypeMethod(pc, getfactoredmatrix, mat);
    1479:   PetscFunctionReturn(PETSC_SUCCESS);
    1480: }

    1482: /*@
    1483:   PCSetOptionsPrefix - Sets the prefix used for searching for all
    1484:   `PC` options in the database.

    1486:   Logically Collective

    1488:   Input Parameters:
    1489: + pc     - the `PC` preconditioner context
    1490: - prefix - the prefix string to prepend to all `PC` option requests

    1492:   Note:
    1493:   A hyphen (-) must NOT be given at the beginning of the prefix name.
    1494:   The first character of all runtime options is AUTOMATICALLY the
    1495:   hyphen.

    1497:   Level: advanced

    1499: .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCAppendOptionsPrefix()`, `PCGetOptionsPrefix()`
    1500: @*/
    1501: PetscErrorCode PCSetOptionsPrefix(PC pc, const char prefix[])
    1502: {
    1503:   PetscFunctionBegin;
    1505:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)pc, prefix));
    1506:   PetscFunctionReturn(PETSC_SUCCESS);
    1507: }

    1509: /*@
    1510:   PCAppendOptionsPrefix - Appends to the prefix used for searching for all
    1511:   `PC` options in the database.

    1513:   Logically Collective

    1515:   Input Parameters:
    1516: + pc     - the `PC` preconditioner context
    1517: - prefix - the prefix string to prepend to all `PC` option requests

    1519:   Note:
    1520:   A hyphen (-) must NOT be given at the beginning of the prefix name.
    1521:   The first character of all runtime options is AUTOMATICALLY the
    1522:   hyphen.

    1524:   Level: advanced

    1526: .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCGetOptionsPrefix()`
    1527: @*/
    1528: PetscErrorCode PCAppendOptionsPrefix(PC pc, const char prefix[])
    1529: {
    1530:   PetscFunctionBegin;
    1532:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)pc, prefix));
    1533:   PetscFunctionReturn(PETSC_SUCCESS);
    1534: }

    1536: /*@
    1537:   PCGetOptionsPrefix - Gets the prefix used for searching for all
    1538:   PC options in the database.

    1540:   Not Collective

    1542:   Input Parameter:
    1543: . pc - the `PC` preconditioner context

    1545:   Output Parameter:
    1546: . prefix - pointer to the prefix string used, is returned

    1548:   Level: advanced

    1550:   Fortran Note:
    1551:   The user should pass in a string `prefix` of
    1552:   sufficient length to hold the prefix.

    1554: .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCAppendOptionsPrefix()`
    1555: @*/
    1556: PetscErrorCode PCGetOptionsPrefix(PC pc, const char *prefix[])
    1557: {
    1558:   PetscFunctionBegin;
    1560:   PetscAssertPointer(prefix, 2);
    1561:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc, prefix));
    1562:   PetscFunctionReturn(PETSC_SUCCESS);
    1563: }

    1565: /*
    1566:    Indicates the right-hand side will be changed by KSPSolve(), this occurs for a few
    1567:   preconditioners including BDDC and Eisentat that transform the equations before applying
    1568:   the Krylov methods
    1569: */
    1570: PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC pc, PetscBool *change)
    1571: {
    1572:   PetscFunctionBegin;
    1574:   PetscAssertPointer(change, 2);
    1575:   *change = PETSC_FALSE;
    1576:   PetscTryMethod(pc, "PCPreSolveChangeRHS_C", (PC, PetscBool *), (pc, change));
    1577:   PetscFunctionReturn(PETSC_SUCCESS);
    1578: }

    1580: /*@
    1581:   PCPreSolve - Optional pre-solve phase, intended for any preconditioner-specific actions that must be performed before
    1582:   the iterative solve itself. Used in conjunction with `PCPostSolve()`

    1584:   Collective

    1586:   Input Parameters:
    1587: + pc  - the `PC` preconditioner context
    1588: - ksp - the Krylov subspace context

    1590:   Level: developer

    1592:   Notes:
    1593:   `KSPSolve()` calls this directly, so is rarely called by the user.

    1595:   Certain preconditioners, such as the `PCType` of `PCEISENSTAT`, change the formulation of the linear system to be solved iteratively.
    1596:   This function performs that transformation. `PCPostSolve()` then transforms the system back to its original form after the solve.
    1597:   `PCPostSolve()` also transforms the resulting solution of the transformed system to the solution of the original problem.

    1599:   `KSPSetPreSolve()` and `KSPSetPostSolve()` provide an alternative way to provide such transformations.

    1601: .seealso: [](ch_ksp), `PC`, `PCPostSolve()`, `KSP`, `PCSetPreSolve()`, `KSPSetPreSolve()`, `KSPSetPostSolve()`
    1602: @*/
    1603: PetscErrorCode PCPreSolve(PC pc, KSP ksp)
    1604: {
    1605:   Vec x, rhs;

    1607:   PetscFunctionBegin;
    1610:   pc->presolvedone++;
    1611:   PetscCheck(pc->presolvedone <= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot embed PCPreSolve() more than twice");
    1612:   PetscCall(KSPGetSolution(ksp, &x));
    1613:   PetscCall(KSPGetRhs(ksp, &rhs));

    1615:   if (pc->ops->presolve) PetscUseTypeMethod(pc, presolve, ksp, rhs, x);
    1616:   else if (pc->presolve) PetscCall(pc->presolve(pc, ksp));
    1617:   PetscFunctionReturn(PETSC_SUCCESS);
    1618: }

    1620: /*@C
    1621:   PCSetPreSolve - Sets function used by `PCPreSolve()` which is intended for any
    1622:   preconditioner-specific actions that must be performed before
    1623:   the iterative solve itself.

    1625:   Logically Collective

    1627:   Input Parameters:
    1628: + pc       - the preconditioner object
    1629: - presolve - the function to call before the solve

    1631:   Calling sequence of `presolve`:
    1632: + pc  - the `PC` context
    1633: - ksp - the `KSP` context

    1635:   Level: developer

    1637: .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCPreSolve()`
    1638: @*/
    1639: PetscErrorCode PCSetPreSolve(PC pc, PetscErrorCode (*presolve)(PC pc, KSP ksp))
    1640: {
    1641:   PetscFunctionBegin;
    1643:   pc->presolve = presolve;
    1644:   PetscFunctionReturn(PETSC_SUCCESS);
    1645: }

    1647: /*@
    1648:   PCPostSolve - Optional post-solve phase, intended for any
    1649:   preconditioner-specific actions that must be performed after
    1650:   the iterative solve itself.

    1652:   Collective

    1654:   Input Parameters:
    1655: + pc  - the `PC` preconditioner context
    1656: - ksp - the `KSP` Krylov subspace context

    1658:   Example Usage:
    1659: .vb
    1660:     PCPreSolve(pc,ksp);
    1661:     KSPSolve(ksp,b,x);
    1662:     PCPostSolve(pc,ksp);
    1663: .ve

    1665:   Level: developer

    1667:   Note:
    1668:   `KSPSolve()` calls this routine directly, so it is rarely called by the user.

    1670: .seealso: [](ch_ksp), `PC`, `PCSetPreSolve()`, `KSPSetPostSolve()`, `KSPSetPreSolve()`, `PCPreSolve()`, `KSPSolve()`
    1671: @*/
    1672: PetscErrorCode PCPostSolve(PC pc, KSP ksp)
    1673: {
    1674:   Vec x, rhs;

    1676:   PetscFunctionBegin;
    1679:   pc->presolvedone--;
    1680:   PetscCall(KSPGetSolution(ksp, &x));
    1681:   PetscCall(KSPGetRhs(ksp, &rhs));
    1682:   PetscTryTypeMethod(pc, postsolve, ksp, rhs, x);
    1683:   PetscFunctionReturn(PETSC_SUCCESS);
    1684: }

    1686: /*@
    1687:   PCLoad - Loads a `PC` that has been stored in binary  with `PCView()`.

    1689:   Collective

    1691:   Input Parameters:
    1692: + newdm  - the newly loaded `PC`, this needs to have been created with `PCCreate()` or
    1693:            some related function before a call to `PCLoad()`.
    1694: - viewer - binary file viewer `PETSCVIEWERBINARY`, obtained from `PetscViewerBinaryOpen()`

    1696:   Level: intermediate

    1698:   Note:
    1699:   The type is determined by the data in the file, any `PCType` set into the `PC` before this call is ignored.

    1701: .seealso: [](ch_ksp), `PC`, `PetscViewerBinaryOpen()`, `PCView()`, `MatLoad()`, `VecLoad()`, `PETSCVIEWERBINARY`
    1702: @*/
    1703: PetscErrorCode PCLoad(PC newdm, PetscViewer viewer)
    1704: {
    1705:   PetscBool isbinary;
    1706:   PetscInt  classid;
    1707:   char      type[256];

    1709:   PetscFunctionBegin;
    1712:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
    1713:   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");

    1715:   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
    1716:   PetscCheck(classid == PC_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not PC next in file");
    1717:   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
    1718:   PetscCall(PCSetType(newdm, type));
    1719:   PetscTryTypeMethod(newdm, load, viewer);
    1720:   PetscFunctionReturn(PETSC_SUCCESS);
    1721: }

    1723: #include <petscdraw.h>
    1724: #if defined(PETSC_HAVE_SAWS)
    1725: #include <petscviewersaws.h>
    1726: #endif

    1728: /*@
    1729:   PCViewFromOptions - View (print or provide information about) the `PC`, based on options in the options database

    1731:   Collective

    1733:   Input Parameters:
    1734: + A    - the `PC` context
    1735: . obj  - Optional object that provides the options prefix
    1736: - name - command line option name

    1738:   Level: developer

    1740: .seealso: [](ch_ksp), `PC`, `PCView`, `PetscObjectViewFromOptions()`, `PCCreate()`
    1741: @*/
    1742: PetscErrorCode PCViewFromOptions(PC A, PetscObject obj, const char name[])
    1743: {
    1744:   PetscFunctionBegin;
    1746:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
    1747:   PetscFunctionReturn(PETSC_SUCCESS);
    1748: }

    1750: /*@
    1751:   PCView - Prints information about the `PC`

    1753:   Collective

    1755:   Input Parameters:
    1756: + pc     - the `PC` preconditioner context
    1757: - viewer - optional `PetscViewer` visualization context

    1759:   Level: intermediate

    1761:   Notes:
    1762:   The available visualization contexts include
    1763: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
    1764: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
    1765:   output where only the first processor opens
    1766:   the file. All other processors send their
    1767:   data to the first processor to print.

    1769:   The user can open an alternative visualization contexts with
    1770:   `PetscViewerASCIIOpen()` (output to a specified file).

    1772: .seealso: [](ch_ksp), `PC`, `PetscViewer`, `PetscViewerType`, `KSPView()`, `PetscViewerASCIIOpen()`
    1773: @*/
    1774: PetscErrorCode PCView(PC pc, PetscViewer viewer)
    1775: {
    1776:   PCType            cstr;
    1777:   PetscViewerFormat format;
    1778:   PetscBool         iascii, isstring, isbinary, isdraw, pop = PETSC_FALSE;
    1779: #if defined(PETSC_HAVE_SAWS)
    1780:   PetscBool issaws;
    1781: #endif

    1783:   PetscFunctionBegin;
    1785:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer));
    1787:   PetscCheckSameComm(pc, 1, viewer, 2);

    1789:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
    1790:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
    1791:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
    1792:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
    1793: #if defined(PETSC_HAVE_SAWS)
    1794:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
    1795: #endif

    1797:   if (iascii) {
    1798:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pc, viewer));
    1799:     if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  PC has not been set up so information may be incomplete\n"));
    1800:     PetscCall(PetscViewerASCIIPushTab(viewer));
    1801:     PetscTryTypeMethod(pc, view, viewer);
    1802:     PetscCall(PetscViewerASCIIPopTab(viewer));
    1803:     if (pc->mat) {
    1804:       PetscCall(PetscViewerGetFormat(viewer, &format));
    1805:       if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) {
    1806:         PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO));
    1807:         pop = PETSC_TRUE;
    1808:       }
    1809:       if (pc->pmat == pc->mat) {
    1810:         PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix = precond matrix:\n"));
    1811:         PetscCall(PetscViewerASCIIPushTab(viewer));
    1812:         PetscCall(MatView(pc->mat, viewer));
    1813:         PetscCall(PetscViewerASCIIPopTab(viewer));
    1814:       } else {
    1815:         if (pc->pmat) {
    1816:           PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix followed by preconditioner matrix:\n"));
    1817:         } else {
    1818:           PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix:\n"));
    1819:         }
    1820:         PetscCall(PetscViewerASCIIPushTab(viewer));
    1821:         PetscCall(MatView(pc->mat, viewer));
    1822:         if (pc->pmat) PetscCall(MatView(pc->pmat, viewer));
    1823:         PetscCall(PetscViewerASCIIPopTab(viewer));
    1824:       }
    1825:       if (pop) PetscCall(PetscViewerPopFormat(viewer));
    1826:     }
    1827:   } else if (isstring) {
    1828:     PetscCall(PCGetType(pc, &cstr));
    1829:     PetscCall(PetscViewerStringSPrintf(viewer, " PCType: %-7.7s", cstr));
    1830:     PetscTryTypeMethod(pc, view, viewer);
    1831:     if (pc->mat) PetscCall(MatView(pc->mat, viewer));
    1832:     if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer));
    1833:   } else if (isbinary) {
    1834:     PetscInt    classid = PC_FILE_CLASSID;
    1835:     MPI_Comm    comm;
    1836:     PetscMPIInt rank;
    1837:     char        type[256];

    1839:     PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
    1840:     PetscCallMPI(MPI_Comm_rank(comm, &rank));
    1841:     if (rank == 0) {
    1842:       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
    1843:       PetscCall(PetscStrncpy(type, ((PetscObject)pc)->type_name, 256));
    1844:       PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
    1845:     }
    1846:     PetscTryTypeMethod(pc, view, viewer);
    1847:   } else if (isdraw) {
    1848:     PetscDraw draw;
    1849:     char      str[25];
    1850:     PetscReal x, y, bottom, h;
    1851:     PetscInt  n;

    1853:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
    1854:     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
    1855:     if (pc->mat) {
    1856:       PetscCall(MatGetSize(pc->mat, &n, NULL));
    1857:       PetscCall(PetscSNPrintf(str, 25, "PC: %s (%" PetscInt_FMT ")", ((PetscObject)pc)->type_name, n));
    1858:     } else {
    1859:       PetscCall(PetscSNPrintf(str, 25, "PC: %s", ((PetscObject)pc)->type_name));
    1860:     }
    1861:     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_RED, PETSC_DRAW_BLACK, str, NULL, &h));
    1862:     bottom = y - h;
    1863:     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
    1864:     PetscTryTypeMethod(pc, view, viewer);
    1865:     PetscCall(PetscDrawPopCurrentPoint(draw));
    1866: #if defined(PETSC_HAVE_SAWS)
    1867:   } else if (issaws) {
    1868:     PetscMPIInt rank;

    1870:     PetscCall(PetscObjectName((PetscObject)pc));
    1871:     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
    1872:     if (!((PetscObject)pc)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)pc, viewer));
    1873:     if (pc->mat) PetscCall(MatView(pc->mat, viewer));
    1874:     if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer));
    1875: #endif
    1876:   }
    1877:   PetscFunctionReturn(PETSC_SUCCESS);
    1878: }

    1880: /*@C
    1881:   PCRegister -  Adds a method (`PCType`) to the PETSc preconditioner package.

    1883:   Not collective. No Fortran Support

    1885:   Input Parameters:
    1886: + sname    - name of a new user-defined solver
    1887: - function - routine to create the method context which will be stored in a `PC` when `PCSetType()` is called

    1889:   Example Usage:
    1890: .vb
    1891:    PCRegister("my_solver", MySolverCreate);
    1892: .ve

    1894:   Then, your solver can be chosen with the procedural interface via
    1895: $     PCSetType(pc, "my_solver")
    1896:   or at runtime via the option
    1897: $     -pc_type my_solver

    1899:   Level: advanced

    1901:   Note:
    1902:   A simpler alternative to using `PCRegister()` for an application specific preconditioner is to use a `PC` of `PCType` `PCSHELL` and
    1903:   provide your customizations with `PCShellSetContext()` and `PCShellSetApply()`

    1905:   `PCRegister()` may be called multiple times to add several user-defined preconditioners.

    1907: .seealso: [](ch_ksp), `PC`, `PCType`, `PCRegisterAll()`, `PCSetType()`, `PCShellSetContext()`, `PCShellSetApply()`, `PCSHELL`
    1908: @*/
    1909: PetscErrorCode PCRegister(const char sname[], PetscErrorCode (*function)(PC))
    1910: {
    1911:   PetscFunctionBegin;
    1912:   PetscCall(PCInitializePackage());
    1913:   PetscCall(PetscFunctionListAdd(&PCList, sname, function));
    1914:   PetscFunctionReturn(PETSC_SUCCESS);
    1915: }

    1917: static PetscErrorCode MatMult_PC(Mat A, Vec X, Vec Y)
    1918: {
    1919:   PC pc;

    1921:   PetscFunctionBegin;
    1922:   PetscCall(MatShellGetContext(A, &pc));
    1923:   PetscCall(PCApply(pc, X, Y));
    1924:   PetscFunctionReturn(PETSC_SUCCESS);
    1925: }

    1927: /*@
    1928:   PCComputeOperator - Computes the explicit preconditioned operator as a matrix `Mat`.

    1930:   Collective

    1932:   Input Parameters:
    1933: + pc      - the `PC` preconditioner object
    1934: - mattype - the `MatType` to be used for the operator

    1936:   Output Parameter:
    1937: . mat - the explicit preconditioned operator

    1939:   Level: advanced

    1941:   Note:
    1942:   This computation is done by applying the operators to columns of the identity matrix.
    1943:   This routine is costly in general, and is recommended for use only with relatively small systems.
    1944:   Currently, this routine uses a dense matrix format when `mattype` == `NULL`

    1946:   Developer Note:
    1947:   This should be called `PCCreateExplicitOperator()`

    1949: .seealso: [](ch_ksp), `PC`, `KSPComputeOperator()`, `MatType`
    1950: @*/
    1951: PetscErrorCode PCComputeOperator(PC pc, MatType mattype, Mat *mat)
    1952: {
    1953:   PetscInt N, M, m, n;
    1954:   Mat      A, Apc;

    1956:   PetscFunctionBegin;
    1958:   PetscAssertPointer(mat, 3);
    1959:   PetscCall(PCGetOperators(pc, &A, NULL));
    1960:   PetscCall(MatGetLocalSize(A, &m, &n));
    1961:   PetscCall(MatGetSize(A, &M, &N));
    1962:   PetscCall(MatCreateShell(PetscObjectComm((PetscObject)pc), m, n, M, N, pc, &Apc));
    1963:   PetscCall(MatShellSetOperation(Apc, MATOP_MULT, (void (*)(void))MatMult_PC));
    1964:   PetscCall(MatComputeOperator(Apc, mattype, mat));
    1965:   PetscCall(MatDestroy(&Apc));
    1966:   PetscFunctionReturn(PETSC_SUCCESS);
    1967: }

    1969: /*@
    1970:   PCSetCoordinates - sets the coordinates of all the nodes (degrees of freedom in the vector) on the local process

    1972:   Collective

    1974:   Input Parameters:
    1975: + pc     - the `PC` preconditioner context
    1976: . dim    - the dimension of the coordinates 1, 2, or 3
    1977: . nloc   - the blocked size of the coordinates array
    1978: - coords - the coordinates array

    1980:   Level: intermediate

    1982:   Notes:
    1983:   `coords` is an array of the dim coordinates for the nodes on
    1984:   the local processor, of size `dim`*`nloc`.
    1985:   If there are 108 equations (dofs) on a processor
    1986:   for a 3d displacement finite element discretization of elasticity (so
    1987:   that there are nloc = 36 = 108/3 nodes) then the array must have 108
    1988:   double precision values (ie, 3 * 36).  These x y z coordinates
    1989:   should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x,
    1990:   ... , N-1.z ].

    1992:   The information provided here can be used by some preconditioners, such as `PCGAMG`, to produce a better preconditioner.
    1993:   See also  `MatSetNearNullSpace()`.

    1995: .seealso: [](ch_ksp), `PC`, `MatSetNearNullSpace()`
    1996: @*/
    1997: PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal coords[])
    1998: {
    1999:   PetscFunctionBegin;
    2002:   PetscTryMethod(pc, "PCSetCoordinates_C", (PC, PetscInt, PetscInt, PetscReal[]), (pc, dim, nloc, coords));
    2003:   PetscFunctionReturn(PETSC_SUCCESS);
    2004: }

    2006: /*@
    2007:   PCGetInterpolations - Gets interpolation matrices for all levels (except level 0)

    2009:   Logically Collective

    2011:   Input Parameter:
    2012: . pc - the precondition context

    2014:   Output Parameters:
    2015: + num_levels     - the number of levels
    2016: - interpolations - the interpolation matrices (size of `num_levels`-1)

    2018:   Level: advanced

    2020:   Developer Note:
    2021:   Why is this here instead of in `PCMG` etc?

    2023: .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetInterpolation()`, `PCGetCoarseOperators()`
    2024: @*/
    2025: PetscErrorCode PCGetInterpolations(PC pc, PetscInt *num_levels, Mat *interpolations[])
    2026: {
    2027:   PetscFunctionBegin;
    2029:   PetscAssertPointer(num_levels, 2);
    2030:   PetscAssertPointer(interpolations, 3);
    2031:   PetscUseMethod(pc, "PCGetInterpolations_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, interpolations));
    2032:   PetscFunctionReturn(PETSC_SUCCESS);
    2033: }

    2035: /*@
    2036:   PCGetCoarseOperators - Gets coarse operator matrices for all levels (except the finest level)

    2038:   Logically Collective

    2040:   Input Parameter:
    2041: . pc - the precondition context

    2043:   Output Parameters:
    2044: + num_levels      - the number of levels
    2045: - coarseOperators - the coarse operator matrices (size of `num_levels`-1)

    2047:   Level: advanced

    2049:   Developer Note:
    2050:   Why is this here instead of in `PCMG` etc?

    2052: .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
    2053: @*/
    2054: PetscErrorCode PCGetCoarseOperators(PC pc, PetscInt *num_levels, Mat *coarseOperators[])
    2055: {
    2056:   PetscFunctionBegin;
    2058:   PetscAssertPointer(num_levels, 2);
    2059:   PetscAssertPointer(coarseOperators, 3);
    2060:   PetscUseMethod(pc, "PCGetCoarseOperators_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, coarseOperators));
    2061:   PetscFunctionReturn(PETSC_SUCCESS);
    2062: }