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_ApplySymmetricLeft, PC_ApplySymmetricRight, PC_ModifySubMatrices, PC_ApplyOnBlocks, PC_ApplyTransposeOnBlocks;
 10: PetscInt      PetscMGLevelId;
 11: PetscLogStage PCMPIStage;

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

 18:   PetscFunctionBegin;
 19:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
 20:   if (pc->pmat) {
 21:     PetscCall(MatHasOperation(pc->pmat, MATOP_GET_DIAGONAL_BLOCK, &hasopblock));
 22:     PetscCall(MatHasOperation(pc->pmat, MATOP_SOLVE, &hasopsolve));
 23:     if (size == 1) {
 24:       PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ICC, &flg1));
 25:       PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ILU, &flg2));
 26:       PetscCall(MatIsSymmetricKnown(pc->pmat, &set, &flg3));
 27:       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &isnormal, MATNORMAL, MATNORMALHERMITIAN, NULL));
 28:       if (flg1 && (!flg2 || (set && flg3))) {
 29:         *type = PCICC;
 30:       } else if (flg2) {
 31:         *type = PCILU;
 32:       } else if (isnormal) {
 33:         *type = PCNONE;
 34:       } else if (hasopblock) { /* likely is a parallel matrix run on one processor */
 35:         if (pc->kspnestlevel > 0) {
 36:           Mat D;

 38:           PetscCall(MatGetDiagonalBlock(pc->pmat, &D));
 39:           PetscCall(PetscObjectTypeCompare((PetscObject)D, ((PetscObject)pc->pmat)->type_name, &flg1)); /* make sure there is no recursive call to PCGetDefaultType_Private() */
 40:         } else flg1 = PETSC_FALSE;
 41:         if (!flg1) *type = PCBJACOBI;
 42:         else *type = PCNONE;
 43:       } else if (hasopsolve) {
 44:         *type = PCMAT;
 45:       } else {
 46:         *type = PCNONE;
 47:       }
 48:     } else {
 49:       if (hasopblock) {
 50:         *type = PCBJACOBI;
 51:       } else if (hasopsolve) {
 52:         *type = PCMAT;
 53:       } else {
 54:         *type = PCNONE;
 55:       }
 56:     }
 57:   } else *type = NULL;
 58:   PetscFunctionReturn(PETSC_SUCCESS);
 59: }

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

 64: static PetscErrorCode PCLogEventsDeactivatePush(void)
 65: {
 66:   PetscFunctionBegin;
 67:   PetscCall(KSPInitializePackage());
 68:   PetscCall(PetscLogEventDeactivatePush(KSP_Solve));
 69:   PetscCall(PetscLogEventDeactivatePush(KSP_SetUp));
 70:   PetscCall(PetscLogEventDeactivatePush(KSP_MatSolve));
 71:   PetscCall(PetscLogEventDeactivatePush(KSP_SolveTranspose));
 72:   PetscCall(PetscLogEventDeactivatePush(KSP_MatSolveTranspose));
 73:   PetscCall(PetscLogEventDeactivatePush(PC_SetUp));
 74:   PetscCall(PetscLogEventDeactivatePush(PC_SetUpOnBlocks));
 75:   PetscCall(PetscLogEventDeactivatePush(PC_Apply));
 76:   PetscCall(PetscLogEventDeactivatePush(PC_MatApply));
 77:   PetscFunctionReturn(PETSC_SUCCESS);
 78: }

 80: static PetscErrorCode PCLogEventsDeactivatePop(void)
 81: {
 82:   PetscFunctionBegin;
 83:   PetscCall(KSPInitializePackage());
 84:   PetscCall(PetscLogEventDeactivatePop(KSP_Solve));
 85:   PetscCall(PetscLogEventDeactivatePop(KSP_SetUp));
 86:   PetscCall(PetscLogEventDeactivatePop(KSP_MatSolve));
 87:   PetscCall(PetscLogEventDeactivatePop(KSP_SolveTranspose));
 88:   PetscCall(PetscLogEventDeactivatePop(KSP_MatSolveTranspose));
 89:   PetscCall(PetscLogEventDeactivatePop(PC_SetUp));
 90:   PetscCall(PetscLogEventDeactivatePop(PC_SetUpOnBlocks));
 91:   PetscCall(PetscLogEventDeactivatePop(PC_Apply));
 92:   PetscCall(PetscLogEventDeactivatePop(PC_MatApply));
 93:   PetscFunctionReturn(PETSC_SUCCESS);
 94: }

 96: /*@
 97:   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

 99:   Collective

101:   Input Parameter:
102: . pc - the `PC` preconditioner context

104:   Level: developer

106:   Notes:
107:   Any options set, including those set with `KSPSetFromOptions()` remain.

109:   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`

111: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`
112: @*/
113: PetscErrorCode PCReset(PC pc)
114: {
115:   PetscFunctionBegin;
117:   PetscTryTypeMethod(pc, reset);
118:   PetscCall(MatDestroy(&pc->pmat));
119:   PetscCall(MatDestroy(&pc->mat));

121:   pc->setupcalled = PETSC_FALSE;
122:   PetscFunctionReturn(PETSC_SUCCESS);
123: }

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

128:   Collective

130:   Input Parameter:
131: . pc - the `PC` preconditioner context

133:   Level: developer

135: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`
136: @*/
137: PetscErrorCode PCDestroy(PC *pc)
138: {
139:   PetscFunctionBegin;
140:   if (!*pc) PetscFunctionReturn(PETSC_SUCCESS);
142:   if (--((PetscObject)*pc)->refct > 0) {
143:     *pc = NULL;
144:     PetscFunctionReturn(PETSC_SUCCESS);
145:   }

147:   PetscCall(PCReset(*pc));

149:   /* if memory was published with SAWs then destroy it */
150:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*pc));
151:   PetscTryTypeMethod(*pc, destroy);
152:   PetscCall(DMDestroy(&(*pc)->dm));
153:   PetscCall(PetscHeaderDestroy(pc));
154:   PetscFunctionReturn(PETSC_SUCCESS);
155: }

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

162:   Logically Collective

164:   Input Parameters:
165: + pc  - the `PC` preconditioner context
166: - flg - `PETSC_TRUE` to use the `Amat`, `PETSC_FALSE` to use the `Pmat` (default is `PETSC_FALSE`)

168:   Options Database Key:
169: . -pc_use_amat (true|false) - use the `Amat` argument to `KSPSetOperators()` or `PCSetOperators()` to apply the operator

171:   Level: intermediate

173:   Note:
174:   For the common case in which the linear system matrix and the matrix used to construct the
175:   preconditioner are identical, this routine has no effect.

177: .seealso: [](ch_ksp), `PC`, `PCGetUseAmat()`, `PCBJACOBI`, `PCMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`,
178:           `KSPSetOperators()`, `PCSetOperators()`
179: @*/
180: PetscErrorCode PCSetUseAmat(PC pc, PetscBool flg)
181: {
182:   PetscFunctionBegin;
184:   pc->useAmat = flg;
185:   PetscFunctionReturn(PETSC_SUCCESS);
186: }

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

191:   Logically Collective

193:   Input Parameters:
194: + pc  - iterative context obtained from `PCCreate()`
195: - flg - `PETSC_TRUE` indicates you want the error generated

197:   Level: advanced

199:   Notes:
200:   Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call `KSPGetConvergedReason()` after a `KSPSolve()`
201:   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
202:   detected.

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

206: .seealso: [](ch_ksp), `PC`, `KSPSetErrorIfNotConverged()`, `PCGetInitialGuessNonzero()`, `PCSetInitialGuessKnoll()`, `PCGetInitialGuessKnoll()`
207: @*/
208: PetscErrorCode PCSetErrorIfFailure(PC pc, PetscBool flg)
209: {
210:   PetscFunctionBegin;
213:   pc->erroriffailure = flg;
214:   PetscFunctionReturn(PETSC_SUCCESS);
215: }

217: /*@
218:   PCGetUseAmat - Gets the flag that indicates that when the preconditioner needs to apply (part of) the
219:   operator during the preconditioning process it applies the `Amat` provided to `TSSetRHSJacobian()`,
220:   `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the `Pmat`.

222:   Logically Collective

224:   Input Parameter:
225: . pc - the `PC` preconditioner context

227:   Output Parameter:
228: . flg - `PETSC_TRUE` to use the `Amat`, `PETSC_FALSE` to use the `Pmat`

230:   Level: intermediate

