xref: /petsc/src/ksp/pc/interface/precon.c (revision 7371636706d0e957dcf5cdcbd64be01474eb50f1)
14b9ad928SBarry Smith /*
24b9ad928SBarry Smith     The PC (preconditioner) interface routines, callable by users.
34b9ad928SBarry Smith */
4af0996ceSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscksp.h" I*/
51e25c274SJed Brown #include <petscdm.h>
64b9ad928SBarry Smith 
74b9ad928SBarry Smith /* Logging support */
80700a824SBarry Smith PetscClassId  PC_CLASSID;
9c677e75fSPierre Jolivet PetscLogEvent PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_MatApply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft;
10011ea8aeSBarry Smith PetscLogEvent PC_ApplySymmetricRight, PC_ModifySubMatrices, PC_ApplyOnBlocks, PC_ApplyTransposeOnBlocks;
11ab83eea4SMatthew G. Knepley PetscInt      PetscMGLevelId;
120316ec64SBarry Smith PetscLogStage PCMPIStage;
134b9ad928SBarry Smith 
14b4f8a55aSStefano Zampini PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC pc, const char *type[])
15d71ae5a4SJacob Faibussowitsch {
162e70eadcSBarry Smith   PetscMPIInt size;
17b4f8a55aSStefano Zampini   PetscBool   hasopblock, hasopsolve, flg1, flg2, set, flg3, isnormal;
18566e8bf2SBarry Smith 
19566e8bf2SBarry Smith   PetscFunctionBegin;
209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
21566e8bf2SBarry Smith   if (pc->pmat) {
22b4f8a55aSStefano Zampini     PetscCall(MatHasOperation(pc->pmat, MATOP_GET_DIAGONAL_BLOCK, &hasopblock));
23b4f8a55aSStefano Zampini     PetscCall(MatHasOperation(pc->pmat, MATOP_SOLVE, &hasopsolve));
24566e8bf2SBarry Smith     if (size == 1) {
259566063dSJacob Faibussowitsch       PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ICC, &flg1));
269566063dSJacob Faibussowitsch       PetscCall(MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ILU, &flg2));
279566063dSJacob Faibussowitsch       PetscCall(MatIsSymmetricKnown(pc->pmat, &set, &flg3));
28da74c943SJose E. Roman       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &isnormal, MATNORMAL, MATNORMALHERMITIAN, NULL));
29ba8a7149SBarry Smith       if (flg1 && (!flg2 || (set && flg3))) {
30566e8bf2SBarry Smith         *type = PCICC;
31566e8bf2SBarry Smith       } else if (flg2) {
32566e8bf2SBarry Smith         *type = PCILU;
33da74c943SJose E. Roman       } else if (isnormal) {
34da74c943SJose E. Roman         *type = PCNONE;
35b4f8a55aSStefano Zampini       } else if (hasopblock) { /* likely is a parallel matrix run on one processor */
36566e8bf2SBarry Smith         *type = PCBJACOBI;
37b4f8a55aSStefano Zampini       } else if (hasopsolve) {
38b4f8a55aSStefano Zampini         *type = PCMAT;
39566e8bf2SBarry Smith       } else {
40566e8bf2SBarry Smith         *type = PCNONE;
41566e8bf2SBarry Smith       }
42566e8bf2SBarry Smith     } else {
43b4f8a55aSStefano Zampini       if (hasopblock) {
44566e8bf2SBarry Smith         *type = PCBJACOBI;
45b4f8a55aSStefano Zampini       } else if (hasopsolve) {
46b4f8a55aSStefano Zampini         *type = PCMAT;
47566e8bf2SBarry Smith       } else {
48566e8bf2SBarry Smith         *type = PCNONE;
49566e8bf2SBarry Smith       }
50566e8bf2SBarry Smith     }
51b4f8a55aSStefano Zampini   } else *type = NULL;
523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53566e8bf2SBarry Smith }
544b9ad928SBarry Smith 
55fe57bb1aSStefano Zampini /* do not log solves, setup and applications of preconditioners while constructing preconditioners; perhaps they should be logged separately from the regular solves */
56fe57bb1aSStefano Zampini PETSC_EXTERN PetscLogEvent KSP_Solve, KSP_SetUp;
57fe57bb1aSStefano Zampini 
58fe57bb1aSStefano Zampini static PetscErrorCode PCLogEventsDeactivatePush(void)
59fe57bb1aSStefano Zampini {
60fe57bb1aSStefano Zampini   PetscFunctionBegin;
61fe57bb1aSStefano Zampini   PetscCall(KSPInitializePackage());
62fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePush(KSP_Solve));
63fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePush(KSP_SetUp));
64fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePush(PC_Apply));
65fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePush(PC_SetUp));
66fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePush(PC_SetUpOnBlocks));
67fe57bb1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
68fe57bb1aSStefano Zampini }
69fe57bb1aSStefano Zampini 
70fe57bb1aSStefano Zampini static PetscErrorCode PCLogEventsDeactivatePop(void)
71fe57bb1aSStefano Zampini {
72fe57bb1aSStefano Zampini   PetscFunctionBegin;
73fe57bb1aSStefano Zampini   PetscCall(KSPInitializePackage());
74fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePop(KSP_Solve));
75fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePop(KSP_SetUp));
76fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePop(PC_Apply));
77fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePop(PC_SetUp));
78fe57bb1aSStefano Zampini   PetscCall(PetscLogEventDeactivatePop(PC_SetUpOnBlocks));
79fe57bb1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
80fe57bb1aSStefano Zampini }
81fe57bb1aSStefano Zampini 
8288584be7SBarry Smith /*@
83562efe2eSBarry Smith   PCReset - Resets a `PC` context to the pcsetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
8488584be7SBarry Smith 
85c3339decSBarry Smith   Collective
8688584be7SBarry Smith 
8788584be7SBarry Smith   Input Parameter:
8888584be7SBarry Smith . pc - the preconditioner context
8988584be7SBarry Smith 
9088584be7SBarry Smith   Level: developer
9188584be7SBarry Smith 
92f1580f4eSBarry Smith   Note:
93562efe2eSBarry Smith   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`
9488584be7SBarry Smith 
95562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`
9688584be7SBarry Smith @*/
97d71ae5a4SJacob Faibussowitsch PetscErrorCode PCReset(PC pc)
98d71ae5a4SJacob Faibussowitsch {
9988584be7SBarry Smith   PetscFunctionBegin;
10088584be7SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
101dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, reset);
1029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pc->diagonalscaleright));
1039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pc->diagonalscaleleft));
1049566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pc->pmat));
1059566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pc->mat));
1062fa5cd67SKarl Rupp 
1070ce6c5a2SBarry Smith   pc->setupcalled = 0;
1083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10988584be7SBarry Smith }
11088584be7SBarry Smith 
1110764c050SBarry Smith /*@
112f1580f4eSBarry Smith   PCDestroy - Destroys `PC` context that was created with `PCCreate()`.
1134b9ad928SBarry Smith 
114c3339decSBarry Smith   Collective
1154b9ad928SBarry Smith 
1164b9ad928SBarry Smith   Input Parameter:
1174b9ad928SBarry Smith . pc - the preconditioner context
1184b9ad928SBarry Smith 
1194b9ad928SBarry Smith   Level: developer
1204b9ad928SBarry Smith 
121562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`
1224b9ad928SBarry Smith @*/
123d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy(PC *pc)
124d71ae5a4SJacob Faibussowitsch {
1254b9ad928SBarry Smith   PetscFunctionBegin;
1263ba16761SJacob Faibussowitsch   if (!*pc) PetscFunctionReturn(PETSC_SUCCESS);
127f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*pc, PC_CLASSID, 1);
128f4f49eeaSPierre Jolivet   if (--((PetscObject)*pc)->refct > 0) {
1299371c9d4SSatish Balay     *pc = NULL;
1303ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1319371c9d4SSatish Balay   }
1324b9ad928SBarry Smith 
1339566063dSJacob Faibussowitsch   PetscCall(PCReset(*pc));
134241cb3abSLisandro Dalcin 
135e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
1369566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*pc));
137f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*pc, destroy);
1389566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*pc)->dm));
1399566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(pc));
1403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1414b9ad928SBarry Smith }
1424b9ad928SBarry Smith 
143cc4c1da9SBarry Smith /*@
144c5eb9154SBarry Smith   PCGetDiagonalScale - Indicates if the preconditioner applies an additional left and right
1454b9ad928SBarry Smith   scaling as needed by certain time-stepping codes.
1464b9ad928SBarry Smith 
147c3339decSBarry Smith   Logically Collective
1484b9ad928SBarry Smith 
1494b9ad928SBarry Smith   Input Parameter:
1504b9ad928SBarry Smith . pc - the preconditioner context
1514b9ad928SBarry Smith 
1524b9ad928SBarry Smith   Output Parameter:
153f1580f4eSBarry Smith . flag - `PETSC_TRUE` if it applies the scaling
1544b9ad928SBarry Smith 
1554b9ad928SBarry Smith   Level: developer
1564b9ad928SBarry Smith 
157f1580f4eSBarry Smith   Note:
158562efe2eSBarry Smith   If this returns `PETSC_TRUE` then the system solved via the Krylov method is, for left and right preconditioning,
1594b9ad928SBarry Smith 
160562efe2eSBarry Smith   $$
161562efe2eSBarry Smith   \begin{align*}
162562efe2eSBarry Smith   D M A D^{-1} y = D M b  \\
163562efe2eSBarry Smith   D A M D^{-1} z = D b.
164562efe2eSBarry Smith   \end{align*}
165562efe2eSBarry Smith   $$
166562efe2eSBarry Smith 
167562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCSetDiagonalScale()`
1684b9ad928SBarry Smith @*/
169d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetDiagonalScale(PC pc, PetscBool *flag)
170d71ae5a4SJacob Faibussowitsch {
1714b9ad928SBarry Smith   PetscFunctionBegin;
1720700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1734f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
1744b9ad928SBarry Smith   *flag = pc->diagonalscale;
1753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1764b9ad928SBarry Smith }
1774b9ad928SBarry Smith 
1784b9ad928SBarry Smith /*@
179c5eb9154SBarry Smith   PCSetDiagonalScale - Indicates the left scaling to use to apply an additional left and right
1804b9ad928SBarry Smith   scaling as needed by certain time-stepping codes.
1814b9ad928SBarry Smith 
182c3339decSBarry Smith   Logically Collective
1834b9ad928SBarry Smith 
1844b9ad928SBarry Smith   Input Parameters:
1854b9ad928SBarry Smith + pc - the preconditioner context
1864b9ad928SBarry Smith - s  - scaling vector
1874b9ad928SBarry Smith 
1884b9ad928SBarry Smith   Level: intermediate
1894b9ad928SBarry Smith 
19095452b02SPatrick Sanan   Notes:
191562efe2eSBarry Smith   The system solved via the Krylov method is, for left and right preconditioning,
192562efe2eSBarry Smith   $$
193562efe2eSBarry Smith   \begin{align*}
194562efe2eSBarry Smith   D M A D^{-1} y = D M b \\
195562efe2eSBarry Smith   D A M D^{-1} z = D b.
196562efe2eSBarry Smith   \end{align*}
197562efe2eSBarry Smith   $$
1984b9ad928SBarry Smith 
199562efe2eSBarry Smith   `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$.
2004b9ad928SBarry Smith 
201562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCGetDiagonalScale()`
2024b9ad928SBarry Smith @*/
203d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetDiagonalScale(PC pc, Vec s)
204d71ae5a4SJacob Faibussowitsch {
2054b9ad928SBarry Smith   PetscFunctionBegin;
2060700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2070700a824SBarry Smith   PetscValidHeaderSpecific(s, VEC_CLASSID, 2);
2084b9ad928SBarry Smith   pc->diagonalscale = PETSC_TRUE;
2092fa5cd67SKarl Rupp 
2109566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)s));
2119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pc->diagonalscaleleft));
2122fa5cd67SKarl Rupp 
2134b9ad928SBarry Smith   pc->diagonalscaleleft = s;
2142fa5cd67SKarl Rupp 
2159566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(s, &pc->diagonalscaleright));
2169566063dSJacob Faibussowitsch   PetscCall(VecCopy(s, pc->diagonalscaleright));
2179566063dSJacob Faibussowitsch   PetscCall(VecReciprocal(pc->diagonalscaleright));
2183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2194b9ad928SBarry Smith }
2204b9ad928SBarry Smith 
221bc08b0f1SBarry Smith /*@
222c5eb9154SBarry Smith   PCDiagonalScaleLeft - Scales a vector by the left scaling as needed by certain time-stepping codes.
2234b9ad928SBarry Smith 
224c3339decSBarry Smith   Logically Collective
2254b9ad928SBarry Smith 
2264b9ad928SBarry Smith   Input Parameters:
2274b9ad928SBarry Smith + pc  - the preconditioner context
2284b9ad928SBarry Smith . in  - input vector
229a2b725a8SWilliam Gropp - out - scaled vector (maybe the same as in)
2304b9ad928SBarry Smith 
2314b9ad928SBarry Smith   Level: intermediate
2324b9ad928SBarry Smith 
23395452b02SPatrick Sanan   Notes:
234562efe2eSBarry Smith   The system solved via the Krylov method is, for left and right preconditioning,
2354b9ad928SBarry Smith 
236562efe2eSBarry Smith   $$
237562efe2eSBarry Smith   \begin{align*}
238562efe2eSBarry Smith   D M A D^{-1} y = D M b  \\
239562efe2eSBarry Smith   D A M D^{-1} z = D b.
240562efe2eSBarry Smith   \end{align*}
241562efe2eSBarry Smith   $$
2424b9ad928SBarry Smith 
243562efe2eSBarry Smith   `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$.
2444b9ad928SBarry Smith 
245562efe2eSBarry Smith   If diagonal scaling is turned off and `in` is not `out` then `in` is copied to `out`
246562efe2eSBarry Smith 
2470241b274SPierre Jolivet .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCSetDiagonalScale()`, `PCDiagonalScaleRight()`, `MatDiagonalScale()`
2484b9ad928SBarry Smith @*/
249d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDiagonalScaleLeft(PC pc, Vec in, Vec out)
250d71ae5a4SJacob Faibussowitsch {
2514b9ad928SBarry Smith   PetscFunctionBegin;
2520700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2530700a824SBarry Smith   PetscValidHeaderSpecific(in, VEC_CLASSID, 2);
2540700a824SBarry Smith   PetscValidHeaderSpecific(out, VEC_CLASSID, 3);
2554b9ad928SBarry Smith   if (pc->diagonalscale) {
2569566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(out, pc->diagonalscaleleft, in));
2574b9ad928SBarry Smith   } else if (in != out) {
2589566063dSJacob Faibussowitsch     PetscCall(VecCopy(in, out));
2594b9ad928SBarry Smith   }
2603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2614b9ad928SBarry Smith }
2624b9ad928SBarry Smith 
263bc08b0f1SBarry Smith /*@
2644b9ad928SBarry Smith   PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.
2654b9ad928SBarry Smith 
266c3339decSBarry Smith   Logically Collective
2674b9ad928SBarry Smith 
2684b9ad928SBarry Smith   Input Parameters:
2694b9ad928SBarry Smith + pc  - the preconditioner context
2704b9ad928SBarry Smith . in  - input vector
271a2b725a8SWilliam Gropp - out - scaled vector (maybe the same as in)
2724b9ad928SBarry Smith 
2734b9ad928SBarry Smith   Level: intermediate
2744b9ad928SBarry Smith 
27595452b02SPatrick Sanan   Notes:
276562efe2eSBarry Smith   The system solved via the Krylov method is, for left and right preconditioning,
2774b9ad928SBarry Smith 
278562efe2eSBarry Smith   $$
279562efe2eSBarry Smith   \begin{align*}
280562efe2eSBarry Smith   D M A D^{-1} y = D M b  \\
281562efe2eSBarry Smith   D A M D^{-1} z = D b.
282a3524536SPierre Jolivet   \end{align*}
283562efe2eSBarry Smith   $$
2844b9ad928SBarry Smith 
285562efe2eSBarry Smith   `PCDiagonalScaleLeft()` scales a vector by $D$. `PCDiagonalScaleRight()` scales a vector by $D^{-1}$.
2864b9ad928SBarry Smith 
287562efe2eSBarry Smith   If diagonal scaling is turned off and `in` is not `out` then `in` is copied to `out`
288562efe2eSBarry Smith 
2890241b274SPierre Jolivet .seealso: [](ch_ksp), `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCSetDiagonalScale()`, `MatDiagonalScale()`
2904b9ad928SBarry Smith @*/
291d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDiagonalScaleRight(PC pc, Vec in, Vec out)
292d71ae5a4SJacob Faibussowitsch {
2934b9ad928SBarry Smith   PetscFunctionBegin;
2940700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2950700a824SBarry Smith   PetscValidHeaderSpecific(in, VEC_CLASSID, 2);
2960700a824SBarry Smith   PetscValidHeaderSpecific(out, VEC_CLASSID, 3);
2974b9ad928SBarry Smith   if (pc->diagonalscale) {
2989566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(out, pc->diagonalscaleright, in));
2994b9ad928SBarry Smith   } else if (in != out) {
3009566063dSJacob Faibussowitsch     PetscCall(VecCopy(in, out));
3014b9ad928SBarry Smith   }
3023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3034b9ad928SBarry Smith }
3044b9ad928SBarry Smith 
30549517cdeSBarry Smith /*@
30649517cdeSBarry Smith   PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the
307f1580f4eSBarry Smith   operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`,
308f1580f4eSBarry Smith   `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat.
30949517cdeSBarry Smith 
310c3339decSBarry Smith   Logically Collective
31149517cdeSBarry Smith 
31249517cdeSBarry Smith   Input Parameters:
31349517cdeSBarry Smith + pc  - the preconditioner context
314f1580f4eSBarry Smith - flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false)
31549517cdeSBarry Smith 
31649517cdeSBarry Smith   Options Database Key:
317562efe2eSBarry Smith . -pc_use_amat <true,false> - use the amat argument to `KSPSetOperators()` or `PCSetOperators()` to apply the operator
31849517cdeSBarry Smith 
31920f4b53cSBarry Smith   Level: intermediate
32020f4b53cSBarry Smith 
321f1580f4eSBarry Smith   Note:
32249517cdeSBarry Smith   For the common case in which the linear system matrix and the matrix used to construct the
323562efe2eSBarry Smith   preconditioner are identical, this routine has no affect.
32449517cdeSBarry Smith 
3250241b274SPierre Jolivet .seealso: [](ch_ksp), `PC`, `PCGetUseAmat()`, `PCBJACOBI`, `PCMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`,
326562efe2eSBarry Smith           `KSPSetOperators()`, `PCSetOperators()`
32749517cdeSBarry Smith @*/
328d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUseAmat(PC pc, PetscBool flg)
329d71ae5a4SJacob Faibussowitsch {
33049517cdeSBarry Smith   PetscFunctionBegin;
33149517cdeSBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
33249517cdeSBarry Smith   pc->useAmat = flg;
3333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33449517cdeSBarry Smith }
33549517cdeSBarry Smith 
336422a814eSBarry Smith /*@
337562efe2eSBarry Smith   PCSetErrorIfFailure - Causes `PC` to generate an error if a floating point exception, for example a zero pivot, is detected.
338422a814eSBarry Smith 
339c3339decSBarry Smith   Logically Collective
340422a814eSBarry Smith 
341422a814eSBarry Smith   Input Parameters:
342562efe2eSBarry Smith + pc  - iterative context obtained from `PCCreate()`
343f1580f4eSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated
344422a814eSBarry Smith 
345422a814eSBarry Smith   Level: advanced
346422a814eSBarry Smith 
347422a814eSBarry Smith   Notes:
348f1580f4eSBarry Smith   Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call `KSPGetConvergedReason()` after a `KSPSolve()`
349422a814eSBarry Smith   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
350422a814eSBarry Smith   detected.
351422a814eSBarry Smith 
352562efe2eSBarry Smith   This is propagated into `KSP`s used by this `PC`, which then propagate it into `PC`s used by those `KSP`s
353422a814eSBarry Smith 
354562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `KSPSetErrorIfNotConverged()`, `PCGetInitialGuessNonzero()`, `PCSetInitialGuessKnoll()`, `PCGetInitialGuessKnoll()`
355422a814eSBarry Smith @*/
356d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetErrorIfFailure(PC pc, PetscBool flg)
357d71ae5a4SJacob Faibussowitsch {
358422a814eSBarry Smith   PetscFunctionBegin;
359422a814eSBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
360422a814eSBarry Smith   PetscValidLogicalCollectiveBool(pc, flg, 2);
361422a814eSBarry Smith   pc->erroriffailure = flg;
3623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
363422a814eSBarry Smith }
364422a814eSBarry Smith 
36549517cdeSBarry Smith /*@
36649517cdeSBarry Smith   PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the
367f1580f4eSBarry Smith   operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`,
368f1580f4eSBarry Smith   `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat.
36949517cdeSBarry Smith 
370c3339decSBarry Smith   Logically Collective
37149517cdeSBarry Smith 
37249517cdeSBarry Smith   Input Parameter:
37349517cdeSBarry Smith . pc - the preconditioner context
37449517cdeSBarry Smith 
37549517cdeSBarry Smith   Output Parameter:
376f1580f4eSBarry Smith . flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false)
37749517cdeSBarry Smith 
37820f4b53cSBarry Smith   Level: intermediate
37920f4b53cSBarry Smith 
380f1580f4eSBarry Smith   Note:
38149517cdeSBarry Smith   For the common case in which the linear system matrix and the matrix used to construct the
38249517cdeSBarry Smith   preconditioner are identical, this routine is does nothing.
38349517cdeSBarry Smith 
3840241b274SPierre Jolivet .seealso: [](ch_ksp), `PC`, `PCSetUseAmat()`, `PCBJACOBI`, `PCMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`
38549517cdeSBarry Smith @*/
386d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetUseAmat(PC pc, PetscBool *flg)
387d71ae5a4SJacob Faibussowitsch {
38849517cdeSBarry Smith   PetscFunctionBegin;
38949517cdeSBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
39049517cdeSBarry Smith   *flg = pc->useAmat;
3913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39249517cdeSBarry Smith }
39349517cdeSBarry Smith 
394f39d8e23SSatish Balay /*@
3953821be0aSBarry Smith   PCSetKSPNestLevel - sets the amount of nesting the `KSP` that contains this `PC` has
3963821be0aSBarry Smith 
3973821be0aSBarry Smith   Collective
3983821be0aSBarry Smith 
3993821be0aSBarry Smith   Input Parameters:
4003821be0aSBarry Smith + pc    - the `PC`
4013821be0aSBarry Smith - level - the nest level
4023821be0aSBarry Smith 
4033821be0aSBarry Smith   Level: developer
4043821be0aSBarry Smith 
4053821be0aSBarry Smith .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPGetNestLevel()`, `PCGetKSPNestLevel()`, `KSPSetNestLevel()`
4063821be0aSBarry Smith @*/
4073821be0aSBarry Smith PetscErrorCode PCSetKSPNestLevel(PC pc, PetscInt level)
4083821be0aSBarry Smith {
4093821be0aSBarry Smith   PetscFunctionBegin;
4107a99bfcaSBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
4117a99bfcaSBarry Smith   PetscValidLogicalCollectiveInt(pc, level, 2);
4123821be0aSBarry Smith   pc->kspnestlevel = level;
4133821be0aSBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
4143821be0aSBarry Smith }
4153821be0aSBarry Smith 
4163821be0aSBarry Smith /*@
4173821be0aSBarry Smith   PCGetKSPNestLevel - gets the amount of nesting the `KSP` that contains this `PC` has
4183821be0aSBarry Smith 
4197a99bfcaSBarry Smith   Not Collective
4203821be0aSBarry Smith 
4213821be0aSBarry Smith   Input Parameter:
4223821be0aSBarry Smith . pc - the `PC`
4233821be0aSBarry Smith 
4243821be0aSBarry Smith   Output Parameter:
4253821be0aSBarry Smith . level - the nest level
4263821be0aSBarry Smith 
4273821be0aSBarry Smith   Level: developer
4283821be0aSBarry Smith 
4293821be0aSBarry Smith .seealso: [](ch_ksp), `KSPSetUp()`, `KSPSolve()`, `KSPDestroy()`, `KSP`, `KSPGMRES`, `KSPType`, `KSPSetNestLevel()`, `PCSetKSPNestLevel()`, `KSPGetNestLevel()`
4303821be0aSBarry Smith @*/
4313821be0aSBarry Smith PetscErrorCode PCGetKSPNestLevel(PC pc, PetscInt *level)
4323821be0aSBarry Smith {
4333821be0aSBarry Smith   PetscFunctionBegin;
4347a99bfcaSBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
4357a99bfcaSBarry Smith   PetscAssertPointer(level, 2);
4363821be0aSBarry Smith   *level = pc->kspnestlevel;
4373821be0aSBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
4383821be0aSBarry Smith }
4393821be0aSBarry Smith 
4403821be0aSBarry Smith /*@
441f1580f4eSBarry Smith   PCCreate - Creates a preconditioner context, `PC`
4424b9ad928SBarry Smith 
443d083f849SBarry Smith   Collective
4444b9ad928SBarry Smith 
4454b9ad928SBarry Smith   Input Parameter:
4464b9ad928SBarry Smith . comm - MPI communicator
4474b9ad928SBarry Smith 
4484b9ad928SBarry Smith   Output Parameter:
4497a99bfcaSBarry Smith . newpc - location to put the preconditioner context
4504b9ad928SBarry Smith 
45120f4b53cSBarry Smith   Level: developer
45220f4b53cSBarry Smith 
453f1580f4eSBarry Smith   Note:
454f1580f4eSBarry Smith   The default preconditioner for sparse matrices is `PCILU` or `PCICC` with 0 fill on one process and block Jacobi (`PCBJACOBI`) with `PCILU` or `PCICC`
455f1580f4eSBarry Smith   in parallel. For dense matrices it is always `PCNONE`.
4564b9ad928SBarry Smith 
457562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCApply()`, `PCDestroy()`
4584b9ad928SBarry Smith @*/
459d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCreate(MPI_Comm comm, PC *newpc)
460d71ae5a4SJacob Faibussowitsch {
4614b9ad928SBarry Smith   PC pc;
4624b9ad928SBarry Smith 
4634b9ad928SBarry Smith   PetscFunctionBegin;
4644f572ea9SToby Isaac   PetscAssertPointer(newpc, 2);
4659566063dSJacob Faibussowitsch   PetscCall(PCInitializePackage());
4664b9ad928SBarry Smith 
4679566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(pc, PC_CLASSID, "PC", "Preconditioner", "PC", comm, PCDestroy, PCView));
4680a545947SLisandro Dalcin   pc->mat                  = NULL;
4690a545947SLisandro Dalcin   pc->pmat                 = NULL;
4704b9ad928SBarry Smith   pc->setupcalled          = 0;
4710c24e6a1SHong Zhang   pc->setfromoptionscalled = 0;
4720a545947SLisandro Dalcin   pc->data                 = NULL;
4734b9ad928SBarry Smith   pc->diagonalscale        = PETSC_FALSE;
4740a545947SLisandro Dalcin   pc->diagonalscaleleft    = NULL;
4750a545947SLisandro Dalcin   pc->diagonalscaleright   = NULL;
4764b9ad928SBarry Smith 
4770a545947SLisandro Dalcin   pc->modifysubmatrices  = NULL;
4780a545947SLisandro Dalcin   pc->modifysubmatricesP = NULL;
4792fa5cd67SKarl Rupp 
480a7d21a52SLisandro Dalcin   *newpc = pc;
4813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4824b9ad928SBarry Smith }
4834b9ad928SBarry Smith 
4844b9ad928SBarry Smith /*@
4854b9ad928SBarry Smith   PCApply - Applies the preconditioner to a vector.
4864b9ad928SBarry Smith 
487c3339decSBarry Smith   Collective
4884b9ad928SBarry Smith 
4894b9ad928SBarry Smith   Input Parameters:
4904b9ad928SBarry Smith + pc - the preconditioner context
4914b9ad928SBarry Smith - x  - input vector
4924b9ad928SBarry Smith 
4934b9ad928SBarry Smith   Output Parameter:
4944b9ad928SBarry Smith . y - output vector
4954b9ad928SBarry Smith 
4964b9ad928SBarry Smith   Level: developer
4974b9ad928SBarry Smith 
498562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`, `PCApplyBAorAB()`
4994b9ad928SBarry Smith @*/
500d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply(PC pc, Vec x, Vec y)
501d71ae5a4SJacob Faibussowitsch {
502106e20bfSBarry Smith   PetscInt m, n, mv, nv;
5034b9ad928SBarry Smith 
5044b9ad928SBarry Smith   PetscFunctionBegin;
5050700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5060700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
5070700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
5087827d75bSBarry Smith   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
509e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
510540bdfbdSVaclav Hapla   /* use pmat to check vector sizes since for KSPLSQR the pmat may be of a different size than mat */
5119566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(pc->pmat, &m, &n));
5129566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(x, &mv));
5139566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(y, &nv));
514540bdfbdSVaclav Hapla   /* check pmat * y = x is feasible */
51563a3b9bcSJacob Faibussowitsch   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);
51663a3b9bcSJacob Faibussowitsch   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);
5179566063dSJacob Faibussowitsch   PetscCall(VecSetErrorIfLocked(y, 3));
518106e20bfSBarry Smith 
5199566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc));
5209566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
5219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0));
522dbbe0bcdSBarry Smith   PetscUseTypeMethod(pc, apply, x, y);
5239566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0));
524e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
5259566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
5263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5274b9ad928SBarry Smith }
5284b9ad928SBarry Smith 
5294b9ad928SBarry Smith /*@
530562efe2eSBarry Smith   PCMatApply - Applies the preconditioner to multiple vectors stored as a `MATDENSE`. Like `PCApply()`, `Y` and `X` must be different matrices.
531c41ea70eSPierre Jolivet 
532c3339decSBarry Smith   Collective
533c677e75fSPierre Jolivet 
534c677e75fSPierre Jolivet   Input Parameters:
535c677e75fSPierre Jolivet + pc - the preconditioner context
536c677e75fSPierre Jolivet - X  - block of input vectors
537c677e75fSPierre Jolivet 
538c677e75fSPierre Jolivet   Output Parameter:
539c677e75fSPierre Jolivet . Y - block of output vectors
540c677e75fSPierre Jolivet 
541c677e75fSPierre Jolivet   Level: developer
542c677e75fSPierre Jolivet 
543562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `KSPMatSolve()`
544c677e75fSPierre Jolivet @*/
545d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMatApply(PC pc, Mat X, Mat Y)
546d71ae5a4SJacob Faibussowitsch {
547c677e75fSPierre Jolivet   Mat       A;
548c677e75fSPierre Jolivet   Vec       cy, cx;
549bd82155bSPierre Jolivet   PetscInt  m1, M1, m2, M2, n1, N1, n2, N2, m3, M3, n3, N3;
550c677e75fSPierre Jolivet   PetscBool match;
551c677e75fSPierre Jolivet 
552c677e75fSPierre Jolivet   PetscFunctionBegin;
553c677e75fSPierre Jolivet   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
554e2b200f6SPierre Jolivet   PetscValidHeaderSpecific(X, MAT_CLASSID, 2);
555e2b200f6SPierre Jolivet   PetscValidHeaderSpecific(Y, MAT_CLASSID, 3);
556e2b200f6SPierre Jolivet   PetscCheckSameComm(pc, 1, X, 2);
557e2b200f6SPierre Jolivet   PetscCheckSameComm(pc, 1, Y, 3);
5587827d75bSBarry Smith   PetscCheck(Y != X, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "Y and X must be different matrices");
5599566063dSJacob Faibussowitsch   PetscCall(PCGetOperators(pc, NULL, &A));
5609566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m3, &n3));
5619566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(X, &m2, &n2));
5629566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(Y, &m1, &n1));
5639566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &M3, &N3));
5649566063dSJacob Faibussowitsch   PetscCall(MatGetSize(X, &M2, &N2));
5659566063dSJacob Faibussowitsch   PetscCall(MatGetSize(Y, &M1, &N1));
56663a3b9bcSJacob Faibussowitsch   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);
56763a3b9bcSJacob Faibussowitsch   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);
56863a3b9bcSJacob Faibussowitsch   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);
5699566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)Y, &match, MATSEQDENSE, MATMPIDENSE, ""));
57028b400f6SJacob Faibussowitsch   PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of output vectors not stored in a dense Mat");
5719566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)X, &match, MATSEQDENSE, MATMPIDENSE, ""));
57228b400f6SJacob Faibussowitsch   PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Provided block of input vectors not stored in a dense Mat");
5739566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc));
574c677e75fSPierre Jolivet   if (pc->ops->matapply) {
5759566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_MatApply, pc, X, Y, 0));
576dbbe0bcdSBarry Smith     PetscUseTypeMethod(pc, matapply, X, Y);
5779566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_MatApply, pc, X, Y, 0));
578c677e75fSPierre Jolivet   } else {
5799566063dSJacob Faibussowitsch     PetscCall(PetscInfo(pc, "PC type %s applying column by column\n", ((PetscObject)pc)->type_name));
580bd82155bSPierre Jolivet     for (n1 = 0; n1 < N1; ++n1) {
5819566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVecRead(X, n1, &cx));
5829566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVecWrite(Y, n1, &cy));
5839566063dSJacob Faibussowitsch       PetscCall(PCApply(pc, cx, cy));
5849566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVecWrite(Y, n1, &cy));
5859566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVecRead(X, n1, &cx));
586c677e75fSPierre Jolivet     }
587c677e75fSPierre Jolivet   }
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
589c677e75fSPierre Jolivet }
590c677e75fSPierre Jolivet 
591c677e75fSPierre Jolivet /*@
5924b9ad928SBarry Smith   PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.
5934b9ad928SBarry Smith 
594c3339decSBarry Smith   Collective
5954b9ad928SBarry Smith 
5964b9ad928SBarry Smith   Input Parameters:
5974b9ad928SBarry Smith + pc - the preconditioner context
5984b9ad928SBarry Smith - x  - input vector
5994b9ad928SBarry Smith 
6004b9ad928SBarry Smith   Output Parameter:
6014b9ad928SBarry Smith . y - output vector
6024b9ad928SBarry Smith 
60320f4b53cSBarry Smith   Level: developer
60420f4b53cSBarry Smith 
605f1580f4eSBarry Smith   Note:
606f1580f4eSBarry Smith   Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners.
6074b9ad928SBarry Smith 
608562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricRight()`
6094b9ad928SBarry Smith @*/
610d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplySymmetricLeft(PC pc, Vec x, Vec y)
611d71ae5a4SJacob Faibussowitsch {
6124b9ad928SBarry Smith   PetscFunctionBegin;
6130700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6140700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
6150700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
6167827d75bSBarry Smith   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
617e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
6189566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc));
6199566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
6209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_ApplySymmetricLeft, pc, x, y, 0));
621dbbe0bcdSBarry Smith   PetscUseTypeMethod(pc, applysymmetricleft, x, y);
6229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_ApplySymmetricLeft, pc, x, y, 0));
6239566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
624e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
6253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6264b9ad928SBarry Smith }
6274b9ad928SBarry Smith 
6284b9ad928SBarry Smith /*@
6294b9ad928SBarry Smith   PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.
6304b9ad928SBarry Smith 
631c3339decSBarry Smith   Collective
6324b9ad928SBarry Smith 
6334b9ad928SBarry Smith   Input Parameters:
6344b9ad928SBarry Smith + pc - the preconditioner context
6354b9ad928SBarry Smith - x  - input vector
6364b9ad928SBarry Smith 
6374b9ad928SBarry Smith   Output Parameter:
6384b9ad928SBarry Smith . y - output vector
6394b9ad928SBarry Smith 
6404b9ad928SBarry Smith   Level: developer
6414b9ad928SBarry Smith 
642f1580f4eSBarry Smith   Note:
643f1580f4eSBarry Smith   Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners.
6444b9ad928SBarry Smith 
645562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplySymmetricLeft()`
6464b9ad928SBarry Smith @*/
647d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplySymmetricRight(PC pc, Vec x, Vec y)
648d71ae5a4SJacob Faibussowitsch {
6494b9ad928SBarry Smith   PetscFunctionBegin;
6500700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6510700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
6520700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
6537827d75bSBarry Smith   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
654e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
6559566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc));
6569566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
6579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_ApplySymmetricRight, pc, x, y, 0));
658dbbe0bcdSBarry Smith   PetscUseTypeMethod(pc, applysymmetricright, x, y);
6599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_ApplySymmetricRight, pc, x, y, 0));
6609566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
661e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
6623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6634b9ad928SBarry Smith }
6644b9ad928SBarry Smith 
6654b9ad928SBarry Smith /*@
6664b9ad928SBarry Smith   PCApplyTranspose - Applies the transpose of preconditioner to a vector.
6674b9ad928SBarry Smith 
668c3339decSBarry Smith   Collective
6694b9ad928SBarry Smith 
6704b9ad928SBarry Smith   Input Parameters:
6714b9ad928SBarry Smith + pc - the preconditioner context
6724b9ad928SBarry Smith - x  - input vector
6734b9ad928SBarry Smith 
6744b9ad928SBarry Smith   Output Parameter:
6754b9ad928SBarry Smith . y - output vector
6764b9ad928SBarry Smith 
67720f4b53cSBarry Smith   Level: developer
67820f4b53cSBarry Smith 
679f1580f4eSBarry Smith   Note:
68095452b02SPatrick Sanan   For complex numbers this applies the non-Hermitian transpose.
6814c97465dSBarry Smith 
682562efe2eSBarry Smith   Developer Note:
683f1580f4eSBarry Smith   We need to implement a `PCApplyHermitianTranspose()`
6844c97465dSBarry Smith 
685562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyBAorAB()`, `PCApplyBAorABTranspose()`, `PCApplyTransposeExists()`
6864b9ad928SBarry Smith @*/
687d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyTranspose(PC pc, Vec x, Vec y)
688d71ae5a4SJacob Faibussowitsch {
6894b9ad928SBarry Smith   PetscFunctionBegin;
6900700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6910700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
6920700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
6937827d75bSBarry Smith   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
694e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
6959566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc));
6969566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
6979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_Apply, pc, x, y, 0));
698dbbe0bcdSBarry Smith   PetscUseTypeMethod(pc, applytranspose, x, y);
6999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_Apply, pc, x, y, 0));
7009566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
701e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
7023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7034b9ad928SBarry Smith }
7044b9ad928SBarry Smith 
7054b9ad928SBarry Smith /*@
7069cc050e5SLisandro Dalcin   PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation
7074b9ad928SBarry Smith 
708c3339decSBarry Smith   Collective
7094b9ad928SBarry Smith 
710f1580f4eSBarry Smith   Input Parameter:
7114b9ad928SBarry Smith . pc - the preconditioner context
7124b9ad928SBarry Smith 
7134b9ad928SBarry Smith   Output Parameter:
714f1580f4eSBarry Smith . flg - `PETSC_TRUE` if a transpose operation is defined
7154b9ad928SBarry Smith 
7164b9ad928SBarry Smith   Level: developer
7174b9ad928SBarry Smith 
718562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApplyTranspose()`
7194b9ad928SBarry Smith @*/
720d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyTransposeExists(PC pc, PetscBool *flg)
721d71ae5a4SJacob Faibussowitsch {
7224b9ad928SBarry Smith   PetscFunctionBegin;
7230700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
7244f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
7256ce5e81cSLisandro Dalcin   if (pc->ops->applytranspose) *flg = PETSC_TRUE;
7266ce5e81cSLisandro Dalcin   else *flg = PETSC_FALSE;
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7284b9ad928SBarry Smith }
7294b9ad928SBarry Smith 
7304b9ad928SBarry Smith /*@
731562efe2eSBarry Smith   PCApplyBAorAB - Applies the preconditioner and operator to a vector. $y = B*A*x $ or $ y = A*B*x$.
7324b9ad928SBarry Smith 
733c3339decSBarry Smith   Collective
7344b9ad928SBarry Smith 
7354b9ad928SBarry Smith   Input Parameters:
7364b9ad928SBarry Smith + pc   - the preconditioner context
737f1580f4eSBarry Smith . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
7384b9ad928SBarry Smith . x    - input vector
7394b9ad928SBarry Smith - work - work vector
7404b9ad928SBarry Smith 
7414b9ad928SBarry Smith   Output Parameter:
7424b9ad928SBarry Smith . y - output vector
7434b9ad928SBarry Smith 
7444b9ad928SBarry Smith   Level: developer
7454b9ad928SBarry Smith 
746f1580f4eSBarry Smith   Note:
747562efe2eSBarry Smith   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.
748562efe2eSBarry Smith   The specific `KSPSolve()` method must also be written to handle the post-solve "correction" for the diagonal scaling.
74913e0d083SBarry Smith 
750562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorABTranspose()`
7514b9ad928SBarry Smith @*/
752d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyBAorAB(PC pc, PCSide side, Vec x, Vec y, Vec work)
753d71ae5a4SJacob Faibussowitsch {
7544b9ad928SBarry Smith   PetscFunctionBegin;
7550700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
756a69c7061SStefano Zampini   PetscValidLogicalCollectiveEnum(pc, side, 2);
7570700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7580700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 4);
7590700a824SBarry Smith   PetscValidHeaderSpecific(work, VEC_CLASSID, 5);
760a69c7061SStefano Zampini   PetscCheckSameComm(pc, 1, x, 3);
761a69c7061SStefano Zampini   PetscCheckSameComm(pc, 1, y, 4);
762a69c7061SStefano Zampini   PetscCheckSameComm(pc, 1, work, 5);
7637827d75bSBarry Smith   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
7647827d75bSBarry Smith   PetscCheck(side == PC_LEFT || side == PC_SYMMETRIC || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right, left, or symmetric");
7657827d75bSBarry Smith   PetscCheck(!pc->diagonalscale || side != PC_SYMMETRIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot include diagonal scaling with symmetric preconditioner application");
766e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE));
7674b9ad928SBarry Smith 
7689566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc));
7694b9ad928SBarry Smith   if (pc->diagonalscale) {
7704b9ad928SBarry Smith     if (pc->ops->applyBA) {
7714b9ad928SBarry Smith       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
7729566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(x, &work2));
7739566063dSJacob Faibussowitsch       PetscCall(PCDiagonalScaleRight(pc, x, work2));
774dbbe0bcdSBarry Smith       PetscUseTypeMethod(pc, applyBA, side, work2, y, work);
7759566063dSJacob Faibussowitsch       PetscCall(PCDiagonalScaleLeft(pc, y, y));
7769566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&work2));
7774b9ad928SBarry Smith     } else if (side == PC_RIGHT) {
7789566063dSJacob Faibussowitsch       PetscCall(PCDiagonalScaleRight(pc, x, y));
7799566063dSJacob Faibussowitsch       PetscCall(PCApply(pc, y, work));
7809566063dSJacob Faibussowitsch       PetscCall(MatMult(pc->mat, work, y));
7819566063dSJacob Faibussowitsch       PetscCall(PCDiagonalScaleLeft(pc, y, y));
7824b9ad928SBarry Smith     } else if (side == PC_LEFT) {
7839566063dSJacob Faibussowitsch       PetscCall(PCDiagonalScaleRight(pc, x, y));
7849566063dSJacob Faibussowitsch       PetscCall(MatMult(pc->mat, y, work));
7859566063dSJacob Faibussowitsch       PetscCall(PCApply(pc, work, y));
7869566063dSJacob Faibussowitsch       PetscCall(PCDiagonalScaleLeft(pc, y, y));
7877827d75bSBarry Smith     } else PetscCheck(side != PC_SYMMETRIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot provide diagonal scaling with symmetric application of preconditioner");
7884b9ad928SBarry Smith   } else {
7894b9ad928SBarry Smith     if (pc->ops->applyBA) {
790dbbe0bcdSBarry Smith       PetscUseTypeMethod(pc, applyBA, side, x, y, work);
7914b9ad928SBarry Smith     } else if (side == PC_RIGHT) {
7929566063dSJacob Faibussowitsch       PetscCall(PCApply(pc, x, work));
7939566063dSJacob Faibussowitsch       PetscCall(MatMult(pc->mat, work, y));
7944b9ad928SBarry Smith     } else if (side == PC_LEFT) {
7959566063dSJacob Faibussowitsch       PetscCall(MatMult(pc->mat, x, work));
7969566063dSJacob Faibussowitsch       PetscCall(PCApply(pc, work, y));
7974b9ad928SBarry Smith     } else if (side == PC_SYMMETRIC) {
7984b9ad928SBarry Smith       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
7999566063dSJacob Faibussowitsch       PetscCall(PCApplySymmetricRight(pc, x, work));
8009566063dSJacob Faibussowitsch       PetscCall(MatMult(pc->mat, work, y));
8019566063dSJacob Faibussowitsch       PetscCall(VecCopy(y, work));
8029566063dSJacob Faibussowitsch       PetscCall(PCApplySymmetricLeft(pc, work, y));
8034b9ad928SBarry Smith     }
8044b9ad928SBarry Smith   }
805e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
8063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8074b9ad928SBarry Smith }
8084b9ad928SBarry Smith 
8094b9ad928SBarry Smith /*@
8104b9ad928SBarry Smith   PCApplyBAorABTranspose - Applies the transpose of the preconditioner
811562efe2eSBarry Smith   and operator to a vector. That is, applies $B^T * A^T$ with left preconditioning,
812562efe2eSBarry Smith   NOT $(B*A)^T = A^T*B^T$.
8134b9ad928SBarry Smith 
814c3339decSBarry Smith   Collective
8154b9ad928SBarry Smith 
8164b9ad928SBarry Smith   Input Parameters:
8174b9ad928SBarry Smith + pc   - the preconditioner context
818f1580f4eSBarry Smith . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
8194b9ad928SBarry Smith . x    - input vector
8204b9ad928SBarry Smith - work - work vector
8214b9ad928SBarry Smith 
8224b9ad928SBarry Smith   Output Parameter:
8234b9ad928SBarry Smith . y - output vector
8244b9ad928SBarry Smith 
82520f4b53cSBarry Smith   Level: developer
82620f4b53cSBarry Smith 
827f1580f4eSBarry Smith   Note:
828562efe2eSBarry Smith   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
829562efe2eSBarry Smith   defined by $B^T$. This is why this has the funny form that it computes $B^T * A^T$
8309b3038f0SBarry Smith 
831562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorAB()`
8324b9ad928SBarry Smith @*/
833d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyBAorABTranspose(PC pc, PCSide side, Vec x, Vec y, Vec work)
834d71ae5a4SJacob Faibussowitsch {
8354b9ad928SBarry Smith   PetscFunctionBegin;
8360700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
8370700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8380700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 4);
8390700a824SBarry Smith   PetscValidHeaderSpecific(work, VEC_CLASSID, 5);
8407827d75bSBarry Smith   PetscCheck(x != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "x and y must be different vectors");
841e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(x, 3, PETSC_TRUE));
8424b9ad928SBarry Smith   if (pc->ops->applyBAtranspose) {
843dbbe0bcdSBarry Smith     PetscUseTypeMethod(pc, applyBAtranspose, side, x, y, work);
844e0f629ddSJacob Faibussowitsch     if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
8453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8464b9ad928SBarry Smith   }
8477827d75bSBarry Smith   PetscCheck(side == PC_LEFT || side == PC_RIGHT, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Side must be right or left");
8484b9ad928SBarry Smith 
8499566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc));
8504b9ad928SBarry Smith   if (side == PC_RIGHT) {
8519566063dSJacob Faibussowitsch     PetscCall(PCApplyTranspose(pc, x, work));
8529566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pc->mat, work, y));
8534b9ad928SBarry Smith   } else if (side == PC_LEFT) {
8549566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pc->mat, x, work));
8559566063dSJacob Faibussowitsch     PetscCall(PCApplyTranspose(pc, work, y));
8564b9ad928SBarry Smith   }
8574b9ad928SBarry Smith   /* add support for PC_SYMMETRIC */
858e0f629ddSJacob Faibussowitsch   if (pc->erroriffailure) PetscCall(VecValidValues_Internal(y, 4, PETSC_FALSE));
8593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8604b9ad928SBarry Smith }
8614b9ad928SBarry Smith 
8624b9ad928SBarry Smith /*@
8634b9ad928SBarry Smith   PCApplyRichardsonExists - Determines whether a particular preconditioner has a
8644b9ad928SBarry Smith   built-in fast application of Richardson's method.
8654b9ad928SBarry Smith 
8664b9ad928SBarry Smith   Not Collective
8674b9ad928SBarry Smith 
8684b9ad928SBarry Smith   Input Parameter:
8694b9ad928SBarry Smith . pc - the preconditioner
8704b9ad928SBarry Smith 
8714b9ad928SBarry Smith   Output Parameter:
872f1580f4eSBarry Smith . exists - `PETSC_TRUE` or `PETSC_FALSE`
8734b9ad928SBarry Smith 
8744b9ad928SBarry Smith   Level: developer
8754b9ad928SBarry Smith 
87639b1ba1bSPierre Jolivet .seealso: [](ch_ksp), `PC`, `KSPRICHARDSON`, `PCApplyRichardson()`
8774b9ad928SBarry Smith @*/
878d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyRichardsonExists(PC pc, PetscBool *exists)
879d71ae5a4SJacob Faibussowitsch {
8804b9ad928SBarry Smith   PetscFunctionBegin;
8810700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
8824f572ea9SToby Isaac   PetscAssertPointer(exists, 2);
8834b9ad928SBarry Smith   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
8844b9ad928SBarry Smith   else *exists = PETSC_FALSE;
8853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8864b9ad928SBarry Smith }
8874b9ad928SBarry Smith 
8884b9ad928SBarry Smith /*@
8894b9ad928SBarry Smith   PCApplyRichardson - Applies several steps of Richardson iteration with
8904b9ad928SBarry Smith   the particular preconditioner. This routine is usually used by the
8914b9ad928SBarry Smith   Krylov solvers and not the application code directly.
8924b9ad928SBarry Smith 
893c3339decSBarry Smith   Collective
8944b9ad928SBarry Smith 
8954b9ad928SBarry Smith   Input Parameters:
8964b9ad928SBarry Smith + pc        - the preconditioner context
897dd8e379bSPierre Jolivet . b         - the right-hand side
8984b9ad928SBarry Smith . w         - one work vector
8994b9ad928SBarry Smith . rtol      - relative decrease in residual norm convergence criteria
90070441072SBarry Smith . abstol    - absolute residual norm convergence criteria
9014b9ad928SBarry Smith . dtol      - divergence residual norm increase criteria
9027319c654SBarry Smith . its       - the number of iterations to apply.
9037319c654SBarry Smith - guesszero - if the input x contains nonzero initial guess
9044b9ad928SBarry Smith 
905d8d19677SJose E. Roman   Output Parameters:
9064d0a8057SBarry Smith + outits - number of iterations actually used (for SOR this always equals its)
9074d0a8057SBarry Smith . reason - the reason the apply terminated
908f1580f4eSBarry Smith - y      - the solution (also contains initial guess if guesszero is `PETSC_FALSE`
9094b9ad928SBarry Smith 
91020f4b53cSBarry Smith   Level: developer
91120f4b53cSBarry Smith 
9124b9ad928SBarry Smith   Notes:
9134b9ad928SBarry Smith   Most preconditioners do not support this function. Use the command
914f1580f4eSBarry Smith   `PCApplyRichardsonExists()` to determine if one does.
9154b9ad928SBarry Smith 
916f1580f4eSBarry Smith   Except for the `PCMG` this routine ignores the convergence tolerances
9174b9ad928SBarry Smith   and always runs for the number of iterations
9184b9ad928SBarry Smith 
919562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCApplyRichardsonExists()`
9204b9ad928SBarry Smith @*/
921d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyRichardson(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
922d71ae5a4SJacob Faibussowitsch {
9234b9ad928SBarry Smith   PetscFunctionBegin;
9240700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
9250700a824SBarry Smith   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
9260700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
9270700a824SBarry Smith   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
9287827d75bSBarry Smith   PetscCheck(b != y, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_IDN, "b and y must be different vectors");
9299566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc));
930dbbe0bcdSBarry Smith   PetscUseTypeMethod(pc, applyrichardson, b, y, w, rtol, abstol, dtol, its, guesszero, outits, reason);
9313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9324b9ad928SBarry Smith }
9334b9ad928SBarry Smith 
934422a814eSBarry Smith /*@
935f1580f4eSBarry Smith   PCSetFailedReason - Sets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail
9361b2b9847SBarry Smith 
937c3339decSBarry Smith   Logically Collective
9381b2b9847SBarry Smith 
939d8d19677SJose E. Roman   Input Parameters:
9401b2b9847SBarry Smith + pc     - the preconditioner context
9411b2b9847SBarry Smith - reason - the reason it failedx
9421b2b9847SBarry Smith 
9431b2b9847SBarry Smith   Level: advanced
9441b2b9847SBarry Smith 
945562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCFailedReason`
9461b2b9847SBarry Smith @*/
947d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFailedReason(PC pc, PCFailedReason reason)
948d71ae5a4SJacob Faibussowitsch {
9491b2b9847SBarry Smith   PetscFunctionBegin;
9506479e835SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
9511b2b9847SBarry Smith   pc->failedreason = reason;
9523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9531b2b9847SBarry Smith }
9541b2b9847SBarry Smith 
9551b2b9847SBarry Smith /*@
956f1580f4eSBarry Smith   PCGetFailedReason - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail
957422a814eSBarry Smith 
958c3339decSBarry Smith   Logically Collective
959422a814eSBarry Smith 
960422a814eSBarry Smith   Input Parameter:
961422a814eSBarry Smith . pc - the preconditioner context
962422a814eSBarry Smith 
963422a814eSBarry Smith   Output Parameter:
9641b2b9847SBarry Smith . reason - the reason it failed
965422a814eSBarry Smith 
966422a814eSBarry Smith   Level: advanced
967422a814eSBarry Smith 
968f1580f4eSBarry Smith   Note:
969f1580f4eSBarry Smith   This is the maximum over reason over all ranks in the PC communicator. It is only valid after
9706479e835SStefano Zampini   a call `KSPCheckDot()` or  `KSPCheckNorm()` inside a `KSPSolve()` or `PCReduceFailedReason()`.
9716479e835SStefano Zampini   It is not valid immediately after a `PCSetUp()` or `PCApply()`, then use `PCGetFailedReasonRank()`
9721b2b9847SBarry Smith 
973a94f484eSPierre Jolivet .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReasonRank()`, `PCSetFailedReason()`
974422a814eSBarry Smith @*/
975d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetFailedReason(PC pc, PCFailedReason *reason)
976d71ae5a4SJacob Faibussowitsch {
977422a814eSBarry Smith   PetscFunctionBegin;
9786479e835SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
9799754764cSHong Zhang   if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled;
9800ae0b32dSHong Zhang   else *reason = pc->failedreason;
9813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
982422a814eSBarry Smith }
983422a814eSBarry Smith 
9841b2b9847SBarry Smith /*@
985f1580f4eSBarry Smith   PCGetFailedReasonRank - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail on this MPI rank
9861b2b9847SBarry Smith 
987f1580f4eSBarry Smith   Not Collective
9881b2b9847SBarry Smith 
9891b2b9847SBarry Smith   Input Parameter:
9901b2b9847SBarry Smith . pc - the preconditioner context
9911b2b9847SBarry Smith 
9921b2b9847SBarry Smith   Output Parameter:
9931b2b9847SBarry Smith . reason - the reason it failed
9941b2b9847SBarry Smith 
99520f4b53cSBarry Smith   Level: advanced
99620f4b53cSBarry Smith 
997f1580f4eSBarry Smith   Note:
998562efe2eSBarry Smith   Different processes may have different reasons or no reason, see `PCGetFailedReason()`
9991b2b9847SBarry Smith 
1000562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()`, `PCReduceFailedReason()`
10011b2b9847SBarry Smith @*/
1002d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetFailedReasonRank(PC pc, PCFailedReason *reason)
1003d71ae5a4SJacob Faibussowitsch {
10041b2b9847SBarry Smith   PetscFunctionBegin;
10056479e835SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
10061b2b9847SBarry Smith   if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled;
10071b2b9847SBarry Smith   else *reason = pc->failedreason;
10083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10091b2b9847SBarry Smith }
1010422a814eSBarry Smith 
10116479e835SStefano Zampini /*@
10126479e835SStefano Zampini   PCReduceFailedReason - Reduce the failed reason among the MPI processes that share the `PC`
10136479e835SStefano Zampini 
10146479e835SStefano Zampini   Collective
10156479e835SStefano Zampini 
10166479e835SStefano Zampini   Input Parameter:
10176479e835SStefano Zampini . pc - the preconditioner context
10186479e835SStefano Zampini 
10196479e835SStefano Zampini   Level: advanced
10206479e835SStefano Zampini 
10216479e835SStefano Zampini   Note:
1022562efe2eSBarry Smith   Different MPI processes may have different reasons or no reason, see `PCGetFailedReason()`. This routine
10236479e835SStefano Zampini   makes them have a common value (failure if any MPI process had a failure).
10246479e835SStefano Zampini 
1025562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()`
10266479e835SStefano Zampini @*/
10276479e835SStefano Zampini PetscErrorCode PCReduceFailedReason(PC pc)
10286479e835SStefano Zampini {
10296479e835SStefano Zampini   PetscInt buf;
10306479e835SStefano Zampini 
10316479e835SStefano Zampini   PetscFunctionBegin;
10326479e835SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
10336479e835SStefano Zampini   buf = (PetscInt)pc->failedreason;
10346479e835SStefano Zampini   PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &buf, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc)));
10356479e835SStefano Zampini   pc->failedreason = (PCFailedReason)buf;
10366479e835SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
10376479e835SStefano Zampini }
10386479e835SStefano Zampini 
10394b9ad928SBarry Smith /*
10404b9ad928SBarry Smith       a setupcall of 0 indicates never setup,
104123ee1639SBarry Smith                      1 indicates has been previously setup
1042422a814eSBarry Smith                     -1 indicates a PCSetUp() was attempted and failed
10434b9ad928SBarry Smith */
10444b9ad928SBarry Smith /*@
10454b9ad928SBarry Smith   PCSetUp - Prepares for the use of a preconditioner.
10464b9ad928SBarry Smith 
1047c3339decSBarry Smith   Collective
10484b9ad928SBarry Smith 
10494b9ad928SBarry Smith   Input Parameter:
10504b9ad928SBarry Smith . pc - the preconditioner context
10514b9ad928SBarry Smith 
10524b9ad928SBarry Smith   Level: developer
10534b9ad928SBarry Smith 
1054562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`
10554b9ad928SBarry Smith @*/
1056d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp(PC pc)
1057d71ae5a4SJacob Faibussowitsch {
1058566e8bf2SBarry Smith   const char      *def;
1059fc9b51d3SBarry Smith   PetscObjectState matstate, matnonzerostate;
10604b9ad928SBarry Smith 
10614b9ad928SBarry Smith   PetscFunctionBegin;
10620700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
106328b400f6SJacob Faibussowitsch   PetscCheck(pc->mat, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be set first");
10646ce5e81cSLisandro Dalcin 
106523ee1639SBarry Smith   if (pc->setupcalled && pc->reusepreconditioner) {
10669566063dSJacob Faibussowitsch     PetscCall(PetscInfo(pc, "Leaving PC with identical preconditioner since reuse preconditioner is set\n"));
10673ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
10684b9ad928SBarry Smith   }
10694b9ad928SBarry Smith 
10709566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)pc->pmat, &matstate));
10719566063dSJacob Faibussowitsch   PetscCall(MatGetNonzeroState(pc->pmat, &matnonzerostate));
107223ee1639SBarry Smith   if (!pc->setupcalled) {
10735e62d202SMark Adams     //PetscCall(PetscInfo(pc, "Setting up PC for first time\n"));
107423ee1639SBarry Smith     pc->flag = DIFFERENT_NONZERO_PATTERN;
10759df67409SStefano Zampini   } else if (matstate == pc->matstate) PetscFunctionReturn(PETSC_SUCCESS);
10769df67409SStefano Zampini   else {
10779df67409SStefano Zampini     if (matnonzerostate != pc->matnonzerostate) {
10789566063dSJacob Faibussowitsch       PetscCall(PetscInfo(pc, "Setting up PC with different nonzero pattern\n"));
107923ee1639SBarry Smith       pc->flag = DIFFERENT_NONZERO_PATTERN;
108023ee1639SBarry Smith     } else {
10815e62d202SMark Adams       //PetscCall(PetscInfo(pc, "Setting up PC with same nonzero pattern\n"));
108223ee1639SBarry Smith       pc->flag = SAME_NONZERO_PATTERN;
108323ee1639SBarry Smith     }
108423ee1639SBarry Smith   }
108523ee1639SBarry Smith   pc->matstate        = matstate;
1086fc9b51d3SBarry Smith   pc->matnonzerostate = matnonzerostate;
108723ee1639SBarry Smith 
10887adad957SLisandro Dalcin   if (!((PetscObject)pc)->type_name) {
10899566063dSJacob Faibussowitsch     PetscCall(PCGetDefaultType_Private(pc, &def));
10909566063dSJacob Faibussowitsch     PetscCall(PCSetType(pc, def));
1091566e8bf2SBarry Smith   }
10924b9ad928SBarry Smith 
10939566063dSJacob Faibussowitsch   PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure));
10949566063dSJacob Faibussowitsch   PetscCall(MatSetErrorIfFailure(pc->mat, pc->erroriffailure));
10959566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_SetUp, pc, 0, 0, 0));
10964b9ad928SBarry Smith   if (pc->ops->setup) {
1097fe57bb1aSStefano Zampini     PetscCall(PCLogEventsDeactivatePush());
1098dbbe0bcdSBarry Smith     PetscUseTypeMethod(pc, setup);
1099fe57bb1aSStefano Zampini     PetscCall(PCLogEventsDeactivatePop());
11004b9ad928SBarry Smith   }
11019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_SetUp, pc, 0, 0, 0));
1102422a814eSBarry Smith   if (!pc->setupcalled) pc->setupcalled = 1;
11033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11044b9ad928SBarry Smith }
11054b9ad928SBarry Smith 
11064b9ad928SBarry Smith /*@
11074b9ad928SBarry Smith   PCSetUpOnBlocks - Sets up the preconditioner for each block in
1108*73716367SStefano Zampini   the block Jacobi, overlapping Schwarz, and fieldsplit methods.
11094b9ad928SBarry Smith 
1110c3339decSBarry Smith   Collective
11114b9ad928SBarry Smith 
1112f1580f4eSBarry Smith   Input Parameter:
11134b9ad928SBarry Smith . pc - the preconditioner context
11144b9ad928SBarry Smith 
11154b9ad928SBarry Smith   Level: developer
11164b9ad928SBarry Smith 
1117*73716367SStefano Zampini   Notes:
1118*73716367SStefano Zampini   For nested preconditioners such as `PCBJACOBI`, `PCSetUp()` is not called on each sub-`KSP` when `PCSetUp()` is
1119f1580f4eSBarry Smith   called on the outer `PC`, this routine ensures it is called.
1120f1580f4eSBarry Smith 
1121*73716367SStefano Zampini   It calls `PCSetUp()` if not yet called.
1122*73716367SStefano Zampini 
1123562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCCreate()`, `PCApply()`, `PCDestroy()`
11244b9ad928SBarry Smith @*/
1125d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUpOnBlocks(PC pc)
1126d71ae5a4SJacob Faibussowitsch {
11274b9ad928SBarry Smith   PetscFunctionBegin;
11280700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1129*73716367SStefano Zampini   if (!pc->setupcalled) PetscCall(PCSetUp(pc)); /* "if" to prevent -info extra prints */
11303ba16761SJacob Faibussowitsch   if (!pc->ops->setuponblocks) PetscFunctionReturn(PETSC_SUCCESS);
11319566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_SetUpOnBlocks, pc, 0, 0, 0));
1132fe57bb1aSStefano Zampini   PetscCall(PCLogEventsDeactivatePush());
1133dbbe0bcdSBarry Smith   PetscUseTypeMethod(pc, setuponblocks);
1134fe57bb1aSStefano Zampini   PetscCall(PCLogEventsDeactivatePop());
11359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_SetUpOnBlocks, pc, 0, 0, 0));
11363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11374b9ad928SBarry Smith }
11384b9ad928SBarry Smith 
11394b9ad928SBarry Smith /*@C
11404b9ad928SBarry Smith   PCSetModifySubMatrices - Sets a user-defined routine for modifying the
114104c3f3b8SBarry Smith   submatrices that arise within certain subdomain-based preconditioners such as `PCASM`
11424b9ad928SBarry Smith 
1143c3339decSBarry Smith   Logically Collective
11444b9ad928SBarry Smith 
11454b9ad928SBarry Smith   Input Parameters:
11464b9ad928SBarry Smith + pc   - the preconditioner context
11474b9ad928SBarry Smith . func - routine for modifying the submatrices
114804c3f3b8SBarry Smith - ctx  - optional user-defined context (may be `NULL`)
11494b9ad928SBarry Smith 
115020f4b53cSBarry Smith   Calling sequence of `func`:
115120f4b53cSBarry Smith + pc     - the preconditioner context
115204c3f3b8SBarry Smith . nsub   - number of index sets
115320f4b53cSBarry Smith . row    - an array of index sets that contain the global row numbers
11544b9ad928SBarry Smith          that comprise each local submatrix
11554b9ad928SBarry Smith . col    - an array of index sets that contain the global column numbers
11564b9ad928SBarry Smith          that comprise each local submatrix
11574b9ad928SBarry Smith . submat - array of local submatrices
11584b9ad928SBarry Smith - ctx    - optional user-defined context for private data for the
115904c3f3b8SBarry Smith          user-defined func routine (may be `NULL`)
11604b9ad928SBarry Smith 
116120f4b53cSBarry Smith   Level: advanced
116220f4b53cSBarry Smith 
11634b9ad928SBarry Smith   Notes:
116404c3f3b8SBarry Smith   The basic submatrices are extracted from the preconditioner matrix as
116504c3f3b8SBarry Smith   usual; the user can then alter these (for example, to set different boundary
116604c3f3b8SBarry Smith   conditions for each submatrix) before they are used for the local solves.
116704c3f3b8SBarry Smith 
1168f1580f4eSBarry Smith   `PCSetModifySubMatrices()` MUST be called before `KSPSetUp()` and
1169f1580f4eSBarry Smith   `KSPSolve()`.
11704b9ad928SBarry Smith 
1171f1580f4eSBarry Smith   A routine set by `PCSetModifySubMatrices()` is currently called within
1172f1580f4eSBarry Smith   the block Jacobi (`PCBJACOBI`) and additive Schwarz (`PCASM`)
11734b9ad928SBarry Smith   preconditioners.  All other preconditioners ignore this routine.
11744b9ad928SBarry Smith 
1175562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCBJACOBI`, `PCASM`, `PCModifySubMatrices()`
11764b9ad928SBarry Smith @*/
117704c3f3b8SBarry Smith PetscErrorCode PCSetModifySubMatrices(PC pc, PetscErrorCode (*func)(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx), void *ctx)
1178d71ae5a4SJacob Faibussowitsch {
11794b9ad928SBarry Smith   PetscFunctionBegin;
11800700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
11814b9ad928SBarry Smith   pc->modifysubmatrices  = func;
11824b9ad928SBarry Smith   pc->modifysubmatricesP = ctx;
11833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11844b9ad928SBarry Smith }
11854b9ad928SBarry Smith 
11864b9ad928SBarry Smith /*@C
11874b9ad928SBarry Smith   PCModifySubMatrices - Calls an optional user-defined routine within
1188f1580f4eSBarry Smith   certain preconditioners if one has been set with `PCSetModifySubMatrices()`.
11894b9ad928SBarry Smith 
1190c3339decSBarry Smith   Collective
11914b9ad928SBarry Smith 
11924b9ad928SBarry Smith   Input Parameters:
11934b9ad928SBarry Smith + pc     - the preconditioner context
11944b9ad928SBarry Smith . nsub   - the number of local submatrices
11954b9ad928SBarry Smith . row    - an array of index sets that contain the global row numbers
11964b9ad928SBarry Smith          that comprise each local submatrix
11974b9ad928SBarry Smith . col    - an array of index sets that contain the global column numbers
11984b9ad928SBarry Smith          that comprise each local submatrix
11994b9ad928SBarry Smith . submat - array of local submatrices
12004b9ad928SBarry Smith - ctx    - optional user-defined context for private data for the
1201562efe2eSBarry Smith          user-defined routine (may be `NULL`)
12024b9ad928SBarry Smith 
12034b9ad928SBarry Smith   Output Parameter:
12044b9ad928SBarry Smith . submat - array of local submatrices (the entries of which may
12054b9ad928SBarry Smith             have been modified)
12064b9ad928SBarry Smith 
120720f4b53cSBarry Smith   Level: developer
120820f4b53cSBarry Smith 
120904c3f3b8SBarry Smith   Note:
12104b9ad928SBarry Smith   The user should NOT generally call this routine, as it will
121104c3f3b8SBarry Smith   automatically be called within certain preconditioners.
12124b9ad928SBarry Smith 
1213562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetModifySubMatrices()`
12144b9ad928SBarry Smith @*/
1215d71ae5a4SJacob Faibussowitsch PetscErrorCode PCModifySubMatrices(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx)
1216d71ae5a4SJacob Faibussowitsch {
12174b9ad928SBarry Smith   PetscFunctionBegin;
12180700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
12193ba16761SJacob Faibussowitsch   if (!pc->modifysubmatrices) PetscFunctionReturn(PETSC_SUCCESS);
12209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_ModifySubMatrices, pc, 0, 0, 0));
12219566063dSJacob Faibussowitsch   PetscCall((*pc->modifysubmatrices)(pc, nsub, row, col, submat, ctx));
12229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_ModifySubMatrices, pc, 0, 0, 0));
12233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12244b9ad928SBarry Smith }
12254b9ad928SBarry Smith 
12264b9ad928SBarry Smith /*@
12274b9ad928SBarry Smith   PCSetOperators - Sets the matrix associated with the linear system and
12284b9ad928SBarry Smith   a (possibly) different one associated with the preconditioner.
12294b9ad928SBarry Smith 
1230c3339decSBarry Smith   Logically Collective
12314b9ad928SBarry Smith 
12324b9ad928SBarry Smith   Input Parameters:
12334b9ad928SBarry Smith + pc   - the preconditioner context
1234e5d3d808SBarry Smith . Amat - the matrix that defines the linear system
1235d1e9a80fSBarry Smith - Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
12364b9ad928SBarry Smith 
123720f4b53cSBarry Smith   Level: intermediate
1238189c0b8aSBarry Smith 
123920f4b53cSBarry Smith   Notes:
124020f4b53cSBarry Smith   Passing a `NULL` for `Amat` or `Pmat` removes the matrix that is currently used.
124120f4b53cSBarry Smith 
124220f4b53cSBarry Smith   If you wish to replace either `Amat` or `Pmat` but leave the other one untouched then
1243f1580f4eSBarry Smith   first call `KSPGetOperators()` to get the one you wish to keep, call `PetscObjectReference()`
1244f1580f4eSBarry Smith   on it and then pass it back in in your call to `KSPSetOperators()`.
1245189c0b8aSBarry Smith 
12464b9ad928SBarry Smith   More Notes about Repeated Solution of Linear Systems:
124720f4b53cSBarry Smith   PETSc does NOT reset the matrix entries of either `Amat` or `Pmat`
12484b9ad928SBarry Smith   to zero after a linear solve; the user is completely responsible for
1249f1580f4eSBarry Smith   matrix assembly.  See the routine `MatZeroEntries()` if desiring to
12504b9ad928SBarry Smith   zero all elements of a matrix.
12514b9ad928SBarry Smith 
1252562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`
12534b9ad928SBarry Smith  @*/
1254d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetOperators(PC pc, Mat Amat, Mat Pmat)
1255d71ae5a4SJacob Faibussowitsch {
12563b3f6333SBarry Smith   PetscInt m1, n1, m2, n2;
12574b9ad928SBarry Smith 
12584b9ad928SBarry Smith   PetscFunctionBegin;
12590700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
12600700a824SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
12610700a824SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
12623fc8bf9cSBarry Smith   if (Amat) PetscCheckSameComm(pc, 1, Amat, 2);
12633fc8bf9cSBarry Smith   if (Pmat) PetscCheckSameComm(pc, 1, Pmat, 3);
126431641f1aSBarry Smith   if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) {
12659566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(Amat, &m1, &n1));
12669566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->mat, &m2, &n2));
126763a3b9bcSJacob Faibussowitsch     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);
12689566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(Pmat, &m1, &n1));
12699566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->pmat, &m2, &n2));
127063a3b9bcSJacob Faibussowitsch     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);
12713b3f6333SBarry Smith   }
12724b9ad928SBarry Smith 
127323ee1639SBarry Smith   if (Pmat != pc->pmat) {
127423ee1639SBarry Smith     /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */
127523ee1639SBarry Smith     pc->matnonzerostate = -1;
127623ee1639SBarry Smith     pc->matstate        = -1;
127723ee1639SBarry Smith   }
127823ee1639SBarry Smith 
1279906ed7ccSBarry Smith   /* reference first in case the matrices are the same */
12809566063dSJacob Faibussowitsch   if (Amat) PetscCall(PetscObjectReference((PetscObject)Amat));
12819566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pc->mat));
12829566063dSJacob Faibussowitsch   if (Pmat) PetscCall(PetscObjectReference((PetscObject)Pmat));
12839566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pc->pmat));
12844b9ad928SBarry Smith   pc->mat  = Amat;
12854b9ad928SBarry Smith   pc->pmat = Pmat;
12863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1287e56f5c9eSBarry Smith }
1288e56f5c9eSBarry Smith 
128923ee1639SBarry Smith /*@
129023ee1639SBarry Smith   PCSetReusePreconditioner - reuse the current preconditioner even if the operator in the preconditioner has changed.
129123ee1639SBarry Smith 
1292c3339decSBarry Smith   Logically Collective
129323ee1639SBarry Smith 
129423ee1639SBarry Smith   Input Parameters:
129523ee1639SBarry Smith + pc   - the preconditioner context
1296f1580f4eSBarry Smith - flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner
129723ee1639SBarry Smith 
12982b26979fSBarry Smith   Level: intermediate
12992b26979fSBarry Smith 
1300f1580f4eSBarry Smith   Note:
1301f1580f4eSBarry Smith   Normally if a matrix inside a `PC` changes the `PC` automatically updates itself using information from the changed matrix. This option
1302f1580f4eSBarry Smith   prevents this.
1303f1580f4eSBarry Smith 
1304562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCGetReusePreconditioner()`, `KSPSetReusePreconditioner()`
130523ee1639SBarry Smith  @*/
1306d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetReusePreconditioner(PC pc, PetscBool flag)
1307d71ae5a4SJacob Faibussowitsch {
130823ee1639SBarry Smith   PetscFunctionBegin;
130923ee1639SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1310f9177522SStefano Zampini   PetscValidLogicalCollectiveBool(pc, flag, 2);
131123ee1639SBarry Smith   pc->reusepreconditioner = flag;
13123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13134b9ad928SBarry Smith }
13144b9ad928SBarry Smith 
1315c60c7ad4SBarry Smith /*@
1316f1580f4eSBarry Smith   PCGetReusePreconditioner - Determines if the `PC` reuses the current preconditioner even if the operator in the preconditioner has changed.
1317c60c7ad4SBarry Smith 
1318bba28a21SBarry Smith   Not Collective
1319c60c7ad4SBarry Smith 
1320c60c7ad4SBarry Smith   Input Parameter:
1321c60c7ad4SBarry Smith . pc - the preconditioner context
1322c60c7ad4SBarry Smith 
1323c60c7ad4SBarry Smith   Output Parameter:
1324f1580f4eSBarry Smith . flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner
1325c60c7ad4SBarry Smith 
1326d0418729SSatish Balay   Level: intermediate
1327d0418729SSatish Balay 
1328562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCSetReusePreconditioner()`
1329c60c7ad4SBarry Smith  @*/
1330d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetReusePreconditioner(PC pc, PetscBool *flag)
1331d71ae5a4SJacob Faibussowitsch {
1332c60c7ad4SBarry Smith   PetscFunctionBegin;
1333c60c7ad4SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
13344f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
1335c60c7ad4SBarry Smith   *flag = pc->reusepreconditioner;
13363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1337c60c7ad4SBarry Smith }
1338c60c7ad4SBarry Smith 
1339487a658cSBarry Smith /*@
13404b9ad928SBarry Smith   PCGetOperators - Gets the matrix associated with the linear system and
13414b9ad928SBarry Smith   possibly a different one associated with the preconditioner.
13424b9ad928SBarry Smith 
1343562efe2eSBarry Smith   Not Collective, though parallel `Mat`s are returned if `pc` is parallel
13444b9ad928SBarry Smith 
13454b9ad928SBarry Smith   Input Parameter:
13464b9ad928SBarry Smith . pc - the preconditioner context
13474b9ad928SBarry Smith 
13484b9ad928SBarry Smith   Output Parameters:
1349e5d3d808SBarry Smith + Amat - the matrix defining the linear system
135023ee1639SBarry Smith - Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat.
13514b9ad928SBarry Smith 
13524b9ad928SBarry Smith   Level: intermediate
13534b9ad928SBarry Smith 
1354f1580f4eSBarry Smith   Note:
135595452b02SPatrick Sanan   Does not increase the reference count of the matrices, so you should not destroy them
1356298cc208SBarry Smith 
1357f1580f4eSBarry Smith   Alternative usage: If the operators have NOT been set with `KSPSetOperators()`/`PCSetOperators()` then the operators
1358f1580f4eSBarry Smith   are created in `PC` and returned to the user. In this case, if both operators
135973950996SBarry Smith   mat and pmat are requested, two DIFFERENT operators will be returned. If
136073950996SBarry Smith   only one is requested both operators in the PC will be the same (i.e. as
1361f1580f4eSBarry Smith   if one had called `KSPSetOperators()`/`PCSetOperators()` with the same argument for both Mats).
136273950996SBarry Smith   The user must set the sizes of the returned matrices and their type etc just
1363f1580f4eSBarry Smith   as if the user created them with `MatCreate()`. For example,
136473950996SBarry Smith 
1365f1580f4eSBarry Smith .vb
1366f1580f4eSBarry Smith          KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to
1367f1580f4eSBarry Smith            set size, type, etc of Amat
136873950996SBarry Smith 
1369f1580f4eSBarry Smith          MatCreate(comm,&mat);
1370f1580f4eSBarry Smith          KSP/PCSetOperators(ksp/pc,Amat,Amat);
1371f1580f4eSBarry Smith          PetscObjectDereference((PetscObject)mat);
1372f1580f4eSBarry Smith            set size, type, etc of Amat
1373f1580f4eSBarry Smith .ve
137473950996SBarry Smith 
137573950996SBarry Smith   and
137673950996SBarry Smith 
1377f1580f4eSBarry Smith .vb
1378f1580f4eSBarry Smith          KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to
1379f1580f4eSBarry Smith            set size, type, etc of Amat and Pmat
138073950996SBarry Smith 
1381f1580f4eSBarry Smith          MatCreate(comm,&Amat);
1382f1580f4eSBarry Smith          MatCreate(comm,&Pmat);
1383f1580f4eSBarry Smith          KSP/PCSetOperators(ksp/pc,Amat,Pmat);
1384f1580f4eSBarry Smith          PetscObjectDereference((PetscObject)Amat);
1385f1580f4eSBarry Smith          PetscObjectDereference((PetscObject)Pmat);
1386f1580f4eSBarry Smith            set size, type, etc of Amat and Pmat
1387f1580f4eSBarry Smith .ve
138873950996SBarry Smith 
1389f1580f4eSBarry Smith   The rationale for this support is so that when creating a `TS`, `SNES`, or `KSP` the hierarchy
1390b8d709abSRichard Tran Mills   of underlying objects (i.e. `SNES`, `KSP`, `PC`, `Mat`) and their lifespans can be completely
1391f1580f4eSBarry Smith   managed by the top most level object (i.e. the `TS`, `SNES`, or `KSP`). Another way to look
1392f1580f4eSBarry Smith   at this is when you create a `SNES` you do not NEED to create a `KSP` and attach it to
1393f1580f4eSBarry Smith   the `SNES` object (the `SNES` object manages it for you). Similarly when you create a KSP
1394f1580f4eSBarry Smith   you do not need to attach a `PC` to it (the `KSP` object manages the `PC` object for you).
1395f1580f4eSBarry Smith   Thus, why should YOU have to create the `Mat` and attach it to the `SNES`/`KSP`/`PC`, when
139673950996SBarry Smith   it can be created for you?
139773950996SBarry Smith 
1398562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperatorsSet()`
13994b9ad928SBarry Smith @*/
1400d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetOperators(PC pc, Mat *Amat, Mat *Pmat)
1401d71ae5a4SJacob Faibussowitsch {
14024b9ad928SBarry Smith   PetscFunctionBegin;
14030700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1404e5d3d808SBarry Smith   if (Amat) {
140573950996SBarry Smith     if (!pc->mat) {
14069fca8c71SStefano Zampini       if (pc->pmat && !Pmat) { /* Pmat has been set, but user did not request it, so use for Amat */
14079a4708feSJed Brown         pc->mat = pc->pmat;
14089566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)pc->mat));
1409e5d3d808SBarry Smith       } else { /* both Amat and Pmat are empty */
14109566063dSJacob Faibussowitsch         PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->mat));
1411e5d3d808SBarry Smith         if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */
141273950996SBarry Smith           pc->pmat = pc->mat;
14139566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)pc->pmat));
141473950996SBarry Smith         }
141573950996SBarry Smith       }
14169a4708feSJed Brown     }
1417e5d3d808SBarry Smith     *Amat = pc->mat;
141873950996SBarry Smith   }
1419e5d3d808SBarry Smith   if (Pmat) {
142073950996SBarry Smith     if (!pc->pmat) {
1421e5d3d808SBarry Smith       if (pc->mat && !Amat) { /* Amat has been set but was not requested, so use for pmat */
14229a4708feSJed Brown         pc->pmat = pc->mat;
14239566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)pc->pmat));
14249a4708feSJed Brown       } else {
14259566063dSJacob Faibussowitsch         PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pc->pmat));
1426e5d3d808SBarry Smith         if (!Amat) { /* user did NOT request Amat, so make same as Pmat */
142773950996SBarry Smith           pc->mat = pc->pmat;
14289566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)pc->mat));
142973950996SBarry Smith         }
143073950996SBarry Smith       }
14319a4708feSJed Brown     }
1432e5d3d808SBarry Smith     *Pmat = pc->pmat;
143373950996SBarry Smith   }
14343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14354b9ad928SBarry Smith }
14364b9ad928SBarry Smith 
14375d83a8b1SBarry Smith /*@
1438906ed7ccSBarry Smith   PCGetOperatorsSet - Determines if the matrix associated with the linear system and
1439f1580f4eSBarry Smith   possibly a different one associated with the preconditioner have been set in the `PC`.
1440906ed7ccSBarry Smith 
144120f4b53cSBarry Smith   Not Collective, though the results on all processes should be the same
1442906ed7ccSBarry Smith 
1443906ed7ccSBarry Smith   Input Parameter:
1444906ed7ccSBarry Smith . pc - the preconditioner context
1445906ed7ccSBarry Smith 
1446906ed7ccSBarry Smith   Output Parameters:
1447906ed7ccSBarry Smith + mat  - the matrix associated with the linear system was set
1448906ed7ccSBarry Smith - pmat - matrix associated with the preconditioner was set, usually the same
1449906ed7ccSBarry Smith 
1450906ed7ccSBarry Smith   Level: intermediate
1451906ed7ccSBarry Smith 
1452562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperators()`
1453906ed7ccSBarry Smith @*/
1454d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetOperatorsSet(PC pc, PetscBool *mat, PetscBool *pmat)
1455d71ae5a4SJacob Faibussowitsch {
1456906ed7ccSBarry Smith   PetscFunctionBegin;
14570700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1458906ed7ccSBarry Smith   if (mat) *mat = (pc->mat) ? PETSC_TRUE : PETSC_FALSE;
1459906ed7ccSBarry Smith   if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE;
14603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1461906ed7ccSBarry Smith }
1462906ed7ccSBarry Smith 
1463f39d8e23SSatish Balay /*@
1464a4fd02acSBarry Smith   PCFactorGetMatrix - Gets the factored matrix from the
1465f1580f4eSBarry Smith   preconditioner context.  This routine is valid only for the `PCLU`,
1466f1580f4eSBarry Smith   `PCILU`, `PCCHOLESKY`, and `PCICC` methods.
14674b9ad928SBarry Smith 
1468562efe2eSBarry Smith   Not Collective though `mat` is parallel if `pc` is parallel
14694b9ad928SBarry Smith 
1470f1580f4eSBarry Smith   Input Parameter:
14714b9ad928SBarry Smith . pc - the preconditioner context
14724b9ad928SBarry Smith 
1473feefa0e1SJacob Faibussowitsch   Output Parameters:
14744b9ad928SBarry Smith . mat - the factored matrix
14754b9ad928SBarry Smith 
14764b9ad928SBarry Smith   Level: advanced
14774b9ad928SBarry Smith 
1478f1580f4eSBarry Smith   Note:
1479562efe2eSBarry Smith   Does not increase the reference count for `mat` so DO NOT destroy it
14809405f653SBarry Smith 
1481562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
14824b9ad928SBarry Smith @*/
1483d71ae5a4SJacob Faibussowitsch PetscErrorCode PCFactorGetMatrix(PC pc, Mat *mat)
1484d71ae5a4SJacob Faibussowitsch {
14854b9ad928SBarry Smith   PetscFunctionBegin;
14860700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14874f572ea9SToby Isaac   PetscAssertPointer(mat, 2);
14887def7855SStefano Zampini   PetscCall(PCFactorSetUpMatSolverType(pc));
1489dbbe0bcdSBarry Smith   PetscUseTypeMethod(pc, getfactoredmatrix, mat);
14903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14914b9ad928SBarry Smith }
14924b9ad928SBarry Smith 
1493cc4c1da9SBarry Smith /*@
14944b9ad928SBarry Smith   PCSetOptionsPrefix - Sets the prefix used for searching for all
1495f1580f4eSBarry Smith   `PC` options in the database.
14964b9ad928SBarry Smith 
1497c3339decSBarry Smith   Logically Collective
14984b9ad928SBarry Smith 
14994b9ad928SBarry Smith   Input Parameters:
15004b9ad928SBarry Smith + pc     - the preconditioner context
1501f1580f4eSBarry Smith - prefix - the prefix string to prepend to all `PC` option requests
15024b9ad928SBarry Smith 
1503f1580f4eSBarry Smith   Note:
15044b9ad928SBarry Smith   A hyphen (-) must NOT be given at the beginning of the prefix name.
15054b9ad928SBarry Smith   The first character of all runtime options is AUTOMATICALLY the
15064b9ad928SBarry Smith   hyphen.
15074b9ad928SBarry Smith 
15084b9ad928SBarry Smith   Level: advanced
15094b9ad928SBarry Smith 
1510562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCAppendOptionsPrefix()`, `PCGetOptionsPrefix()`
15114b9ad928SBarry Smith @*/
1512d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetOptionsPrefix(PC pc, const char prefix[])
1513d71ae5a4SJacob Faibussowitsch {
15144b9ad928SBarry Smith   PetscFunctionBegin;
15150700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15169566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)pc, prefix));
15173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15184b9ad928SBarry Smith }
15194b9ad928SBarry Smith 
1520cc4c1da9SBarry Smith /*@
15214b9ad928SBarry Smith   PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1522f1580f4eSBarry Smith   `PC` options in the database.
15234b9ad928SBarry Smith 
1524c3339decSBarry Smith   Logically Collective
15254b9ad928SBarry Smith 
15264b9ad928SBarry Smith   Input Parameters:
15274b9ad928SBarry Smith + pc     - the preconditioner context
1528f1580f4eSBarry Smith - prefix - the prefix string to prepend to all `PC` option requests
15294b9ad928SBarry Smith 
1530f1580f4eSBarry Smith   Note:
15314b9ad928SBarry Smith   A hyphen (-) must NOT be given at the beginning of the prefix name.
15324b9ad928SBarry Smith   The first character of all runtime options is AUTOMATICALLY the
15334b9ad928SBarry Smith   hyphen.
15344b9ad928SBarry Smith 
15354b9ad928SBarry Smith   Level: advanced
15364b9ad928SBarry Smith 
1537562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCGetOptionsPrefix()`
15384b9ad928SBarry Smith @*/
1539d71ae5a4SJacob Faibussowitsch PetscErrorCode PCAppendOptionsPrefix(PC pc, const char prefix[])
1540d71ae5a4SJacob Faibussowitsch {
15414b9ad928SBarry Smith   PetscFunctionBegin;
15420700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15439566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)pc, prefix));
15443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15454b9ad928SBarry Smith }
15464b9ad928SBarry Smith 
1547cc4c1da9SBarry Smith /*@
15484b9ad928SBarry Smith   PCGetOptionsPrefix - Gets the prefix used for searching for all
15494b9ad928SBarry Smith   PC options in the database.
15504b9ad928SBarry Smith 
15514b9ad928SBarry Smith   Not Collective
15524b9ad928SBarry Smith 
1553f1580f4eSBarry Smith   Input Parameter:
15544b9ad928SBarry Smith . pc - the preconditioner context
15554b9ad928SBarry Smith 
1556f1580f4eSBarry Smith   Output Parameter:
15574b9ad928SBarry Smith . prefix - pointer to the prefix string used, is returned
15584b9ad928SBarry Smith 
15594b9ad928SBarry Smith   Level: advanced
15604b9ad928SBarry Smith 
1561562efe2eSBarry Smith   Fortran Note:
1562562efe2eSBarry Smith   The user should pass in a string `prefix` of
1563562efe2eSBarry Smith   sufficient length to hold the prefix.
1564562efe2eSBarry Smith 
1565562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCAppendOptionsPrefix()`
15664b9ad928SBarry Smith @*/
1567d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetOptionsPrefix(PC pc, const char *prefix[])
1568d71ae5a4SJacob Faibussowitsch {
15694b9ad928SBarry Smith   PetscFunctionBegin;
15700700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15714f572ea9SToby Isaac   PetscAssertPointer(prefix, 2);
15729566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc, prefix));
15733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15744b9ad928SBarry Smith }
15754b9ad928SBarry Smith 
15768066bbecSBarry Smith /*
1577dd8e379bSPierre Jolivet    Indicates the right-hand side will be changed by KSPSolve(), this occurs for a few
15788066bbecSBarry Smith   preconditioners including BDDC and Eisentat that transform the equations before applying
15798066bbecSBarry Smith   the Krylov methods
15808066bbecSBarry Smith */
1581d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC pc, PetscBool *change)
1582d71ae5a4SJacob Faibussowitsch {
1583a06fd7f2SStefano Zampini   PetscFunctionBegin;
1584a06fd7f2SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15854f572ea9SToby Isaac   PetscAssertPointer(change, 2);
1586a06fd7f2SStefano Zampini   *change = PETSC_FALSE;
1587cac4c232SBarry Smith   PetscTryMethod(pc, "PCPreSolveChangeRHS_C", (PC, PetscBool *), (pc, change));
15883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1589a06fd7f2SStefano Zampini }
1590a06fd7f2SStefano Zampini 
15914b9ad928SBarry Smith /*@
15924b9ad928SBarry Smith   PCPreSolve - Optional pre-solve phase, intended for any
15934b9ad928SBarry Smith   preconditioner-specific actions that must be performed before
15944b9ad928SBarry Smith   the iterative solve itself.
15954b9ad928SBarry Smith 
1596c3339decSBarry Smith   Collective
15974b9ad928SBarry Smith 
15984b9ad928SBarry Smith   Input Parameters:
15994b9ad928SBarry Smith + pc  - the preconditioner context
16004b9ad928SBarry Smith - ksp - the Krylov subspace context
16014b9ad928SBarry Smith 
16024b9ad928SBarry Smith   Level: developer
16034b9ad928SBarry Smith 
1604feefa0e1SJacob Faibussowitsch   Example Usage:
16054b9ad928SBarry Smith .vb
16064b9ad928SBarry Smith     PCPreSolve(pc,ksp);
160723ce1328SBarry Smith     KSPSolve(ksp,b,x);
16084b9ad928SBarry Smith     PCPostSolve(pc,ksp);
16094b9ad928SBarry Smith .ve
16104b9ad928SBarry Smith 
16114b9ad928SBarry Smith   Notes:
1612f1580f4eSBarry Smith   The pre-solve phase is distinct from the `PCSetUp()` phase.
16134b9ad928SBarry Smith 
1614f1580f4eSBarry Smith   `KSPSolve()` calls this directly, so is rarely called by the user.
16154b9ad928SBarry Smith 
1616562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCPostSolve()`
16174b9ad928SBarry Smith @*/
1618d71ae5a4SJacob Faibussowitsch PetscErrorCode PCPreSolve(PC pc, KSP ksp)
1619d71ae5a4SJacob Faibussowitsch {
16204b9ad928SBarry Smith   Vec x, rhs;
16214b9ad928SBarry Smith 
16224b9ad928SBarry Smith   PetscFunctionBegin;
16230700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16240700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
1625d9a03883SBarry Smith   pc->presolvedone++;
16267827d75bSBarry Smith   PetscCheck(pc->presolvedone <= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot embed PCPreSolve() more than twice");
16279566063dSJacob Faibussowitsch   PetscCall(KSPGetSolution(ksp, &x));
16289566063dSJacob Faibussowitsch   PetscCall(KSPGetRhs(ksp, &rhs));
16294b9ad928SBarry Smith 
1630dbbe0bcdSBarry Smith   if (pc->ops->presolve) PetscUseTypeMethod(pc, presolve, ksp, rhs, x);
1631f4f49eeaSPierre Jolivet   else if (pc->presolve) PetscCall(pc->presolve(pc, ksp));
16323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16334b9ad928SBarry Smith }
16344b9ad928SBarry Smith 
1635f560b561SHong Zhang /*@C
1636f1580f4eSBarry Smith   PCSetPreSolve - Sets function used by `PCPreSolve()` which is intended for any
1637f560b561SHong Zhang   preconditioner-specific actions that must be performed before
1638f560b561SHong Zhang   the iterative solve itself.
1639f560b561SHong Zhang 
1640c3339decSBarry Smith   Logically Collective
1641f560b561SHong Zhang 
1642f560b561SHong Zhang   Input Parameters:
1643f560b561SHong Zhang + pc       - the preconditioner object
1644f560b561SHong Zhang - presolve - the function to call before the solve
1645f560b561SHong Zhang 
164620f4b53cSBarry Smith   Calling sequence of `presolve`:
164720f4b53cSBarry Smith + pc  - the `PC` context
164820f4b53cSBarry Smith - ksp - the `KSP` context
1649f560b561SHong Zhang 
1650f560b561SHong Zhang   Level: developer
1651f560b561SHong Zhang 
1652562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetUp()`, `PCPreSolve()`
1653f560b561SHong Zhang @*/
165404c3f3b8SBarry Smith PetscErrorCode PCSetPreSolve(PC pc, PetscErrorCode (*presolve)(PC pc, KSP ksp))
1655d71ae5a4SJacob Faibussowitsch {
1656f560b561SHong Zhang   PetscFunctionBegin;
1657f560b561SHong Zhang   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1658f560b561SHong Zhang   pc->presolve = presolve;
16593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1660f560b561SHong Zhang }
1661f560b561SHong Zhang 
16624b9ad928SBarry Smith /*@
16634b9ad928SBarry Smith   PCPostSolve - Optional post-solve phase, intended for any
16644b9ad928SBarry Smith   preconditioner-specific actions that must be performed after
16654b9ad928SBarry Smith   the iterative solve itself.
16664b9ad928SBarry Smith 
1667c3339decSBarry Smith   Collective
16684b9ad928SBarry Smith 
16694b9ad928SBarry Smith   Input Parameters:
16704b9ad928SBarry Smith + pc  - the preconditioner context
16714b9ad928SBarry Smith - ksp - the Krylov subspace context
16724b9ad928SBarry Smith 
1673feefa0e1SJacob Faibussowitsch   Example Usage:
16744b9ad928SBarry Smith .vb
16754b9ad928SBarry Smith     PCPreSolve(pc,ksp);
167623ce1328SBarry Smith     KSPSolve(ksp,b,x);
16774b9ad928SBarry Smith     PCPostSolve(pc,ksp);
16784b9ad928SBarry Smith .ve
16794b9ad928SBarry Smith 
1680562efe2eSBarry Smith   Level: developer
1681562efe2eSBarry Smith 
16824b9ad928SBarry Smith   Note:
1683f1580f4eSBarry Smith   `KSPSolve()` calls this routine directly, so it is rarely called by the user.
16844b9ad928SBarry Smith 
1685562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCSetPostSolve()`, `PCSetPresolve()`, `PCPreSolve()`, `KSPSolve()`
16864b9ad928SBarry Smith @*/
1687d71ae5a4SJacob Faibussowitsch PetscErrorCode PCPostSolve(PC pc, KSP ksp)
1688d71ae5a4SJacob Faibussowitsch {
16894b9ad928SBarry Smith   Vec x, rhs;
16904b9ad928SBarry Smith 
16914b9ad928SBarry Smith   PetscFunctionBegin;
16920700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16930700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
1694d9a03883SBarry Smith   pc->presolvedone--;
16959566063dSJacob Faibussowitsch   PetscCall(KSPGetSolution(ksp, &x));
16969566063dSJacob Faibussowitsch   PetscCall(KSPGetRhs(ksp, &rhs));
1697dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, postsolve, ksp, rhs, x);
16983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16994b9ad928SBarry Smith }
17004b9ad928SBarry Smith 
1701ffeef943SBarry Smith /*@
1702f1580f4eSBarry Smith   PCLoad - Loads a `PC` that has been stored in binary  with `PCView()`.
170355849f57SBarry Smith 
1704c3339decSBarry Smith   Collective
170555849f57SBarry Smith 
170655849f57SBarry Smith   Input Parameters:
1707f1580f4eSBarry Smith + newdm  - the newly loaded `PC`, this needs to have been created with `PCCreate()` or
1708f1580f4eSBarry Smith            some related function before a call to `PCLoad()`.
1709f1580f4eSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
171055849f57SBarry Smith 
171155849f57SBarry Smith   Level: intermediate
171255849f57SBarry Smith 
1713f1580f4eSBarry Smith   Note:
1714562efe2eSBarry Smith   The type is determined by the data in the file, any `PCType` set into the `PC` before this call is ignored.
171555849f57SBarry Smith 
1716562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PetscViewerBinaryOpen()`, `PCView()`, `MatLoad()`, `VecLoad()`
171755849f57SBarry Smith @*/
1718d71ae5a4SJacob Faibussowitsch PetscErrorCode PCLoad(PC newdm, PetscViewer viewer)
1719d71ae5a4SJacob Faibussowitsch {
172055849f57SBarry Smith   PetscBool isbinary;
1721060da220SMatthew G. Knepley   PetscInt  classid;
172255849f57SBarry Smith   char      type[256];
172355849f57SBarry Smith 
172455849f57SBarry Smith   PetscFunctionBegin;
172555849f57SBarry Smith   PetscValidHeaderSpecific(newdm, PC_CLASSID, 1);
172655849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
172828b400f6SJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
172955849f57SBarry Smith 
17309566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
17317827d75bSBarry Smith   PetscCheck(classid == PC_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not PC next in file");
17329566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
17339566063dSJacob Faibussowitsch   PetscCall(PCSetType(newdm, type));
1734dbbe0bcdSBarry Smith   PetscTryTypeMethod(newdm, load, viewer);
17353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
173655849f57SBarry Smith }
173755849f57SBarry Smith 
17389804daf3SBarry Smith #include <petscdraw.h>
1739e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
1740e04113cfSBarry Smith   #include <petscviewersaws.h>
17410acecf5bSBarry Smith #endif
1742fe2efc57SMark 
1743ffeef943SBarry Smith /*@
1744562efe2eSBarry Smith   PCViewFromOptions - View from the `PC` based on options in the options database
1745fe2efc57SMark 
1746c3339decSBarry Smith   Collective
1747fe2efc57SMark 
1748fe2efc57SMark   Input Parameters:
174920f4b53cSBarry Smith + A    - the `PC` context
1750f1580f4eSBarry Smith . obj  - Optional object that provides the options prefix
1751736c3998SJose E. Roman - name - command line option
1752fe2efc57SMark 
1753fe2efc57SMark   Level: intermediate
1754f1580f4eSBarry Smith 
1755562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCView`, `PetscObjectViewFromOptions()`, `PCCreate()`
1756fe2efc57SMark @*/
1757d71ae5a4SJacob Faibussowitsch PetscErrorCode PCViewFromOptions(PC A, PetscObject obj, const char name[])
1758d71ae5a4SJacob Faibussowitsch {
1759fe2efc57SMark   PetscFunctionBegin;
1760fe2efc57SMark   PetscValidHeaderSpecific(A, PC_CLASSID, 1);
17619566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
17623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1763fe2efc57SMark }
1764fe2efc57SMark 
1765ffeef943SBarry Smith /*@
1766f1580f4eSBarry Smith   PCView - Prints information about the `PC`
17674b9ad928SBarry Smith 
1768c3339decSBarry Smith   Collective
17694b9ad928SBarry Smith 
17704b9ad928SBarry Smith   Input Parameters:
1771feefa0e1SJacob Faibussowitsch + pc     - the `PC` context
17724b9ad928SBarry Smith - viewer - optional visualization context
17734b9ad928SBarry Smith 
177420f4b53cSBarry Smith   Level: developer
177520f4b53cSBarry Smith 
1776f1580f4eSBarry Smith   Notes:
17774b9ad928SBarry Smith   The available visualization contexts include
1778f1580f4eSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
1779f1580f4eSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
17804b9ad928SBarry Smith   output where only the first processor opens
17814b9ad928SBarry Smith   the file. All other processors send their
17824b9ad928SBarry Smith   data to the first processor to print.
17834b9ad928SBarry Smith 
17844b9ad928SBarry Smith   The user can open an alternative visualization contexts with
1785f1580f4eSBarry Smith   `PetscViewerASCIIOpen()` (output to a specified file).
17864b9ad928SBarry Smith 
1787562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PetscViewer`, `KSPView()`, `PetscViewerASCIIOpen()`
17884b9ad928SBarry Smith @*/
1789d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView(PC pc, PetscViewer viewer)
1790d71ae5a4SJacob Faibussowitsch {
179119fd82e9SBarry Smith   PCType            cstr;
17926cd81132SPierre Jolivet   PetscViewerFormat format;
17936cd81132SPierre Jolivet   PetscBool         iascii, isstring, isbinary, isdraw, pop = PETSC_FALSE;
1794e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
1795536b137fSBarry Smith   PetscBool issaws;
17960acecf5bSBarry Smith #endif
17974b9ad928SBarry Smith 
17984b9ad928SBarry Smith   PetscFunctionBegin;
17990700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
180048a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer));
18010700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1802c9780b6fSBarry Smith   PetscCheckSameComm(pc, 1, viewer, 2);
18034b9ad928SBarry Smith 
18049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
18059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
18069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
18079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
1808e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
18099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
18100acecf5bSBarry Smith #endif
1811219b1045SBarry Smith 
181232077d6dSBarry Smith   if (iascii) {
18139566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pc, viewer));
181448a46eb9SPierre Jolivet     if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  PC has not been set up so information may be incomplete\n"));
18159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
1816dbbe0bcdSBarry Smith     PetscTryTypeMethod(pc, view, viewer);
18179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
1818834dbeb0SBarry Smith     if (pc->mat) {
18196cd81132SPierre Jolivet       PetscCall(PetscViewerGetFormat(viewer, &format));
18206cd81132SPierre Jolivet       if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) {
18219566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO));
18226cd81132SPierre Jolivet         pop = PETSC_TRUE;
18236cd81132SPierre Jolivet       }
18244b9ad928SBarry Smith       if (pc->pmat == pc->mat) {
18259566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix = precond matrix:\n"));
18269566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
18279566063dSJacob Faibussowitsch         PetscCall(MatView(pc->mat, viewer));
18289566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
18294b9ad928SBarry Smith       } else {
1830834dbeb0SBarry Smith         if (pc->pmat) {
18319566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix followed by preconditioner matrix:\n"));
18324b9ad928SBarry Smith         } else {
18339566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "  linear system matrix:\n"));
18344b9ad928SBarry Smith         }
18359566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
18369566063dSJacob Faibussowitsch         PetscCall(MatView(pc->mat, viewer));
18379566063dSJacob Faibussowitsch         if (pc->pmat) PetscCall(MatView(pc->pmat, viewer));
18389566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
18394b9ad928SBarry Smith       }
18406cd81132SPierre Jolivet       if (pop) PetscCall(PetscViewerPopFormat(viewer));
18414b9ad928SBarry Smith     }
18424b9ad928SBarry Smith   } else if (isstring) {
18439566063dSJacob Faibussowitsch     PetscCall(PCGetType(pc, &cstr));
18449566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " PCType: %-7.7s", cstr));
1845dbbe0bcdSBarry Smith     PetscTryTypeMethod(pc, view, viewer);
18469566063dSJacob Faibussowitsch     if (pc->mat) PetscCall(MatView(pc->mat, viewer));
18479566063dSJacob Faibussowitsch     if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer));
18485b0b0462SBarry Smith   } else if (isbinary) {
184955849f57SBarry Smith     PetscInt    classid = PC_FILE_CLASSID;
185055849f57SBarry Smith     MPI_Comm    comm;
185155849f57SBarry Smith     PetscMPIInt rank;
185255849f57SBarry Smith     char        type[256];
185355849f57SBarry Smith 
18549566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
18559566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1856dd400576SPatrick Sanan     if (rank == 0) {
18579566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
18589566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)pc)->type_name, 256));
18599566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
186055849f57SBarry Smith     }
1861dbbe0bcdSBarry Smith     PetscTryTypeMethod(pc, view, viewer);
1862219b1045SBarry Smith   } else if (isdraw) {
1863219b1045SBarry Smith     PetscDraw draw;
1864d9884438SBarry Smith     char      str[25];
186589fd9fafSBarry Smith     PetscReal x, y, bottom, h;
1866d9884438SBarry Smith     PetscInt  n;
1867219b1045SBarry Smith 
18689566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
18699566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
18701d840656SPeter Brune     if (pc->mat) {
18719566063dSJacob Faibussowitsch       PetscCall(MatGetSize(pc->mat, &n, NULL));
187263a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(str, 25, "PC: %s (%" PetscInt_FMT ")", ((PetscObject)pc)->type_name, n));
18731d840656SPeter Brune     } else {
18749566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(str, 25, "PC: %s", ((PetscObject)pc)->type_name));
18751d840656SPeter Brune     }
18769566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_RED, PETSC_DRAW_BLACK, str, NULL, &h));
187789fd9fafSBarry Smith     bottom = y - h;
18789566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
1879dbbe0bcdSBarry Smith     PetscTryTypeMethod(pc, view, viewer);
18809566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
1881e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
1882536b137fSBarry Smith   } else if (issaws) {
1883d45a07a7SBarry Smith     PetscMPIInt rank;
1884d45a07a7SBarry Smith 
18859566063dSJacob Faibussowitsch     PetscCall(PetscObjectName((PetscObject)pc));
18869566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
188748a46eb9SPierre Jolivet     if (!((PetscObject)pc)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)pc, viewer));
18889566063dSJacob Faibussowitsch     if (pc->mat) PetscCall(MatView(pc->mat, viewer));
18899566063dSJacob Faibussowitsch     if (pc->pmat && pc->pmat != pc->mat) PetscCall(MatView(pc->pmat, viewer));
18900acecf5bSBarry Smith #endif
18914b9ad928SBarry Smith   }
18923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18934b9ad928SBarry Smith }
18944b9ad928SBarry Smith 
18954b9ad928SBarry Smith /*@C
1896562efe2eSBarry Smith   PCRegister -  Adds a method (`PCType`) to the preconditioner package.
18971c84c290SBarry Smith 
1898cc4c1da9SBarry Smith   Not collective. No Fortran Support
18991c84c290SBarry Smith 
19001c84c290SBarry Smith   Input Parameters:
190120f4b53cSBarry Smith + sname    - name of a new user-defined solver
190220f4b53cSBarry Smith - function - routine to create method context
19031c84c290SBarry Smith 
1904feefa0e1SJacob Faibussowitsch   Example Usage:
19051c84c290SBarry Smith .vb
1906bdf89e91SBarry Smith    PCRegister("my_solver", MySolverCreate);
19071c84c290SBarry Smith .ve
19081c84c290SBarry Smith 
19091c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
19101c84c290SBarry Smith $     PCSetType(pc, "my_solver")
19111c84c290SBarry Smith   or at runtime via the option
19121c84c290SBarry Smith $     -pc_type my_solver
19134b9ad928SBarry Smith 
19144b9ad928SBarry Smith   Level: advanced
19151c84c290SBarry Smith 
191620f4b53cSBarry Smith   Note:
191720f4b53cSBarry Smith   `PCRegister()` may be called multiple times to add several user-defined preconditioners.
191820f4b53cSBarry Smith 
1919562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCType`, `PCRegisterAll()`
19204b9ad928SBarry Smith @*/
1921d71ae5a4SJacob Faibussowitsch PetscErrorCode PCRegister(const char sname[], PetscErrorCode (*function)(PC))
1922d71ae5a4SJacob Faibussowitsch {
19234b9ad928SBarry Smith   PetscFunctionBegin;
19249566063dSJacob Faibussowitsch   PetscCall(PCInitializePackage());
19259566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PCList, sname, function));
19263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19274b9ad928SBarry Smith }
19284b9ad928SBarry Smith 
1929d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_PC(Mat A, Vec X, Vec Y)
1930d71ae5a4SJacob Faibussowitsch {
1931186a3e20SStefano Zampini   PC pc;
1932186a3e20SStefano Zampini 
1933186a3e20SStefano Zampini   PetscFunctionBegin;
19349566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(A, &pc));
19359566063dSJacob Faibussowitsch   PetscCall(PCApply(pc, X, Y));
19363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1937186a3e20SStefano Zampini }
1938186a3e20SStefano Zampini 
19395d83a8b1SBarry Smith /*@
19400bacdadaSStefano Zampini   PCComputeOperator - Computes the explicit preconditioned operator.
19414b9ad928SBarry Smith 
1942c3339decSBarry Smith   Collective
19434b9ad928SBarry Smith 
1944d8d19677SJose E. Roman   Input Parameters:
1945186a3e20SStefano Zampini + pc      - the preconditioner object
1946562efe2eSBarry Smith - mattype - the `MatType` to be used for the operator
19474b9ad928SBarry Smith 
19484b9ad928SBarry Smith   Output Parameter:
1949a5b23f4aSJose E. Roman . mat - the explicit preconditioned operator
19504b9ad928SBarry Smith 
195120f4b53cSBarry Smith   Level: advanced
195220f4b53cSBarry Smith 
1953f1580f4eSBarry Smith   Note:
1954186a3e20SStefano Zampini   This computation is done by applying the operators to columns of the identity matrix.
1955186a3e20SStefano Zampini   This routine is costly in general, and is recommended for use only with relatively small systems.
1956562efe2eSBarry Smith   Currently, this routine uses a dense matrix format when `mattype` == `NULL`
19574b9ad928SBarry Smith 
1958562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `KSPComputeOperator()`, `MatType`
19594b9ad928SBarry Smith @*/
1960d71ae5a4SJacob Faibussowitsch PetscErrorCode PCComputeOperator(PC pc, MatType mattype, Mat *mat)
1961d71ae5a4SJacob Faibussowitsch {
1962186a3e20SStefano Zampini   PetscInt N, M, m, n;
1963186a3e20SStefano Zampini   Mat      A, Apc;
19644b9ad928SBarry Smith 
19654b9ad928SBarry Smith   PetscFunctionBegin;
19660700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
19674f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
19689566063dSJacob Faibussowitsch   PetscCall(PCGetOperators(pc, &A, NULL));
19699566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
19709566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &M, &N));
19719566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(PetscObjectComm((PetscObject)pc), m, n, M, N, pc, &Apc));
19729566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(Apc, MATOP_MULT, (void (*)(void))MatMult_PC));
19739566063dSJacob Faibussowitsch   PetscCall(MatComputeOperator(Apc, mattype, mat));
19749566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Apc));
19753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19764b9ad928SBarry Smith }
19774b9ad928SBarry Smith 
19786c237d78SBarry Smith /*@
19796c237d78SBarry Smith   PCSetCoordinates - sets the coordinates of all the nodes on the local process
19806c237d78SBarry Smith 
1981c3339decSBarry Smith   Collective
19826c237d78SBarry Smith 
19836c237d78SBarry Smith   Input Parameters:
19846c237d78SBarry Smith + pc     - the solver context
19856c237d78SBarry Smith . dim    - the dimension of the coordinates 1, 2, or 3
198614893cbeSStefano Zampini . nloc   - the blocked size of the coordinates array
198714893cbeSStefano Zampini - coords - the coordinates array
19886c237d78SBarry Smith 
19896c237d78SBarry Smith   Level: intermediate
19906c237d78SBarry Smith 
1991f1580f4eSBarry Smith   Note:
199220f4b53cSBarry Smith   `coords` is an array of the dim coordinates for the nodes on
199320f4b53cSBarry Smith   the local processor, of size `dim`*`nloc`.
199414893cbeSStefano Zampini   If there are 108 equation on a processor
19956c237d78SBarry Smith   for a displacement finite element discretization of elasticity (so
199614893cbeSStefano Zampini   that there are nloc = 36 = 108/3 nodes) then the array must have 108
19976c237d78SBarry Smith   double precision values (ie, 3 * 36).  These x y z coordinates
19986c237d78SBarry Smith   should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x,
19996c237d78SBarry Smith   ... , N-1.z ].
20006c237d78SBarry Smith 
2001562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `MatSetNearNullSpace()`
20026c237d78SBarry Smith @*/
2003d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal coords[])
2004d71ae5a4SJacob Faibussowitsch {
20056c237d78SBarry Smith   PetscFunctionBegin;
200632954da3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
200732954da3SStefano Zampini   PetscValidLogicalCollectiveInt(pc, dim, 2);
200822794d57SStefano Zampini   PetscTryMethod(pc, "PCSetCoordinates_C", (PC, PetscInt, PetscInt, PetscReal[]), (pc, dim, nloc, coords));
20093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20106c237d78SBarry Smith }
2011fd2dd295SFande Kong 
2012fd2dd295SFande Kong /*@
2013fd2dd295SFande Kong   PCGetInterpolations - Gets interpolation matrices for all levels (except level 0)
2014fd2dd295SFande Kong 
2015c3339decSBarry Smith   Logically Collective
2016fd2dd295SFande Kong 
2017d8d19677SJose E. Roman   Input Parameter:
2018d8d19677SJose E. Roman . pc - the precondition context
2019fd2dd295SFande Kong 
2020d8d19677SJose E. Roman   Output Parameters:
2021d8d19677SJose E. Roman + num_levels     - the number of levels
2022562efe2eSBarry Smith - interpolations - the interpolation matrices (size of `num_levels`-1)
2023fd2dd295SFande Kong 
2024fd2dd295SFande Kong   Level: advanced
2025fd2dd295SFande Kong 
2026562efe2eSBarry Smith   Developer Note:
2027f1580f4eSBarry Smith   Why is this here instead of in `PCMG` etc?
2028fd2dd295SFande Kong 
2029562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetInterpolation()`, `PCGetCoarseOperators()`
2030fd2dd295SFande Kong @*/
2031d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetInterpolations(PC pc, PetscInt *num_levels, Mat *interpolations[])
2032d71ae5a4SJacob Faibussowitsch {
2033fd2dd295SFande Kong   PetscFunctionBegin;
2034fd2dd295SFande Kong   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20354f572ea9SToby Isaac   PetscAssertPointer(num_levels, 2);
20364f572ea9SToby Isaac   PetscAssertPointer(interpolations, 3);
2037cac4c232SBarry Smith   PetscUseMethod(pc, "PCGetInterpolations_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, interpolations));
20383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2039fd2dd295SFande Kong }
2040fd2dd295SFande Kong 
2041fd2dd295SFande Kong /*@
2042fd2dd295SFande Kong   PCGetCoarseOperators - Gets coarse operator matrices for all levels (except the finest level)
2043fd2dd295SFande Kong 
2044c3339decSBarry Smith   Logically Collective
2045fd2dd295SFande Kong 
2046d8d19677SJose E. Roman   Input Parameter:
2047d8d19677SJose E. Roman . pc - the precondition context
2048fd2dd295SFande Kong 
2049d8d19677SJose E. Roman   Output Parameters:
2050d8d19677SJose E. Roman + num_levels      - the number of levels
2051562efe2eSBarry Smith - coarseOperators - the coarse operator matrices (size of `num_levels`-1)
2052fd2dd295SFande Kong 
2053fd2dd295SFande Kong   Level: advanced
2054fd2dd295SFande Kong 
2055562efe2eSBarry Smith   Developer Note:
2056f1580f4eSBarry Smith   Why is this here instead of in `PCMG` etc?
2057fd2dd295SFande Kong 
2058562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
2059fd2dd295SFande Kong @*/
2060d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGetCoarseOperators(PC pc, PetscInt *num_levels, Mat *coarseOperators[])
2061d71ae5a4SJacob Faibussowitsch {
2062fd2dd295SFande Kong   PetscFunctionBegin;
2063fd2dd295SFande Kong   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20644f572ea9SToby Isaac   PetscAssertPointer(num_levels, 2);
20654f572ea9SToby Isaac   PetscAssertPointer(coarseOperators, 3);
2066cac4c232SBarry Smith   PetscUseMethod(pc, "PCGetCoarseOperators_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, coarseOperators));
20673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2068fd2dd295SFande Kong }
2069