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