232: .seealso: [](ch_ksp), `PC`, `PCSetUseAmat()`, `PCBJACOBI`, `PCMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`
233: @*/
234: PetscErrorCode PCGetUseAmat(PC pc, PetscBool *flg)
235: {
236:   PetscFunctionBegin;
238:   *flg = pc->useAmat;
239:   PetscFunctionReturn(PETSC_SUCCESS);
240: }

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

245:   Collective

247:   Input Parameters:
248: + pc    - the `PC`
249: - level - the nest level

251:   Level: developer

253: .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPGetNestLevel()`, `PCGetKSPNestLevel()`, `KSPSetNestLevel()`
254: @*/
255: PetscErrorCode PCSetKSPNestLevel(PC pc, PetscInt level)
256: {
257:   PetscFunctionBegin;
260:   pc->kspnestlevel = level;
261:   PetscFunctionReturn(PETSC_SUCCESS);
262: }

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

267:   Not Collective

269:   Input Parameter:
270: . pc - the `PC`

272:   Output Parameter:
273: . level - the nest level

275:   Level: developer

277: .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPSetNestLevel()`, `PCSetKSPNestLevel()`, `KSPGetNestLevel()`
278: @*/
279: PetscErrorCode PCGetKSPNestLevel(PC pc, PetscInt *level)
280: {
281:   PetscFunctionBegin;
283:   PetscAssertPointer(level, 2);
284:   *level = pc->kspnestlevel;
285:   PetscFunctionReturn(PETSC_SUCCESS);
286: }

288: /*@
289:   PCCreate - Creates a preconditioner context, `PC`

291:   Collective

293:   Input Parameter:
294: . comm - MPI communicator

296:   Output Parameter:
297: . newpc - location to put the `PC` preconditioner context

299:   Level: developer

301:   Notes:
302:   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`.

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

306:   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`
307:   in parallel. For dense matrices it is always `PCNONE`.

309: .seealso: [](ch_ksp), `PC`, `PCType`, `PCSetType`, `PCSetUp()`, `PCApply()`, `PCDestroy()`, `KSP`, `KSPGetPC()`
310: @*/
311: PetscErrorCode PCCreate(MPI_Comm comm, PC *newpc)
312: {
313:   PC pc;

315:   PetscFunctionBegin;
316:   PetscAssertPointer(newpc, 2);
317:   PetscCall(PCInitializePackage());

319:   PetscCall(PetscHeaderCreate(pc, PC_CLASSID, "PC", "Preconditioner", "PC", comm, PCDestroy, PCView));
320:   PetscCall(PCParametersInitialize(pc));
321:   *newpc = pc;
322:   PetscFunctionReturn(PETSC_SUCCESS);
323: }

325: /*@
326:   PCParametersInitialize - Sets the base defaults for parameters in `pc`, updating a parameter's current value when it matches its previously recorded default.

328:   Logically collective

330:   Input Parameter:
331: . pc - the `PC` object

333:   Level: developer

335:   Notes:

337:   The base defaults are the non-type-specific values established when the `PC` is created. A `PCType` constructor may subsequently replace them with type-specific defaults.

339:   Developer Notes:

341:   `PCCreate()` calls this routine to establish the base defaults. `PCSetType()` calls it before constructing a new `PCType`, so the recorded defaults associated with the previous type are replaced before the new type installs its own defaults.

343:   Default tracking is based on value equality, not on whether a setter was called. Consequently, an explicitly assigned value that equals the recorded default may be updated when the type changes.

345: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCDestroy()`, `PetscObjectParameterSetDefault()`
346: @*/
347: PetscErrorCode PCParametersInitialize(PC pc)
348: {
349:   PetscObjectParameterSetDefault(pc, useAmat, PETSC_FALSE);
350:   return PETSC_SUCCESS;
351: }

353: /*@
354:   PCApply - Applies the preconditioner to a vector.

356:   Collective

358:   Input Parameters:
359: + pc - the `PC` preconditioner context
360: - x  - input vector

362:   Output Parameter:
363: . y - output vector

365:   Level: developer

367: .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`, `PCApplyBAorAB()`
368: @*/
369: PetscErrorCode PCApply(PC pc, Vec x, Vec y)
370: {
371:   PetscInt m, n, mv, nv;

373:   PetscFunctionBegin;
377:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
378:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
379:   /* use pmat to check vector sizes since for KSPLSQR the pmat may be of a different size than mat */
380:   PetscCall(MatGetLocalSize(pc->pmat, &m, &n));
381:   PetscCall(VecGetLocalSize(x, &mv));
382:   PetscCall(VecGetLocalSize(y, &nv));
383:   /* check pmat * y = x is feasible */
384:   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);
385:   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);
386:   PetscCall(VecSetErrorIfLocked(y, 3));

388:   PetscCall(PCSetUp(pc));
389:   PetscCall(VecLockReadPush(x));
390:   PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0));
391:   PetscUseTypeMethod(pc, apply, x, y);
392:   PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0));
393:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
394:   PetscCall(VecLockReadPop(x));
395:   PetscFunctionReturn(PETSC_SUCCESS);
396: }

398: /*
399:    Checks that the blocks of vectors In and Out are dense and have layouts compatible with each other and with Pmat, inname and outname naming them in the error messages
400: */
401: static PetscErrorCode PCMatCheckBlocks_Private(PC pc, Mat In, Mat Out, const char *inname, const char *outname)
402: {
403:   Mat       A;
404:   PetscInt  m1, M1, m2, M2, n1, N1, n2, N2, m3, M3, n3, N3;
405:   PetscBool match;

407:   PetscFunctionBegin;
408:   PetscCall(PCGetOperators(pc, NULL, &A));
409:   PetscCall(MatGetLocalSize(A, &m3, &n3));
410:   PetscCall(MatGetLocalSize(In, &m2, &n2));
411:   PetscCall(MatGetLocalSize(Out, &m1, &n1));
412:   PetscCall(MatGetSize(A, &M3, &N3));
413:   PetscCall(MatGetSize(In, &M2, &N2));
414:   PetscCall(MatGetSize(Out, &M1, &N1));
415:   PetscCheck(n1 == n2 && N1 == N2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible number of columns between block of %s (n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and block of %s (n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")", inname, n2, N2, outname, n1, N1);
416:   PetscCheck(m2 == m3 && M2 == M3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout between block of %s (m,M) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and Pmat (m,M)x(n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")x(%" PetscInt_FMT ",%" PetscInt_FMT ")", inname, m2, M2, m3, M3, n3, N3);
417:   PetscCheck(m1 == n3 && M1 == N3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout between block of %s (m,M) = (%" PetscInt_FMT ",%" PetscInt_FMT ") and Pmat (m,M)x(n,N) = (%" PetscInt_FMT ",%" PetscInt_FMT ")x(%" PetscInt_FMT ",%" PetscInt_FMT ")", outname, m1, M1, m3, M3, n3, N3);
418:   PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)Out, &match, MATSEQDENSE, MATMPIDENSE, ""));
419:   PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of %s not stored in a dense Mat", outname);
420:   PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)In, &match, MATSEQDENSE, MATMPIDENSE, ""));
421:   PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of %s not stored in a dense Mat", inname);
422:   PetscFunctionReturn(PETSC_SUCCESS);
423: }

425: static PetscErrorCode PCMatApplyTranspose_Private(PC pc, Mat X, Mat Y, PetscBool transpose)
426: {
427:   Vec      cy, cx;
428:   PetscInt n1, N1;

430:   PetscFunctionBegin;
434:   PetscCheckSameComm(pc, 1, X, 2);
435:   PetscCheckSameComm(pc, 1, Y, 3);
436:   PetscCheck(Y != X, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "Y and X must be different matrices");
437:   PetscCall(PCMatCheckBlocks_Private(pc, X, Y, "input vectors", "output vectors"));
438:   PetscCall(MatGetSize(Y, NULL, &N1));
439:   PetscCall(PCSetUp(pc));
440:   if (!transpose && pc->ops->matapply) {
441:     PetscCall(PetscLogEventBegin(PC_MatApply, pc, X, Y, 0));
442:     PetscUseTypeMethod(pc, matapply, X, Y);
443:     PetscCall(PetscLogEventEnd(PC_MatApply, pc, X, Y, 0));
444:   } else if (transpose && pc->ops->matapplytranspose) {
445:     PetscCall(PetscLogEventBegin(PC_MatApply, pc, X, Y, 0));
446:     PetscUseTypeMethod(pc, matapplytranspose, X, Y);
447:     PetscCall(PetscLogEventEnd(PC_MatApply, pc, X, Y, 0));
448:   } else {
449:     PetscCall(PetscInfo(pc, "PC type %s applying column by column\n", ((PetscObject)pc)->type_name));
450:     for (n1 = 0; n1 < N1; ++n1) {
451:       PetscCall(MatDenseGetColumnVecRead(X, n1, &cx));
452:       PetscCall(MatDenseGetColumnVecWrite(Y, n1, &cy));
453:       if (!transpose) PetscCall(PCApply(pc, cx, cy));
454:       else PetscCall(PCApplyTranspose(pc, cx, cy));
455:       PetscCall(MatDenseRestoreColumnVecWrite(Y, n1, &cy));
456:       PetscCall(MatDenseRestoreColumnVecRead(X, n1, &cx));
457:     }
458:   }
459:   PetscFunctionReturn(PETSC_SUCCESS);
460: }

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

