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