465:   Collective

467:   Input Parameters:
468: + pc - the `PC` preconditioner context
469: - X  - block of input vectors

471:   Output Parameter:
472: . Y - block of output vectors

474:   Level: developer

476: .seealso: [](ch_ksp), `PC`, `PCApply()`, `KSPMatSolve()`
477: @*/
478: PetscErrorCode PCMatApply(PC pc, Mat X, Mat Y)
479: {
480:   PetscFunctionBegin;
481:   PetscCall(PCMatApplyTranspose_Private(pc, X, Y, PETSC_FALSE));
482:   PetscFunctionReturn(PETSC_SUCCESS);
483: }

485: /*@
486:   PCMatApplyTranspose - Applies the transpose of preconditioner to multiple vectors stored as a `MATDENSE`. Like `PCApplyTranspose()`, `Y` and `X` must be different matrices.

488:   Collective

490:   Input Parameters:
491: + pc - the `PC` preconditioner context
492: - X  - block of input vectors

494:   Output Parameter:
495: . Y - block of output vectors

497:   Level: developer

499: .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`, `KSPMatSolveTranspose()`
500: @*/
501: PetscErrorCode PCMatApplyTranspose(PC pc, Mat X, Mat Y)
502: {
503:   PetscFunctionBegin;
504:   PetscCall(PCMatApplyTranspose_Private(pc, X, Y, PETSC_TRUE));
505:   PetscFunctionReturn(PETSC_SUCCESS);
506: }

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

511:   Collective

513:   Input Parameters:
514: + pc - the `PC` preconditioner context
515: - x  - input vector

517:   Output Parameter:
518: . y - output vector

520:   Level: developer

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

525: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricRight()`
526: @*/
527: PetscErrorCode PCApplySymmetricLeft(PC pc, Vec x, Vec y)
528: {
529:   PetscFunctionBegin;
533:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
534:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
535:   PetscCall(PCSetUp(pc));
536:   PetscCall(VecLockReadPush(x));
537:   PetscCall(PetscLogEventBegin(PC_ApplySymmetricLeft, pc, x, y, 0));
538:   PetscUseTypeMethod(pc, applysymmetricleft, x, y);
539:   PetscCall(PetscLogEventEnd(PC_ApplySymmetricLeft, pc, x, y, 0));
540:   PetscCall(VecLockReadPop(x));
541:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
542:   PetscFunctionReturn(PETSC_SUCCESS);
543: }

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

548:   Collective

550:   Input Parameters:
551: + pc - the `PC` preconditioner context
552: - x  - input vector

554:   Output Parameter:
555: . y - output vector

557:   Level: developer

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

562: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricLeft()`
563: @*/
564: PetscErrorCode PCApplySymmetricRight(PC pc, Vec x, Vec y)
565: {
566:   PetscFunctionBegin;
570:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
571:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
572:   PetscCall(PCSetUp(pc));
573:   PetscCall(VecLockReadPush(x));
574:   PetscCall(PetscLogEventBegin(PC_ApplySymmetricRight, pc, x, y, 0));
575:   PetscUseTypeMethod(pc, applysymmetricright, x, y);
576:   PetscCall(PetscLogEventEnd(PC_ApplySymmetricRight, pc, x, y, 0));
577:   PetscCall(VecLockReadPop(x));
578:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
579:   PetscFunctionReturn(PETSC_SUCCESS);
580: }

582: /*@
583:   PCApplyTranspose - Applies the transpose of preconditioner to a vector.

585:   Collective

587:   Input Parameters:
588: + pc - the `PC` preconditioner context
589: - x  - input vector

591:   Output Parameter:
592: . y - output vector

594:   Level: developer

596:   Note:
597:   For complex numbers this applies the non-Hermitian transpose.

599:   Developer Note:
600:   We need to implement a `PCApplyHermitianTranspose()`

602: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyBAorAB()`, `PCApplyBAorABTranspose()`, `PCApplyTransposeExists()`
603: @*/
604: PetscErrorCode PCApplyTranspose(PC pc, Vec x, Vec y)
605: {
606:   PetscFunctionBegin;
610:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
611:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
612:   PetscCall(PCSetUp(pc));
613:   PetscCall(VecLockReadPush(x));
614:   PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0));
615:   PetscUseTypeMethod(pc, applytranspose, x, y);
616:   PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0));
617:   PetscCall(VecLockReadPop(x));
618:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
619:   PetscFunctionReturn(PETSC_SUCCESS);
620: }

622: /*@
623:   PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation

625:   Collective

627:   Input Parameter:
628: . pc - the `PC` preconditioner context

630:   Output Parameter:
631: . flg - `PETSC_TRUE` if a transpose operation is defined

633:   Level: developer

635: .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`
636: @*/
637: PetscErrorCode PCApplyTransposeExists(PC pc, PetscBool *flg)
638: {
639:   PetscFunctionBegin;
641:   PetscAssertPointer(flg, 2);
642:   if (pc->ops->applytranspose) *flg = PETSC_TRUE;
643:   else *flg = PETSC_FALSE;
644:   PetscFunctionReturn(PETSC_SUCCESS);
645: }

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

650:   Collective

652:   Input Parameters:
653: + pc   - the `PC` preconditioner context
654: . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
655: . x    - input vector
656: - work - work vector

658:   Output Parameter:
659: . y - output vector

661:   Level: developer

663: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorABTranspose()`
664: @*/
665: PetscErrorCode PCApplyBAorAB(PC pc, PCSide side, Vec x, Vec y, Vec work)
666: {
667:   PetscFunctionBegin;
673:   PetscCheckSameComm(pc, 1, x, 3);
674:   PetscCheckSameComm(pc, 1, y, 4);
675:   PetscCheckSameComm(pc, 1, work, 5);
676:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
677:   PetscCheck(side == PC_LEFT || side == PC_SYMMETRIC || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right, left, or symmetric");
678:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE));

680:   PetscCall(PCSetUp(pc));
681:   if (pc->ops->applyBA) {
682:     PetscUseTypeMethod(pc, applyBA, side, x, y, work);
683:   } else if (side == PC_RIGHT) {
684:     PetscCall(PCApply(pc, x, work));
685:     PetscCall(MatMult(pc->mat, work, y));
686:   } else if (side == PC_LEFT) {
687:     PetscCall(MatMult(pc->mat, x, work));
688:     PetscCall(PCApply(pc, work, y));
689:   } else if (side == PC_SYMMETRIC) {
690:     /* There's an extra copy here; maybe should provide 2 work vectors instead? */
691:     PetscCall(PCApplySymmetricRight(pc, x, work));
692:     PetscCall(MatMult(pc->mat, work, y));
693:     PetscCall(VecCopy(y, work));
694:     PetscCall(PCApplySymmetricLeft(pc, work, y));
695:   }
696:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
697:   PetscFunctionReturn(PETSC_SUCCESS);
698: }

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

705:   Collective

707:   Input Parameters:
708: + pc   - the `PC` preconditioner context
709: . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
710: . x    - input vector
711: - work - work vector

713:   Output Parameter:
714: . y - output vector

716:   Level: developer

718:   Note:
719:   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
720:   defined by $B^T$. This is why this has the funny form that it computes $B^T * A^T$

722: .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorAB()`
723: @*/
724: PetscErrorCode PCApplyBAorABTranspose(PC pc, PCSide side, Vec x, Vec y, Vec work)
725: {
726:   PetscFunctionBegin;
731:   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
732:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE));
733:   if (pc->ops->applyBAtranspose) {
734:     PetscUseTypeMethod(pc, applyBAtranspose, side, x, y, work);
735:     if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
736:     PetscFunctionReturn(PETSC_SUCCESS);
737:   }
738:   PetscCheck(side == PC_LEFT || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right or left");

740:   PetscCall(PCSetUp(pc));
741:   if (side == PC_RIGHT) {
742:     PetscCall(PCApplyTranspose(pc, x, work));
743:     PetscCall(MatMultTranspose(pc->mat, work, y));
744:   } else if (side == PC_LEFT) {
745:     PetscCall(MatMultTranspose(pc->mat, x, work));
746:     PetscCall(PCApplyTranspose(pc, work, y));
747:   }
748:   /* add support for PC_SYMMETRIC */
749:   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
750:   PetscFunctionReturn(PETSC_SUCCESS);
751: }

753: /*@
754:   PCApplyRichardsonExists - Determines whether a particular preconditioner has a
755:   built-in fast application of Richardson's method.

757:   Not Collective

759:   Input Parameter:
760: . pc - the preconditioner

762:   Output Parameter:
763: . exists - `PETSC_TRUE` or `PETSC_FALSE`

765:   Level: developer

767: .seealso: [](ch_ksp), `PC`, `KSPRICHARDSON`, `PCApplyRichardson()`, `PCMatApplyRichardsonExists()`
768: @*/
769: PetscErrorCode PCApplyRichardsonExists(PC pc, PetscBool *exists)
770: {
771:   PetscFunctionBegin;
773:   PetscAssertPointer(exists, 2);
774:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
775:   else *exists = PETSC_FALSE;
776:   PetscFunctionReturn(PETSC_SUCCESS);
777: }

779: /*@
780:   PCApplyRichardson - Applies several steps of Richardson iteration with
781:   the particular preconditioner. This routine is usually used by the
782:   Krylov solvers and not the application code directly.

784:   Collective

786:   Input Parameters:
787: + pc        - the `PC` preconditioner context
788: . b         - the right-hand side
789: . w         - one work vector
790: . rtol      - relative decrease in residual norm convergence criteria
791: . abstol    - absolute residual norm convergence criteria
792: . dtol      - divergence residual norm increase criteria
793: . its       - the number of iterations to apply.
794: - guesszero - if the input x contains nonzero initial guess

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

801:   Level: developer

803:   Notes:
804:   Most preconditioners do not support this function. Use the command
805:   `PCApplyRichardsonExists()` to determine if one does.

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

810: .seealso: [](ch_ksp), `PC`, `PCApplyRichardsonExists()`, `PCMatApplyRichardson()`
811: @*/
812: PetscErrorCode PCApplyRichardson(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
813: {
814:   PetscFunctionBegin;
819:   PetscCheck(b != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "b and y must be different vectors");
820:   PetscCall(PCSetUp(pc));
821:   PetscUseTypeMethod(pc, applyrichardson, b, y, w, rtol, abstol, dtol, its, guesszero, outits, reason);
822:   PetscFunctionReturn(PETSC_SUCCESS);
823: }

825: /*@
826:   PCMatApplyRichardsonExists - Determines whether a particular preconditioner has a
827:   built-in fast application of Richardson's method on a block of vectors stored as a `MATDENSE`.

829:   Not Collective

831:   Input Parameter:
832: . pc - the preconditioner

834:   Output Parameter:
835: . exists - `PETSC_TRUE` or `PETSC_FALSE`

837:   Level: developer

839: .seealso: [](ch_ksp), `PC`, `KSPRICHARDSON`, `PCMatApplyRichardson()`, `PCApplyRichardsonExists()`
840: @*/
841: PetscErrorCode PCMatApplyRichardsonExists(PC pc, PetscBool *exists)
842: {
843:   PetscFunctionBegin;
845:   PetscAssertPointer(exists, 2);
846:   if (pc->ops->matapplyrichardson) *exists = PETSC_TRUE;
847:   else *exists = PETSC_FALSE;
848:   PetscFunctionReturn(PETSC_SUCCESS);
849: }

851: /*@
852:   PCMatApplyRichardson - Applies several steps of Richardson iteration with the particular preconditioner
853:   to multiple vectors stored as a `MATDENSE`. This routine is usually used by the Krylov solvers and not
854:   the application code directly.

856:   Collective

858:   Input Parameters:
859: + pc        - the `PC` preconditioner context
860: . B         - the block of right-hand sides
861: . W         - one work block of vectors, may be `NULL`
862: . rtol      - relative decrease in residual norm convergence criteria
863: . abstol    - absolute residual norm convergence criteria
864: . dtol      - divergence residual norm increase criteria
865: . its       - the number of iterations to apply
866: - guesszero - `PETSC_TRUE` if `Y` is known to be initially zero

868:   Output Parameters:
869: + outits - number of iterations actually used
870: . reason - the reason the apply terminated
871: - Y      - the block of solutions (also contains the initial guess if guesszero is `PETSC_FALSE`)

873:   Level: developer

875:   Notes:
876:   Most preconditioners do not support this function. Use the command
877:   `PCMatApplyRichardsonExists()` to determine if one does.

879:   `W` may be `NULL`. For example `KSPRICHARDSON` does not provide one, so implementations that need scratch space must allocate it themselves.

881:   Like `PCMatApply()`, `B` and `Y` must be different matrices.

883: .seealso: [](ch_ksp), `PC`, `PCMatApplyRichardsonExists()`, `PCApplyRichardson()`, `PCMatApply()`, `KSPMatSolve()`
884: @*/
885: PetscErrorCode PCMatApplyRichardson(PC pc, Mat B, Mat Y, Mat W, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
886: {
887:   PetscFunctionBegin;
892:   PetscCheckSameComm(pc, 1, B, 2);
893:   PetscCheckSameComm(pc, 1, Y, 3);
894:   if (W) PetscCheckSameComm(pc, 1, W, 4);
895:   PetscCheck(Y != B, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "Y and B must be different matrices");
896:   PetscCheck(!W || (W != Y && W != B), PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "W must be different from B and Y");
897:   PetscCall(PCMatCheckBlocks_Private(pc, B, Y, "right-hand sides", "solutions"));
898:   /* W has the same layout as B, so it is checked against Pmat and against the number of columns of Y in the same way */
899:   if (W) PetscCall(PCMatCheckBlocks_Private(pc, W, Y, "work vectors", "solutions"));
900:   PetscCall(PCSetUp(pc));
901:   PetscUseTypeMethod(pc, matapplyrichardson, B, Y, W, rtol, abstol, dtol, its, guesszero, outits, reason);
902:   PetscFunctionReturn(PETSC_SUCCESS);
903: }

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

908:   Logically Collective

910:   Input Parameters:
911: + pc     - the `PC` preconditioner context
912: - reason - the reason it failed

914:   Level: advanced

916: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCFailedReason`
917: @*/
918: PetscErrorCode PCSetFailedReason(PC pc, PCFailedReason reason)
919: {
920:   PetscFunctionBegin;
922:   pc->failedreason = reason;
923:   PetscFunctionReturn(PETSC_SUCCESS);
924: }

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

929:   Not Collective

931:   Input Parameter:
932: . pc - the `PC` preconditioner context

934:   Output Parameter:
935: . reason - the reason it failed

937:   Level: advanced

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

944: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCSetFailedReason()`, `PCFailedReason`
945: @*/
946: PetscErrorCode PCGetFailedReason(PC pc, PCFailedReason *reason)
947: {
948:   PetscFunctionBegin;
950:   *reason = pc->failedreason;
951:   PetscFunctionReturn(PETSC_SUCCESS);
952: }

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

957:   Collective

959:   Input Parameter:
960: . pc - the `PC` preconditioner context

962:   Level: advanced

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

968: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()`, `PCFailedReason`
969: @*/
970: PetscErrorCode PCReduceFailedReason(PC pc)
971: {
972:   PetscInt buf;

974:   PetscFunctionBegin;
976:   buf = (PetscInt)pc->failedreason;
977:   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &buf, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc)));
978:   pc->failedreason = (PCFailedReason)buf;
979:   PetscFunctionReturn(PETSC_SUCCESS);
980: }

982: /*
983:       a setupcall of 0 indicates never setup,
984:                      1 indicates has been previously setup
985:                     -1 indicates a PCSetUp() was attempted and failed
986: */
987: /*@
988:   PCSetUp - Prepares for the use of a preconditioner. Performs all the one-time operations needed before the preconditioner
989:   can be used with `PCApply()`

991:   Collective

993:   Input Parameter:
994: . pc - the `PC` preconditioner context

996:   Level: developer

998:   Notes:
999:   For example, for `PCLU` this will compute the factorization.

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

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

1006: .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `KSPSetUp()`, `PCSetUpOnBlocks()`
1007: @*/
1008: PetscErrorCode PCSetUp(PC pc)
1009: {
1010:   const char *def;
1011:   MatState    matstate;

1013:   PetscFunctionBegin;
1015:   PetscCheck(pc->mat, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Missing A matrix. Use PCSetOperators()");
1016:   PetscCheck(pc->pmat, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Missing P matrix. Use PCSetOperators()");

1018:   if (pc->setupcalled && pc->reusepreconditioner) {
1019:     PetscCall(PetscInfo(pc, "Leaving PC with identical preconditioner since reuse preconditioner is set\n"));
1020:     PetscFunctionReturn(PETSC_SUCCESS);
1021:   }

1023:   PetscCall(MatGetState(pc->pmat, &matstate));
1024:   if (!pc->setupcalled) pc->flag = DIFFERENT_NONZERO_PATTERN;
1025:   else {
1026:     PetscBool same;

1028:     PetscCall(MatStateCompare(matstate, pc->matstate, &same));
1029:     if (same) PetscFunctionReturn(PETSC_SUCCESS);
1030:     pc->flag = SAME_NONZERO_PATTERN;
1031:     if (matstate.nonzerostate != pc->matstate.nonzerostate) {
1032:       PetscCall(PetscInfo(pc, "Setting up PC with different nonzero pattern\n"));
1033:       pc->flag = DIFFERENT_NONZERO_PATTERN;
1034:     }
1035:   }
1036:   pc->matstate = matstate;

1038:   if (!((PetscObject)pc)->type_name) {
1039:     PetscCall(PCGetDefaultType_Private(pc, &def));
1040:     PetscCall(PCSetType(pc, def));
1041:   }

1043:   PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure));
1044:   PetscCall(MatSetErrorIfFailure(pc->mat, pc->erroriffailure));
1045:   PetscCall(PetscLogEventBegin(PC_SetUp, pc, 0, 0, 0));
1046:   if (pc->ops->setup) {
1047:     PetscCall(PCLogEventsDeactivatePush());
1048:     PetscUseTypeMethod(pc, setup);
1049:     PetscCall(PCLogEventsDeactivatePop());
1050:   }
1051:   PetscCall(PetscLogEventEnd(PC_SetUp, pc, 0, 0, 0));
1052:   if (pc->postsetup) PetscCall((*pc->postsetup)(pc));
1053:   pc->setupcalled = PETSC_TRUE;
1054:   PetscFunctionReturn(PETSC_SUCCESS);
1055: }

1057: /*@
1058:   PCSetUpOnBlocks - Sets up the preconditioner for each block in
1059:   the block Jacobi, overlapping Schwarz, and fieldsplit methods.

1061:   Collective

1063:   Input Parameter:
1064: . pc - the `PC` preconditioner context

1066:   Level: developer

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

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

1074: .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCCreate()`, `PCApply()`, `PCDestroy()`
1075: @*/
1076: PetscErrorCode PCSetUpOnBlocks(PC pc)
1077: {
1078:   PetscFunctionBegin;
1080:   if (!pc->setupcalled) PetscCall(PCSetUp(pc)); /* "if" to prevent -info extra prints */
1081:   if (!pc->ops->setuponblocks) PetscFunctionReturn(PETSC_SUCCESS);
1082:   PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure));
1083:   PetscCall(PetscLogEventBegin(PC_SetUpOnBlocks, pc, 0, 0, 0));
1084:   PetscCall(PCLogEventsDeactivatePush());
1085:   PetscUseTypeMethod(pc, setuponblocks);
1086:   PetscCall(PCLogEventsDeactivatePop());
1087:   PetscCall(PetscLogEventEnd(PC_SetUpOnBlocks, pc, 0, 0, 0));
1088:   PetscFunctionReturn(PETSC_SUCCESS);
1089: }

1091: /*@
1092:   PCSetModifySubMatrices - Sets a user-defined routine for modifying the
1093:   submatrices that arise within certain subdomain-based preconditioners such as `PCASM`

1095:   Logically Collective

1097:   Input Parameters:
1098: + pc   - the `PC` preconditioner context
1099: . func - routine for modifying the submatrices, see `PCModifySubMatricesFn`
1100: - ctx  - optional user-defined context (may be `NULL`)

1102:   Level: advanced

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

1109:   `PCSetModifySubMatrices()` MUST be called before `KSPSetUp()` and
1110:   `KSPSolve()`.

1112:   A routine set by `PCSetModifySubMatrices()` is currently called within
1113:   `PCBJACOBI`, `PCASM`, `PCGASM`, and `PCHPDDM`.
1114:   All other preconditioners ignore this routine.

1116: .seealso: [](ch_ksp), `PC`, `PCModifySubMatricesFn`, `PCBJACOBI`, `PCASM`, `PCModifySubMatrices()`
1117: @*/
1118: PetscErrorCode PCSetModifySubMatrices(PC pc, PCModifySubMatricesFn *func, PetscCtx ctx)
1119: {
1120:   PetscFunctionBegin;
1122:   pc->modifysubmatrices  = func;
1123:   pc->modifysubmatricesP = ctx;
1124:   PetscFunctionReturn(PETSC_SUCCESS);
1125: }

1127: /*@
1128:   PCModifySubMatrices - Calls an optional user-defined routine within
1129:   certain preconditioners if one has been set with `PCSetModifySubMatrices()`.

1131:   Collective

1133:   Input Parameters:
1134: + pc     - the `PC` preconditioner context
1135: . nsub   - the number of local submatrices
1136: . row    - an array of index sets that contain the global row numbers
1137:          that comprise each local submatrix
1138: . col    - an array of index sets that contain the global column numbers
1139:          that comprise each local submatrix
1140: . submat - array of local submatrices
1141: - ctx    - optional user-defined context for private data for the
1142:          user-defined routine (may be `NULL`)

1144:   Output Parameter:
1145: . submat - array of local submatrices (the entries of which may
1146:             have been modified)

1148:   Level: developer

1150:   Note:
1151:   The user should NOT generally call this routine, as it will
1152:   automatically be called within certain preconditioners.

1154: .seealso: [](ch_ksp), `PC`, `PCModifySubMatricesFn`, `PCSetModifySubMatrices()`
1155: @*/
1156: PetscErrorCode PCModifySubMatrices(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], PetscCtx ctx)
1157: {
1158:   PetscFunctionBegin;
1160:   if (!pc->modifysubmatrices) PetscFunctionReturn(PETSC_SUCCESS);
1161:   PetscCall(PetscLogEventBegin(PC_ModifySubMatrices, pc, 0, 0, 0));
1162:   PetscCall((*pc->modifysubmatrices)(pc, nsub, row, col, submat, ctx));
1163:   PetscCall(PetscLogEventEnd(PC_ModifySubMatrices, pc, 0, 0, 0));
1164:   PetscFunctionReturn(PETSC_SUCCESS);
1165: }

1167: /*@
1168:   PCSetOperators - Sets the matrix associated with the linear system and
1169:   a (possibly) different one from which the preconditioner will be constructed.

1171:   Logically Collective

1173:   Input Parameters:
1174: + pc   - the `PC` preconditioner context
1175: . Amat - the matrix that defines the linear system
1176: - Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.

1178:   Level: advanced

1180:   Notes:
1181:   Using this routine directly is rarely needed, the preferred, and equivalent, usage is `KSPSetOperators()`.

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

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

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

1195: .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`
1196:  @*/
1197: PetscErrorCode PCSetOperators(PC pc, Mat Amat, Mat Pmat)
1198: {
1199:   PetscInt m1, n1, m2, n2;

1201:   PetscFunctionBegin;
1205:   if (Amat) PetscCheckSameComm(pc, 1, Amat, 2);
1206:   if (Pmat) PetscCheckSameComm(pc, 1, Pmat, 3);
1207:   if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) {
1208:     PetscCall(MatGetLocalSize(Amat, &m1, &n1));
1209:     PetscCall(MatGetLocalSize(pc->mat, &m2, &n2));
1210:     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);
1211:     PetscCall(MatGetLocalSize(Pmat, &m1, &n1));
1212:     PetscCall(MatGetLocalSize(pc->pmat, &m2, &n2));
1213:     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);
1214:   }

1216:   if (Pmat != pc->pmat) {
1217:     /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */
1218:     PetscCall(MatStateInvalidate(pc->matstate));
1219:   }

1221:   /* reference first in case the matrices are the same */
1222:   PetscCall(PetscObjectReference((PetscObject)Amat));
1223:   PetscCall(MatDestroy(&pc->mat));
1224:   PetscCall(PetscObjectReference((PetscObject)Pmat));
1225:   PetscCall(MatDestroy(&pc->pmat));
1226:   pc->mat  = Amat;
1227:   pc->pmat = Pmat;
1228:   PetscFunctionReturn(PETSC_SUCCESS);
1229: }

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

1234:   Logically Collective

1236:   Input Parameters:
1237: + pc   - the `PC` preconditioner context
1238: - flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner

1240:   Level: intermediate

1242:   Note:
1243:   Normally if a matrix inside a `PC` changes the `PC` automatically updates itself using information from the changed matrix. This option
1244:   prevents this.

1246: .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCGetReusePreconditioner()`, `KSPSetReusePreconditioner()`
1247:  @*/
1248: PetscErrorCode PCSetReusePreconditioner(PC pc, PetscBool flag)
1249: {
1250:   PetscFunctionBegin;
1253:   pc->reusepreconditioner = flag;
1254:   PetscTryMethod(pc, "PCSetReusePreconditioner_C", (PC, PetscBool), (pc, flag));
1255:   PetscFunctionReturn(PETSC_SUCCESS);
1256: }

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

1261:   Not Collective

1263:   Input Parameter:
1264: . pc - the `PC` preconditioner context

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

1269:   Level: intermediate

1271: .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCSetReusePreconditioner()`
1272:  @*/
1273: PetscErrorCode PCGetReusePreconditioner(PC pc, PetscBool *flag)
1274: {
1275:   PetscFunctionBegin;
1277:   PetscAssertPointer(flag, 2);
1278:   *flag = pc->reusepreconditioner;
1279:   PetscFunctionReturn(PETSC_SUCCESS);
1280: }

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

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

1288:   Input Parameter:
1289: . pc - the `PC` preconditioner context

1291:   Output Parameters:
1292: + Amat - the matrix defining the linear system
1293: - Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat.

1295:   Level: intermediate

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

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

1308: .vb
1309:          KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to
1310:            set size, type, etc of Amat

1312:          MatCreate(comm,&mat);
1313:          KSP/PCSetOperators(ksp/pc,Amat,Amat);
1314:          PetscObjectDereference((PetscObject)mat);
1315:            set size, type, etc of Amat
1316: .ve

1318:   and

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

1324:          MatCreate(comm,&Amat);
1325:          MatCreate(comm,&Pmat);
1326:          KSP/PCSetOperators(ksp/pc,Amat,Pmat);
1327:          PetscObjectDereference((PetscObject)Amat);
1328:          PetscObjectDereference((PetscObject)Pmat);
1329:            set size, type, etc of Amat and Pmat
1330: .ve

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

1341: .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperatorsSet()`
1342: @*/
1343: PetscErrorCode PCGetOperators(PC pc, Mat *Amat, Mat *Pmat)
1344: {
1345:   PetscFunctionBegin;
1347:   if (Amat) {
1348:     if (!pc->mat) {
1349:       if (pc->pmat && !Pmat) { /* Pmat has been set, but user did not request it, so use for Amat */
1350:         pc->mat = pc->pmat;
1351:         PetscCall(PetscObjectReference((PetscObject)pc->mat));
1352:       } else { /* both Amat and Pmat are empty */
1353:         PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->mat));
1354:         if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */
1355:           pc->pmat = pc->mat;
1356:           PetscCall(PetscObjectReference((PetscObject)pc->pmat));
1357:         }
1358:       }
1359:     }
1360:     *Amat = pc->mat;
1361:   }
1362:   if (Pmat) {
1363:     if (!pc->pmat) {
1364:       if (pc->mat && !Amat) { /* Amat has been set but was not requested, so use for pmat */
1365:         pc->pmat = pc->mat;
1366:         PetscCall(PetscObjectReference((PetscObject)pc->pmat));
1367:       } else {
1368:         PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->pmat));
1369:         if (!Amat) { /* user did NOT request Amat, so make same as Pmat */
1370:           pc->mat = pc->pmat;
1371:           PetscCall(PetscObjectReference((PetscObject)pc->mat));
1372:         }
1373:       }
1374:     }
1375:     *Pmat = pc->pmat;
1376:   }
1377:   PetscFunctionReturn(PETSC_SUCCESS);
1378: }

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

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

1386:   Input Parameter:
1387: . pc - the `PC` preconditioner context

1389:   Output Parameters:
1390: + mat  - the matrix associated with the linear system was set
1391: - pmat - matrix associated with the preconditioner was set, usually the same

1393:   Level: intermediate

1395: .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperators()`
1396: @*/
1397: PetscErrorCode PCGetOperatorsSet(PC pc, PetscBool *mat, PetscBool *pmat)
1398: {
1399:   PetscFunctionBegin;
1401:   if (mat) *mat = pc->mat ? PETSC_TRUE : PETSC_FALSE;
1402:   if (pmat) *pmat = pc->pmat ? PETSC_TRUE : PETSC_FALSE;
1403:   PetscFunctionReturn(PETSC_SUCCESS);
1404: }

1406: /*@
1407:   PCFactorGetMatrix - Gets the factored matrix from the
1408:   preconditioner context.  This routine is valid only for the `PCLU`,
1409:   `PCILU`, `PCCHOLESKY`, and `PCICC` methods.

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

1413:   Input Parameter:
1414: . pc - the `PC` preconditioner context

1416:   Output Parameters:
1417: . mat - the factored matrix

1419:   Level: advanced

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

1424: .seealso: [](ch_ksp), `PC`, `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
1425: @*/
1426: PetscErrorCode PCFactorGetMatrix(PC pc, Mat *mat)
1427: {
1428:   PetscFunctionBegin;
1430:   PetscAssertPointer(mat, 2);
1431:   PetscCall(PCFactorSetUpMatSolverType(pc));
1432:   PetscUseTypeMethod(pc, getfactoredmatrix, mat);
1433:   PetscFunctionReturn(PETSC_SUCCESS);
1434: }

1436: /*@
1437:   PCSetOptionsPrefix - Sets the prefix used for searching for all
1438:   `PC` options in the database.

1440:   Logically Collective

1442:   Input Parameters:
1443: + pc     - the `PC` preconditioner context
1444: - prefix - the prefix string to prepend to all `PC` option requests

1446:   Level: advanced

1448:   Note:
1449:   A hyphen (-) must NOT be given at the beginning of the prefix name.
1450:   The first character of all runtime options is AUTOMATICALLY the
1451:   hyphen.

1453: .seealso: [](ch_ksp), `PC`, `PCSetFromOptions()`, `PCAppendOptionsPrefix()`, `PCGetOptionsPrefix()`
1454: @*/
1455: PetscErrorCode PCSetOptionsPrefix(PC pc, const char prefix[])
1456: {
1457:   PetscFunctionBegin;
1459:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)pc, prefix));
1460:   PetscFunctionReturn(PETSC_SUCCESS);
1461: }

1463: /*@
1464:   PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1465:   `PC` options in the database.

1467:   Logically Collective

1469:   Input Parameters:
1470: + pc     - the `PC` preconditioner context
1471: - prefix - the prefix string to prepend to all `PC` option requests

1473:   Level: advanced

1475:   Note:
1476:   A hyphen (-) must NOT be given at the beginning of the prefix name.
1477:   The first character of all runtime options is AUTOMATICALLY the
1478:   hyphen.

1480: .seealso: [](ch_ksp), `PC`, `PCSetFromOptions()`, `PCSetOptionsPrefix()`, `PCGetOptionsPrefix()`
1481: @*/
1482: PetscErrorCode PCAppendOptionsPrefix(PC pc, const char prefix[])
1483: {
1484:   PetscFunctionBegin;
1486:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)pc, prefix));
1487:   PetscFunctionReturn(PETSC_SUCCESS);
1488: }

1490: /*@
1491:   PCGetOptionsPrefix - Gets the prefix used for searching for all
1492:   `PC` options in the database.

1494:   Not Collective

1496:   Input Parameter:
1497: . pc - the `PC` preconditioner context

1499:   Output Parameter:
1500: . prefix - pointer to the prefix string used, is returned

1502:   Level: advanced

1504: .seealso: [](ch_ksp), `PC`, `PCSetFromOptions()`, `PCSetOptionsPrefix()`, `PCAppendOptionsPrefix()`
1505: @*/
1506: PetscErrorCode PCGetOptionsPrefix(PC pc, const char *prefix[])
1507: {
1508:   PetscFunctionBegin;
1510:   PetscAssertPointer(prefix, 2);
1511:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc, prefix));
1512:   PetscFunctionReturn(PETSC_SUCCESS);
1513: }

1515: /*
1516:    Indicates the right-hand side will be changed by KSPSolve(), this occurs for a few
1517:   preconditioners including BDDC and Eisentat that transform the equations before applying
1518:   the Krylov methods
1519: */
1520: PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC pc, PetscBool *change)
1521: {
1522:   PetscFunctionBegin;
1524:   PetscAssertPointer(change, 2);
1525:   *change = PETSC_FALSE;
1526:   PetscTryMethod(pc, "PCPreSolveChangeRHS_C", (PC, PetscBool *), (pc, change));
1527:   PetscFunctionReturn(PETSC_SUCCESS);
1528: }

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

1534:   Collective

1536:   Input Parameters:
1537: + pc  - the `PC` preconditioner context
1538: - ksp - the Krylov subspace context

1540:   Level: developer

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

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

1549:   `KSPSetPostSolve()` provides an alternative way to provide such transformations.

1551: .seealso: [](ch_ksp), `PC`, `PCPostSolve()`, `KSP`, `PCSetPostSetUp()`, `KSPSetPreSolve()`, `KSPSetPostSolve()`
1552: @*/
1553: PetscErrorCode PCPreSolve(PC pc, KSP ksp)
1554: {
1555:   Vec x, rhs;

1557:   PetscFunctionBegin;
1560:   pc->presolvedone++;
1561:   PetscCheck(pc->presolvedone <= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot embed PCPreSolve() more than twice");
1562:   PetscCall(KSPGetSolution(ksp, &x));
1563:   PetscCall(KSPGetRhs(ksp, &rhs));
1564:   PetscTryTypeMethod(pc, presolve, ksp, rhs, x);
1565:   PetscFunctionReturn(PETSC_SUCCESS);
1566: }

1568: /*@
1569:   PCSetPostSetUp - Sets function called at the end of `PCSetUp()` to adjust the computed preconditioner

1571:   Logically Collective

1573:   Input Parameters:
1574: + pc        - the preconditioner object
1575: - postsetup - the function to call after `PCSetUp()`

1577:   Calling sequence of `postsetup`:
1578: . pc - the `PC` context

1580:   Level: developer

1582: .seealso: [](ch_ksp), `PC`, `PCSetUp()`
1583: @*/
1584: PetscErrorCode PCSetPostSetUp(PC pc, PetscErrorCode (*postsetup)(PC pc))
1585: {
1586:   PetscFunctionBegin;
1588:   pc->postsetup = postsetup;
1589:   PetscFunctionReturn(PETSC_SUCCESS);
1590: }

1592: /*@
1593:   PCPostSolve - Optional post-solve phase, intended for any
1594:   preconditioner-specific actions that must be performed after
1595:   the iterative solve itself.

1597:   Collective

1599:   Input Parameters:
1600: + pc  - the `PC` preconditioner context
1601: - ksp - the `KSP` Krylov subspace context

1603:   Example Usage:
1604: .vb
1605:     PCPreSolve(pc,ksp);
1606:     KSPSolve(ksp,b,x);
1607:     PCPostSolve(pc,ksp);
1608: .ve

1610:   Level: developer

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

1615: .seealso: [](ch_ksp), `PC`, `KSPSetPostSolve()`, `KSPSetPreSolve()`, `PCPreSolve()`, `KSPSolve()`
1616: @*/
1617: PetscErrorCode PCPostSolve(PC pc, KSP ksp)
1618: {
1619:   Vec x, rhs;

1621:   PetscFunctionBegin;
1624:   pc->presolvedone--;
1625:   PetscCall(KSPGetSolution(ksp, &x));
1626:   PetscCall(KSPGetRhs(ksp, &rhs));
1627:   PetscTryTypeMethod(pc, postsolve, ksp, rhs, x);
1628:   PetscFunctionReturn(PETSC_SUCCESS);
1629: }

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

1634:   Collective

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

1641:   Level: intermediate

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

1646: .seealso: [](ch_ksp), `PC`, `PetscViewerBinaryOpen()`, `PCView()`, `MatLoad()`, `VecLoad()`, `PETSCVIEWERBINARY`
1647: @*/
1648: PetscErrorCode PCLoad(PC newdm, PetscViewer viewer)
1649: {
1650:   PetscBool isbinary;
1651:   PetscInt  classid;
1652:   char      type[256];

1654:   PetscFunctionBegin;
1657:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1658:   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");

1660:   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
1661:   PetscCheck(classid == PC_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not PC next in file");
1662:   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
1663:   PetscCall(PCSetType(newdm, type));
1664:   PetscTryTypeMethod(newdm, load, viewer);
1665:   PetscFunctionReturn(PETSC_SUCCESS);
1666: }

1668: #include <petscdraw.h>
1669: #if PetscDefined(HAVE_SAWS)
1670: #include <petscviewersaws.h>
1671: #endif

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

1676:   Collective

1678:   Input Parameters:
1679: + A    - the `PC` context
1680: . obj  - optional object that provides the options prefix, pass `NULL` to use the options prefix of `A`
1681: - name - command line option name

1683:   Options Database Key:
1684: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`

1686:   Level: developer

1688:   Note:
1689:   This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
1690:   rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.

1692: .seealso: [](ch_ksp), `PC`, `PCView()`, `PetscObjectViewFromOptions()`, `PCCreate()`, `PetscOptionsCreateViewer()`
1693: @*/
1694: PetscErrorCode PCViewFromOptions(PC A, PetscObject obj, const char name[])
1695: {
1696:   PetscFunctionBegin;
1698:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1699:   PetscFunctionReturn(PETSC_SUCCESS);
1700: }

1702: /*@
1703:   PCView - Prints information about the `PC`

1705:   Collective

1707:   Input Parameters:
1708: + pc     - the `PC` preconditioner context
1709: - viewer - optional `PetscViewer` visualization context

1711:   Level: intermediate

1713:   Notes:
1714:   The available visualization contexts include
1715: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
1716: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
1717:   output where only the first processor opens
1718:   the file. All other processors send their
1719:   data to the first processor to print.

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

1724: .seealso: [](ch_ksp), `PC`, `PetscViewer`, `PetscViewerType`, `KSPView()`, `PetscViewerASCIIOpen()`
1725: @*/
1726: PetscErrorCode PCView(PC pc, PetscViewer viewer)
1727: {
1728:   PCType            cstr;
1729:   PetscViewerFormat format;
1730:   PetscBool         isascii, isstring, isbinary, isdraw, pop = PETSC_FALSE;
1731: #if PetscDefined(HAVE_SAWS)
1732:   PetscBool issaws;
1733: #endif

1735:   PetscFunctionBegin;
1737:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer));
1739:   PetscCheckSameComm(pc, 1, viewer, 2);

1741:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1742:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1743:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1744:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
1745: #if PetscDefined(HAVE_SAWS)
1746:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1747: #endif

1749:   if (isascii) {
1750:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pc, viewer));
1751:     if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  PC has not been set up so information may be incomplete\n"));
1752:     PetscCall(PetscViewerASCIIPushTab(viewer));
1753:     PetscTryTypeMethod(pc, view, viewer);
1754:     PetscCall(PetscViewerASCIIPopTab(viewer));
1755:     if (pc->mat) {
1756:       PetscCall(PetscViewerGetFormat(viewer, &format));
1757:       if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) {
1758:         PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO));
1759:         pop = PETSC_TRUE;
1760:       }
1761:       if (pc->pmat == pc->mat) {
1762:         PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix, which is also used to construct the preconditioner:\n"));
1763:         PetscCall(PetscViewerASCIIPushTab(viewer));
1764:         PetscCall(MatView(pc->mat, viewer));
1765:         PetscCall(PetscViewerASCIIPopTab(viewer));
1766:       } else {
1767:         if (pc->pmat) {
1768:           PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix, followed by the matrix used to construct the preconditioner:\n"));
1769:         } else {
1770:           PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix:\n"));
1771:         }
1772:         PetscCall(PetscViewerASCIIPushTab(viewer));
1773:         PetscCall(MatView(pc->mat, viewer));
1774:         if (pc->pmat) PetscCall(MatView(pc->pmat, viewer));
1775:         PetscCall(PetscViewerASCIIPopTab(viewer));
1776:       }
1777:       if (pop) PetscCall(PetscViewerPopFormat(viewer));
1778:     }
1779:   } else if (isstring) {
1780:     PetscCall(PCGetType(pc, &cstr));
1781:     PetscCall(PetscViewerStringSPrintf(viewer, " PCType: %-7.7s", cstr));
1782:     PetscTryTypeMethod(pc, view, viewer);
1783:     if (pc->mat) PetscCall(MatView(pc->mat, viewer));
1784:     if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer));
1785:   } else if (isbinary) {
1786:     PetscInt    classid = PC_FILE_CLASSID;
1787:     MPI_Comm    comm;
1788:     PetscMPIInt rank;
1789:     char        type[256];

1791:     PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
1792:     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1793:     if (rank == 0) {
1794:       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
1795:       PetscCall(PetscStrncpy(type, ((PetscObject)pc)->type_name, 256));
1796:       PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
1797:     }
1798:     PetscTryTypeMethod(pc, view, viewer);
1799:   } else if (isdraw) {
1800:     PetscDraw draw;
1801:     char      str[25];
1802:     PetscReal x, y, bottom, h;
1803:     PetscInt  n;

1805:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1806:     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
1807:     if (pc->mat) {
1808:       PetscCall(MatGetSize(pc->mat, &n, NULL));
1809:       PetscCall(PetscSNPrintf(str, 25, "PC: %s (%" PetscInt_FMT ")", ((PetscObject)pc)->type_name, n));
1810:     } else {
1811:       PetscCall(PetscSNPrintf(str, 25, "PC: %s", ((PetscObject)pc)->type_name));
1812:     }
1813:     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_RED, PETSC_DRAW_BLACK, str, NULL, &h));
1814:     bottom = y - h;
1815:     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
1816:     PetscTryTypeMethod(pc, view, viewer);
1817:     PetscCall(PetscDrawPopCurrentPoint(draw));
1818: #if PetscDefined(HAVE_SAWS)
1819:   } else if (issaws) {
1820:     PetscMPIInt rank;

1822:     PetscCall(PetscObjectName((PetscObject)pc));
1823:     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1824:     if (!((PetscObject)pc)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)pc, viewer));
1825:     if (pc->mat) PetscCall(MatView(pc->mat, viewer));
1826:     if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer));
1827: #endif
1828:   }
1829:   PetscFunctionReturn(PETSC_SUCCESS);
1830: }

1832: /*@
1833:   PCRegister -  Adds a method (`PCType`) to the PETSc preconditioner package.

1835:   Not collective. No Fortran Support

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

1841:   Example Usage:
1842: .vb
1843:    PCRegister("my_solver", MySolverCreate);
1844: .ve

1846:   Then, your solver can be chosen with the procedural interface via
1847: .vb
1848:   PCSetType(pc, "my_solver")
1849: .ve
1850:   or at runtime via the option
1851: .vb
1852:   -pc_type my_solver
1853: .ve

1855:   Level: advanced

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

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

1863: .seealso: [](ch_ksp), `PC`, `PCType`, `PCRegisterAll()`, `PCSetType()`, `PCShellSetContext()`, `PCShellSetApply()`, `PCSHELL`
1864: @*/
1865: PetscErrorCode PCRegister(const char sname[], PetscErrorCode (*function)(PC))
1866: {
1867:   PetscFunctionBegin;
1868:   PetscCall(PCInitializePackage());
1869:   PetscCall(PetscFunctionListAdd(&PCList, sname, function));
1870:   PetscFunctionReturn(PETSC_SUCCESS);
1871: }

1873: static PetscErrorCode MatMult_PC(Mat A, Vec X, Vec Y)
1874: {
1875:   PC pc;

1877:   PetscFunctionBegin;
1878:   PetscCall(MatShellGetContext(A, &pc));
1879:   PetscCall(PCApply(pc, X, Y));
1880:   PetscFunctionReturn(PETSC_SUCCESS);
1881: }

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

1886:   Collective

1888:   Input Parameters:
1889: + pc      - the `PC` preconditioner object
1890: - mattype - the `MatType` to be used for the operator

1892:   Output Parameter:
1893: . mat - the explicit preconditioned operator

1895:   Level: advanced

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

1902:   Developer Note:
1903:   This should be called `PCCreateExplicitOperator()`

1905: .seealso: [](ch_ksp), `PC`, `KSPComputeOperator()`, `MatType`
1906: @*/
1907: PetscErrorCode PCComputeOperator(PC pc, MatType mattype, Mat *mat)
1908: {
1909:   PetscInt N, M, m, n;
1910:   Mat      A, Apc;

1912:   PetscFunctionBegin;
1914:   PetscAssertPointer(mat, 3);
1915:   PetscCall(PCGetOperators(pc, &A, NULL));
1916:   PetscCall(MatGetLocalSize(A, &m, &n));
1917:   PetscCall(MatGetSize(A, &M, &N));
1918:   PetscCall(MatCreateShell(PetscObjectComm((PetscObject)pc), m, n, M, N, pc, &Apc));
1919:   PetscCall(MatShellSetOperation(Apc, MATOP_MULT, (PetscErrorCodeFn *)MatMult_PC));
1920:   PetscCall(MatComputeOperator(Apc, mattype, mat));
1921:   PetscCall(MatDestroy(&Apc));
1922:   PetscFunctionReturn(PETSC_SUCCESS);
1923: }

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

1928:   Collective

1930:   Input Parameters:
1931: + pc     - the `PC` preconditioner context
1932: . dim    - the dimension of the coordinates 1, 2, or 3
1933: . nloc   - the blocked size of the coordinates array
1934: - coords - the coordinates array

1936:   Level: intermediate

1938:   Notes:
1939:   `coords` is an array of the dim coordinates for the nodes on
1940:   the local processor, of size `dim`*`nloc`.
1941:   If there are 108 equations (dofs) on a processor
1942:   for a 3d displacement finite element discretization of elasticity (so
1943:   that there are nloc = 36 = 108/3 nodes) then the array must have 108
1944:   double precision values (ie, 3 * 36).  These x y z coordinates
1945:   should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x,
1946:   ... , N-1.z ].

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

1951: .seealso: [](ch_ksp), `PC`, `MatSetNearNullSpace()`
1952: @*/
1953: PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal coords[])
1954: {
1955:   PetscFunctionBegin;
1958:   PetscTryMethod(pc, "PCSetCoordinates_C", (PC, PetscInt, PetscInt, PetscReal[]), (pc, dim, nloc, coords));
1959:   PetscFunctionReturn(PETSC_SUCCESS);
1960: }

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

1965:   Logically Collective

1967:   Input Parameter:
1968: . pc - the precondition context

1970:   Output Parameters:
1971: + num_levels     - the number of levels
1972: - interpolations - the interpolation matrices (size of `num_levels`-1)

1974:   Level: advanced

1976:   Developer Note:
1977:   Why is this here instead of in `PCMG` etc?

1979: .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetInterpolation()`, `PCGetCoarseOperators()`
1980: @*/
1981: PetscErrorCode PCGetInterpolations(PC pc, PetscInt *num_levels, Mat *interpolations[])
1982: {
1983:   PetscFunctionBegin;
1985:   PetscAssertPointer(num_levels, 2);
1986:   PetscAssertPointer(interpolations, 3);
1987:   PetscUseMethod(pc, "PCGetInterpolations_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, interpolations));
1988:   PetscFunctionReturn(PETSC_SUCCESS);
1989: }

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

1994:   Logically Collective

1996:   Input Parameter:
1997: . pc - the precondition context

1999:   Output Parameters:
2000: + num_levels      - the number of levels
2001: - coarseOperators - the coarse operator matrices (size of `num_levels`-1)

2003:   Level: advanced

2005:   Developer Note:
2006:   Why is this here instead of in `PCMG` etc?

2008: .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
2009: @*/
2010: PetscErrorCode PCGetCoarseOperators(PC pc, PetscInt *num_levels, Mat *coarseOperators[])
2011: {
2012:   PetscFunctionBegin;
2014:   PetscAssertPointer(num_levels, 2);
2015:   PetscAssertPointer(coarseOperators, 3);
2016:   PetscUseMethod(pc, "PCGetCoarseOperators_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, coarseOperators));
2017:   PetscFunctionReturn(PETSC_SUCCESS);
2018: }