Actual source code: precon.c
2: /*
3: The PC (preconditioner) interface routines, callable by users.
4: */
5: #include <petsc/private/pcimpl.h>
6: #include <petscdm.h>
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;
14: PetscErrorCode PCGetDefaultType_Private(PC pc, const char *type[])
15: {
16: PetscMPIInt size;
17: PetscBool hasop, flg1, flg2, set, flg3, isnormal;
19: MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size);
20: if (pc->pmat) {
21: MatHasOperation(pc->pmat, MATOP_GET_DIAGONAL_BLOCK, &hasop);
22: if (size == 1) {
23: MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ICC, &flg1);
24: MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ILU, &flg2);
25: MatIsSymmetricKnown(pc->pmat, &set, &flg3);
26: PetscObjectTypeCompareAny((PetscObject)pc->pmat, &isnormal, MATNORMAL, MATNORMALHERMITIAN, NULL);
27: if (flg1 && (!flg2 || (set && flg3))) {
28: *type = PCICC;
29: } else if (flg2) {
30: *type = PCILU;
31: } else if (isnormal) {
32: *type = PCNONE;
33: } else if (hasop) { /* likely is a parallel matrix run on one processor */
34: *type = PCBJACOBI;
35: } else {
36: *type = PCNONE;
37: }
38: } else {
39: if (hasop) {
40: *type = PCBJACOBI;
41: } else {
42: *type = PCNONE;
43: }
44: }
45: } else {
46: if (size == 1) {
47: *type = PCILU;
48: } else {
49: *type = PCBJACOBI;
50: }
51: }
52: return 0;
53: }
55: /*@
56: PCReset - Resets a PC context to the pcsetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
58: Collective on pc
60: Input Parameter:
61: . pc - the preconditioner context
63: Level: developer
65: Note:
66: 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
68: .seealso: `PC`, `PCCreate()`, `PCSetUp()`
69: @*/
70: PetscErrorCode PCReset(PC pc)
71: {
73: PetscTryTypeMethod(pc, reset);
74: VecDestroy(&pc->diagonalscaleright);
75: VecDestroy(&pc->diagonalscaleleft);
76: MatDestroy(&pc->pmat);
77: MatDestroy(&pc->mat);
79: pc->setupcalled = 0;
80: return 0;
81: }
83: /*@C
84: PCDestroy - Destroys `PC` context that was created with `PCCreate()`.
86: Collective on pc
88: Input Parameter:
89: . pc - the preconditioner context
91: Level: developer
93: .seealso: `PC`, `PCCreate()`, `PCSetUp()`
94: @*/
95: PetscErrorCode PCDestroy(PC *pc)
96: {
97: if (!*pc) return 0;
99: if (--((PetscObject)(*pc))->refct > 0) {
100: *pc = NULL;
101: return 0;
102: }
104: PCReset(*pc);
106: /* if memory was published with SAWs then destroy it */
107: PetscObjectSAWsViewOff((PetscObject)*pc);
108: PetscTryTypeMethod((*pc), destroy);
109: DMDestroy(&(*pc)->dm);
110: PetscHeaderDestroy(pc);
111: return 0;
112: }
114: /*@C
115: PCGetDiagonalScale - Indicates if the preconditioner applies an additional left and right
116: scaling as needed by certain time-stepping codes.
118: Logically Collective on pc
120: Input Parameter:
121: . pc - the preconditioner context
123: Output Parameter:
124: . flag - `PETSC_TRUE` if it applies the scaling
126: Level: developer
128: Note:
129: If this returns `PETSC_TRUE` then the system solved via the Krylov method is
130: .vb
131: D M A D^{-1} y = D M b for left preconditioning or
132: D A M D^{-1} z = D b for right preconditioning
133: .ve
135: .seealso: `PC`, `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCSetDiagonalScale()`
136: @*/
137: PetscErrorCode PCGetDiagonalScale(PC pc, PetscBool *flag)
138: {
141: *flag = pc->diagonalscale;
142: return 0;
143: }
145: /*@
146: PCSetDiagonalScale - Indicates the left scaling to use to apply an additional left and right
147: scaling as needed by certain time-stepping codes.
149: Logically Collective on pc
151: Input Parameters:
152: + pc - the preconditioner context
153: - s - scaling vector
155: Level: intermediate
157: Notes:
158: The system solved via the Krylov method is
159: .vb
160: D M A D^{-1} y = D M b for left preconditioning or
161: D A M D^{-1} z = D b for right preconditioning
162: .ve
164: `PCDiagonalScaleLeft()` scales a vector by D. `PCDiagonalScaleRight()` scales a vector by D^{-1}.
166: .seealso: `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCGetDiagonalScale()`
167: @*/
168: PetscErrorCode PCSetDiagonalScale(PC pc, Vec s)
169: {
172: pc->diagonalscale = PETSC_TRUE;
174: PetscObjectReference((PetscObject)s);
175: VecDestroy(&pc->diagonalscaleleft);
177: pc->diagonalscaleleft = s;
179: VecDuplicate(s, &pc->diagonalscaleright);
180: VecCopy(s, pc->diagonalscaleright);
181: VecReciprocal(pc->diagonalscaleright);
182: return 0;
183: }
185: /*@
186: PCDiagonalScaleLeft - Scales a vector by the left scaling as needed by certain time-stepping codes.
188: Logically Collective on pc
190: Input Parameters:
191: + pc - the preconditioner context
192: . in - input vector
193: - out - scaled vector (maybe the same as in)
195: Level: intermediate
197: Notes:
198: The system solved via the Krylov method is
199: .vb
200: D M A D^{-1} y = D M b for left preconditioning or
201: D A M D^{-1} z = D b for right preconditioning
202: .ve
204: `PCDiagonalScaleLeft()` scales a vector by D. `PCDiagonalScaleRight()` scales a vector by D^{-1}.
206: If diagonal scaling is turned off and in is not out then in is copied to out
208: .seealso: `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleSet()`, `PCDiagonalScaleRight()`, `PCDiagonalScale()`
209: @*/
210: PetscErrorCode PCDiagonalScaleLeft(PC pc, Vec in, Vec out)
211: {
215: if (pc->diagonalscale) {
216: VecPointwiseMult(out, pc->diagonalscaleleft, in);
217: } else if (in != out) {
218: VecCopy(in, out);
219: }
220: return 0;
221: }
223: /*@
224: PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.
226: Logically Collective on pc
228: Input Parameters:
229: + pc - the preconditioner context
230: . in - input vector
231: - out - scaled vector (maybe the same as in)
233: Level: intermediate
235: Notes:
236: The system solved via the Krylov method is
237: .vb
238: D M A D^{-1} y = D M b for left preconditioning or
239: D A M D^{-1} z = D b for right preconditioning
240: .ve
242: `PCDiagonalScaleLeft()` scales a vector by D. `PCDiagonalScaleRight()` scales a vector by D^{-1}.
244: If diagonal scaling is turned off and in is not out then in is copied to out
246: .seealso: `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleSet()`, `PCDiagonalScale()`
247: @*/
248: PetscErrorCode PCDiagonalScaleRight(PC pc, Vec in, Vec out)
249: {
253: if (pc->diagonalscale) {
254: VecPointwiseMult(out, pc->diagonalscaleright, in);
255: } else if (in != out) {
256: VecCopy(in, out);
257: }
258: return 0;
259: }
261: /*@
262: PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the
263: operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`,
264: `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat.
266: Logically Collective on pc
268: Input Parameters:
269: + pc - the preconditioner context
270: - flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false)
272: Options Database Key:
273: . -pc_use_amat <true,false> - use the amat to apply the operator
275: Note:
276: For the common case in which the linear system matrix and the matrix used to construct the
277: preconditioner are identical, this routine is does nothing.
279: Level: intermediate
281: .seealso: `PC`, `PCGetUseAmat()`, `PCBJACOBI`, `PGMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`
282: @*/
283: PetscErrorCode PCSetUseAmat(PC pc, PetscBool flg)
284: {
286: pc->useAmat = flg;
287: return 0;
288: }
290: /*@
291: PCSetErrorIfFailure - Causes `PC` to generate an error if a FPE, for example a zero pivot, is detected.
293: Logically Collective on pc
295: Input Parameters:
296: + pc - iterative context obtained from PCCreate()
297: - flg - `PETSC_TRUE` indicates you want the error generated
299: Level: advanced
301: Notes:
302: Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call `KSPGetConvergedReason()` after a `KSPSolve()`
303: 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
304: detected.
306: This is propagated into KSPs used by this PC, which then propagate it into PCs used by those KSPs
308: .seealso: `PC`, `KSPSetErrorIfNotConverged()`, `PCGetInitialGuessNonzero()`, `PCSetInitialGuessKnoll()`, `PCGetInitialGuessKnoll()`
309: @*/
310: PetscErrorCode PCSetErrorIfFailure(PC pc, PetscBool flg)
311: {
314: pc->erroriffailure = flg;
315: return 0;
316: }
318: /*@
319: PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the
320: operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`,
321: `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat.
323: Logically Collective on pc
325: Input Parameter:
326: . pc - the preconditioner context
328: Output Parameter:
329: . flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false)
331: Note:
332: For the common case in which the linear system matrix and the matrix used to construct the
333: preconditioner are identical, this routine is does nothing.
335: Level: intermediate
337: .seealso: `PC`, `PCSetUseAmat()`, `PCBJACOBI`, `PGMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`
338: @*/
339: PetscErrorCode PCGetUseAmat(PC pc, PetscBool *flg)
340: {
342: *flg = pc->useAmat;
343: return 0;
344: }
346: /*@
347: PCCreate - Creates a preconditioner context, `PC`
349: Collective
351: Input Parameter:
352: . comm - MPI communicator
354: Output Parameter:
355: . pc - location to put the preconditioner context
357: Note:
358: The default preconditioner for sparse matrices is `PCILU` or `PCICC` with 0 fill on one process and block Jacobi (`PCBJACOBI`) with `PCILU` or `PCICC`
359: in parallel. For dense matrices it is always `PCNONE`.
361: Level: developer
363: .seealso: `PC`, `PCSetUp()`, `PCApply()`, `PCDestroy()`
364: @*/
365: PetscErrorCode PCCreate(MPI_Comm comm, PC *newpc)
366: {
367: PC pc;
370: *newpc = NULL;
371: PCInitializePackage();
373: PetscHeaderCreate(pc, PC_CLASSID, "PC", "Preconditioner", "PC", comm, PCDestroy, PCView);
375: pc->mat = NULL;
376: pc->pmat = NULL;
377: pc->setupcalled = 0;
378: pc->setfromoptionscalled = 0;
379: pc->data = NULL;
380: pc->diagonalscale = PETSC_FALSE;
381: pc->diagonalscaleleft = NULL;
382: pc->diagonalscaleright = NULL;
384: pc->modifysubmatrices = NULL;
385: pc->modifysubmatricesP = NULL;
387: *newpc = pc;
388: return 0;
389: }
391: /*@
392: PCApply - Applies the preconditioner to a vector.
394: Collective on pc
396: Input Parameters:
397: + pc - the preconditioner context
398: - x - input vector
400: Output Parameter:
401: . y - output vector
403: Level: developer
405: .seealso: `PC`, `PCApplyTranspose()`, `PCApplyBAorAB()`
406: @*/
407: PetscErrorCode PCApply(PC pc, Vec x, Vec y)
408: {
409: PetscInt m, n, mv, nv;
415: if (pc->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
416: /* use pmat to check vector sizes since for KSPLSQR the pmat may be of a different size than mat */
417: MatGetLocalSize(pc->pmat, &m, &n);
418: VecGetLocalSize(x, &mv);
419: VecGetLocalSize(y, &nv);
420: /* check pmat * y = x is feasible */
423: VecSetErrorIfLocked(y, 3);
425: PCSetUp(pc);
426: VecLockReadPush(x);
427: PetscLogEventBegin(PC_Apply, pc, x, y, 0);
428: PetscUseTypeMethod(pc, apply, x, y);
429: PetscLogEventEnd(PC_Apply, pc, x, y, 0);
430: if (pc->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
431: VecLockReadPop(x);
432: return 0;
433: }
435: /*@
436: PCMatApply - Applies the preconditioner to multiple vectors stored as a `MATDENSE`. Like `PCApply()`, Y and X must be different matrices.
438: Collective on pc
440: Input Parameters:
441: + pc - the preconditioner context
442: - X - block of input vectors
444: Output Parameter:
445: . Y - block of output vectors
447: Level: developer
449: .seealso: `PC`, `PCApply()`, `KSPMatSolve()`
450: @*/
451: PetscErrorCode PCMatApply(PC pc, Mat X, Mat Y)
452: {
453: Mat A;
454: Vec cy, cx;
455: PetscInt m1, M1, m2, M2, n1, N1, n2, N2, m3, M3, n3, N3;
456: PetscBool match;
464: PCGetOperators(pc, NULL, &A);
465: MatGetLocalSize(A, &m3, &n3);
466: MatGetLocalSize(X, &m2, &n2);
467: MatGetLocalSize(Y, &m1, &n1);
468: MatGetSize(A, &M3, &N3);
469: MatGetSize(X, &M2, &N2);
470: MatGetSize(Y, &M1, &N1);
474: PetscObjectBaseTypeCompareAny((PetscObject)Y, &match, MATSEQDENSE, MATMPIDENSE, "");
476: PetscObjectBaseTypeCompareAny((PetscObject)X, &match, MATSEQDENSE, MATMPIDENSE, "");
478: PCSetUp(pc);
479: if (pc->ops->matapply) {
480: PetscLogEventBegin(PC_MatApply, pc, X, Y, 0);
481: PetscUseTypeMethod(pc, matapply, X, Y);
482: PetscLogEventEnd(PC_MatApply, pc, X, Y, 0);
483: } else {
484: PetscInfo(pc, "PC type %s applying column by column\n", ((PetscObject)pc)->type_name);
485: for (n1 = 0; n1 < N1; ++n1) {
486: MatDenseGetColumnVecRead(X, n1, &cx);
487: MatDenseGetColumnVecWrite(Y, n1, &cy);
488: PCApply(pc, cx, cy);
489: MatDenseRestoreColumnVecWrite(Y, n1, &cy);
490: MatDenseRestoreColumnVecRead(X, n1, &cx);
491: }
492: }
493: return 0;
494: }
496: /*@
497: PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.
499: Collective on pc
501: Input Parameters:
502: + pc - the preconditioner context
503: - x - input vector
505: Output Parameter:
506: . y - output vector
508: Note:
509: Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners.
511: Level: developer
513: .seealso: `PC`, `PCApply()`, `PCApplySymmetricRight()`
514: @*/
515: PetscErrorCode PCApplySymmetricLeft(PC pc, Vec x, Vec y)
516: {
521: if (pc->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
522: PCSetUp(pc);
523: VecLockReadPush(x);
524: PetscLogEventBegin(PC_ApplySymmetricLeft, pc, x, y, 0);
525: PetscUseTypeMethod(pc, applysymmetricleft, x, y);
526: PetscLogEventEnd(PC_ApplySymmetricLeft, pc, x, y, 0);
527: VecLockReadPop(x);
528: if (pc->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
529: return 0;
530: }
532: /*@
533: PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.
535: Collective on pc
537: Input Parameters:
538: + pc - the preconditioner context
539: - x - input vector
541: Output Parameter:
542: . y - output vector
544: Level: developer
546: Note:
547: Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners.
549: .seealso: `PC`, `PCApply()`, `PCApplySymmetricLeft()`
550: @*/
551: PetscErrorCode PCApplySymmetricRight(PC pc, Vec x, Vec y)
552: {
557: if (pc->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
558: PCSetUp(pc);
559: VecLockReadPush(x);
560: PetscLogEventBegin(PC_ApplySymmetricRight, pc, x, y, 0);
561: PetscUseTypeMethod(pc, applysymmetricright, x, y);
562: PetscLogEventEnd(PC_ApplySymmetricRight, pc, x, y, 0);
563: VecLockReadPop(x);
564: if (pc->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
565: return 0;
566: }
568: /*@
569: PCApplyTranspose - Applies the transpose of preconditioner to a vector.
571: Collective on pc
573: Input Parameters:
574: + pc - the preconditioner context
575: - x - input vector
577: Output Parameter:
578: . y - output vector
580: Note:
581: For complex numbers this applies the non-Hermitian transpose.
583: Developer Note:
584: We need to implement a `PCApplyHermitianTranspose()`
586: Level: developer
588: .seealso: `PC`, `PCApply()`, `PCApplyBAorAB()`, `PCApplyBAorABTranspose()`, `PCApplyTransposeExists()`
589: @*/
590: PetscErrorCode PCApplyTranspose(PC pc, Vec x, Vec y)
591: {
596: if (pc->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
597: PCSetUp(pc);
598: VecLockReadPush(x);
599: PetscLogEventBegin(PC_Apply, pc, x, y, 0);
600: PetscUseTypeMethod(pc, applytranspose, x, y);
601: PetscLogEventEnd(PC_Apply, pc, x, y, 0);
602: VecLockReadPop(x);
603: if (pc->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
604: return 0;
605: }
607: /*@
608: PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation
610: Collective on pc
612: Input Parameter:
613: . pc - the preconditioner context
615: Output Parameter:
616: . flg - `PETSC_TRUE` if a transpose operation is defined
618: Level: developer
620: .seealso: `PC`, `PCApplyTranspose()`
621: @*/
622: PetscErrorCode PCApplyTransposeExists(PC pc, PetscBool *flg)
623: {
626: if (pc->ops->applytranspose) *flg = PETSC_TRUE;
627: else *flg = PETSC_FALSE;
628: return 0;
629: }
631: /*@
632: PCApplyBAorAB - Applies the preconditioner and operator to a vector. y = B*A*x or y = A*B*x.
634: Collective on pc
636: Input Parameters:
637: + pc - the preconditioner context
638: . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
639: . x - input vector
640: - work - work vector
642: Output Parameter:
643: . y - output vector
645: Level: developer
647: Note:
648: 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
649: specific `KSPSolve()` method must also be written to handle the post-solve "correction" for the diagonal scaling.
651: .seealso: `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorABTranspose()`
652: @*/
653: PetscErrorCode PCApplyBAorAB(PC pc, PCSide side, Vec x, Vec y, Vec work)
654: {
666: if (pc->erroriffailure) VecValidValues_Internal(x, 3, PETSC_TRUE);
668: PCSetUp(pc);
669: if (pc->diagonalscale) {
670: if (pc->ops->applyBA) {
671: Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
672: VecDuplicate(x, &work2);
673: PCDiagonalScaleRight(pc, x, work2);
674: PetscUseTypeMethod(pc, applyBA, side, work2, y, work);
675: PCDiagonalScaleLeft(pc, y, y);
676: VecDestroy(&work2);
677: } else if (side == PC_RIGHT) {
678: PCDiagonalScaleRight(pc, x, y);
679: PCApply(pc, y, work);
680: MatMult(pc->mat, work, y);
681: PCDiagonalScaleLeft(pc, y, y);
682: } else if (side == PC_LEFT) {
683: PCDiagonalScaleRight(pc, x, y);
684: MatMult(pc->mat, y, work);
685: PCApply(pc, work, y);
686: PCDiagonalScaleLeft(pc, y, y);
688: } else {
689: if (pc->ops->applyBA) {
690: PetscUseTypeMethod(pc, applyBA, side, x, y, work);
691: } else if (side == PC_RIGHT) {
692: PCApply(pc, x, work);
693: MatMult(pc->mat, work, y);
694: } else if (side == PC_LEFT) {
695: MatMult(pc->mat, x, work);
696: PCApply(pc, work, y);
697: } else if (side == PC_SYMMETRIC) {
698: /* There's an extra copy here; maybe should provide 2 work vectors instead? */
699: PCApplySymmetricRight(pc, x, work);
700: MatMult(pc->mat, work, y);
701: VecCopy(y, work);
702: PCApplySymmetricLeft(pc, work, y);
703: }
704: }
705: if (pc->erroriffailure) VecValidValues_Internal(y, 4, PETSC_FALSE);
706: return 0;
707: }
709: /*@
710: PCApplyBAorABTranspose - Applies the transpose of the preconditioner
711: and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
712: NOT tr(B*A) = tr(A)*tr(B).
714: Collective on pc
716: Input Parameters:
717: + pc - the preconditioner context
718: . side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
719: . x - input vector
720: - work - work vector
722: Output Parameter:
723: . y - output vector
725: Note:
726: 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
727: defined by B'. This is why this has the funny form that it computes tr(B) * tr(A)
729: Level: developer
731: .seealso: `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorAB()`
732: @*/
733: PetscErrorCode PCApplyBAorABTranspose(PC pc, PCSide side, Vec x, Vec y, Vec work)
734: {
740: if (pc->erroriffailure) VecValidValues_Internal(x, 3, PETSC_TRUE);
741: if (pc->ops->applyBAtranspose) {
742: PetscUseTypeMethod(pc, applyBAtranspose, side, x, y, work);
743: if (pc->erroriffailure) VecValidValues_Internal(y, 4, PETSC_FALSE);
744: return 0;
745: }
748: PCSetUp(pc);
749: if (side == PC_RIGHT) {
750: PCApplyTranspose(pc, x, work);
751: MatMultTranspose(pc->mat, work, y);
752: } else if (side == PC_LEFT) {
753: MatMultTranspose(pc->mat, x, work);
754: PCApplyTranspose(pc, work, y);
755: }
756: /* add support for PC_SYMMETRIC */
757: if (pc->erroriffailure) VecValidValues_Internal(y, 4, PETSC_FALSE);
758: return 0;
759: }
761: /*@
762: PCApplyRichardsonExists - Determines whether a particular preconditioner has a
763: built-in fast application of Richardson's method.
765: Not Collective
767: Input Parameter:
768: . pc - the preconditioner
770: Output Parameter:
771: . exists - `PETSC_TRUE` or `PETSC_FALSE`
773: Level: developer
775: .seealso: `PC`, `PCRICHARDSON`, `PCApplyRichardson()`
776: @*/
777: PetscErrorCode PCApplyRichardsonExists(PC pc, PetscBool *exists)
778: {
781: if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
782: else *exists = PETSC_FALSE;
783: return 0;
784: }
786: /*@
787: PCApplyRichardson - Applies several steps of Richardson iteration with
788: the particular preconditioner. This routine is usually used by the
789: Krylov solvers and not the application code directly.
791: Collective on pc
793: Input Parameters:
794: + pc - the preconditioner context
795: . b - the right hand side
796: . w - one work vector
797: . rtol - relative decrease in residual norm convergence criteria
798: . abstol - absolute residual norm convergence criteria
799: . dtol - divergence residual norm increase criteria
800: . its - the number of iterations to apply.
801: - guesszero - if the input x contains nonzero initial guess
803: Output Parameters:
804: + outits - number of iterations actually used (for SOR this always equals its)
805: . reason - the reason the apply terminated
806: - y - the solution (also contains initial guess if guesszero is `PETSC_FALSE`
808: Notes:
809: Most preconditioners do not support this function. Use the command
810: `PCApplyRichardsonExists()` to determine if one does.
812: Except for the `PCMG` this routine ignores the convergence tolerances
813: and always runs for the number of iterations
815: Level: developer
817: .seealso: `PC`, `PCApplyRichardsonExists()`
818: @*/
819: PetscErrorCode PCApplyRichardson(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
820: {
826: PCSetUp(pc);
827: PetscUseTypeMethod(pc, applyrichardson, b, y, w, rtol, abstol, dtol, its, guesszero, outits, reason);
828: return 0;
829: }
831: /*@
832: PCSetFailedReason - Sets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail
834: Logically Collective on pc
836: Input Parameters:
837: + pc - the preconditioner context
838: - reason - the reason it failedx
840: Level: advanced
842: .seealso: `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCFailedReason`
843: @*/
844: PetscErrorCode PCSetFailedReason(PC pc, PCFailedReason reason)
845: {
846: pc->failedreason = reason;
847: return 0;
848: }
850: /*@
851: PCGetFailedReason - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail
853: Logically Collective on pc
855: Input Parameter:
856: . pc - the preconditioner context
858: Output Parameter:
859: . reason - the reason it failed
861: Level: advanced
863: Note:
864: This is the maximum over reason over all ranks in the PC communicator. It is only valid after
865: a call `KSPCheckDot()` or `KSPCheckNorm()` inside a `KSPSolve()`. It is not valid immediately after a `PCSetUp()`
866: or `PCApply()`, then use `PCGetFailedReasonRank()`
868: .seealso: PC`, ``PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReasonRank()`, `PCSetFailedReason()`
869: @*/
870: PetscErrorCode PCGetFailedReason(PC pc, PCFailedReason *reason)
871: {
872: if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled;
873: else *reason = pc->failedreason;
874: return 0;
875: }
877: /*@
878: PCGetFailedReasonRank - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail on this MPI rank
880: Not Collective
882: Input Parameter:
883: . pc - the preconditioner context
885: Output Parameter:
886: . reason - the reason it failed
888: Note:
889: Different ranks may have different reasons or no reason, see `PCGetFailedReason()`
891: Level: advanced
893: .seealso: `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()`
894: @*/
895: PetscErrorCode PCGetFailedReasonRank(PC pc, PCFailedReason *reason)
896: {
897: if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled;
898: else *reason = pc->failedreason;
899: return 0;
900: }
902: /* Next line needed to deactivate KSP_Solve logging */
903: #include <petsc/private/kspimpl.h>
905: /*
906: a setupcall of 0 indicates never setup,
907: 1 indicates has been previously setup
908: -1 indicates a PCSetUp() was attempted and failed
909: */
910: /*@
911: PCSetUp - Prepares for the use of a preconditioner.
913: Collective on pc
915: Input Parameter:
916: . pc - the preconditioner context
918: Level: developer
920: .seealso: `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`
921: @*/
922: PetscErrorCode PCSetUp(PC pc)
923: {
924: const char *def;
925: PetscObjectState matstate, matnonzerostate;
930: if (pc->setupcalled && pc->reusepreconditioner) {
931: PetscInfo(pc, "Leaving PC with identical preconditioner since reuse preconditioner is set\n");
932: return 0;
933: }
935: PetscObjectStateGet((PetscObject)pc->pmat, &matstate);
936: MatGetNonzeroState(pc->pmat, &matnonzerostate);
937: if (!pc->setupcalled) {
938: PetscInfo(pc, "Setting up PC for first time\n");
939: pc->flag = DIFFERENT_NONZERO_PATTERN;
940: } else if (matstate == pc->matstate) {
941: PetscInfo(pc, "Leaving PC with identical preconditioner since operator is unchanged\n");
942: return 0;
943: } else {
944: if (matnonzerostate > pc->matnonzerostate) {
945: PetscInfo(pc, "Setting up PC with different nonzero pattern\n");
946: pc->flag = DIFFERENT_NONZERO_PATTERN;
947: } else {
948: PetscInfo(pc, "Setting up PC with same nonzero pattern\n");
949: pc->flag = SAME_NONZERO_PATTERN;
950: }
951: }
952: pc->matstate = matstate;
953: pc->matnonzerostate = matnonzerostate;
955: if (!((PetscObject)pc)->type_name) {
956: PCGetDefaultType_Private(pc, &def);
957: PCSetType(pc, def);
958: }
960: MatSetErrorIfFailure(pc->pmat, pc->erroriffailure);
961: MatSetErrorIfFailure(pc->mat, pc->erroriffailure);
962: PetscLogEventBegin(PC_SetUp, pc, 0, 0, 0);
963: if (pc->ops->setup) {
964: /* do not log solves and applications of preconditioners while constructing preconditioners; perhaps they should be logged separately from the regular solves */
965: KSPInitializePackage();
966: PetscLogEventDeactivatePush(KSP_Solve);
967: PetscLogEventDeactivatePush(PC_Apply);
968: PetscUseTypeMethod(pc, setup);
969: PetscLogEventDeactivatePop(KSP_Solve);
970: PetscLogEventDeactivatePop(PC_Apply);
971: }
972: PetscLogEventEnd(PC_SetUp, pc, 0, 0, 0);
973: if (!pc->setupcalled) pc->setupcalled = 1;
974: return 0;
975: }
977: /*@
978: PCSetUpOnBlocks - Sets up the preconditioner for each block in
979: the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
980: methods.
982: Collective on pc
984: Input Parameter:
985: . pc - the preconditioner context
987: Level: developer
989: Note:
990: For nested preconditioners such as `PCBJACOBI` `PCSetUp()` is not called on each sub-`KSP` when `PCSetUp()` is
991: called on the outer `PC`, this routine ensures it is called.
993: .seealso: `PC`, `PCSetUp()`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCSetUp()`
994: @*/
995: PetscErrorCode PCSetUpOnBlocks(PC pc)
996: {
998: if (!pc->ops->setuponblocks) return 0;
999: PetscLogEventBegin(PC_SetUpOnBlocks, pc, 0, 0, 0);
1000: PetscUseTypeMethod(pc, setuponblocks);
1001: PetscLogEventEnd(PC_SetUpOnBlocks, pc, 0, 0, 0);
1002: return 0;
1003: }
1005: /*@C
1006: PCSetModifySubMatrices - Sets a user-defined routine for modifying the
1007: submatrices that arise within certain subdomain-based preconditioners.
1008: The basic submatrices are extracted from the preconditioner matrix as
1009: usual; the user can then alter these (for example, to set different boundary
1010: conditions for each submatrix) before they are used for the local solves.
1012: Logically Collective on pc
1014: Input Parameters:
1015: + pc - the preconditioner context
1016: . func - routine for modifying the submatrices
1017: - ctx - optional user-defined context (may be null)
1019: Calling sequence of func:
1020: $ func (PC pc,PetscInt nsub,IS *row,IS *col,Mat *submat,void *ctx);
1022: + row - an array of index sets that contain the global row numbers
1023: that comprise each local submatrix
1024: . col - an array of index sets that contain the global column numbers
1025: that comprise each local submatrix
1026: . submat - array of local submatrices
1027: - ctx - optional user-defined context for private data for the
1028: user-defined func routine (may be null)
1030: Notes:
1031: `PCSetModifySubMatrices()` MUST be called before `KSPSetUp()` and
1032: `KSPSolve()`.
1034: A routine set by `PCSetModifySubMatrices()` is currently called within
1035: the block Jacobi (`PCBJACOBI`) and additive Schwarz (`PCASM`)
1036: preconditioners. All other preconditioners ignore this routine.
1038: Level: advanced
1040: .seealso: `PC`, `PCBJACOBI`, `PCASM`, `PCModifySubMatrices()`
1041: @*/
1042: PetscErrorCode PCSetModifySubMatrices(PC pc, PetscErrorCode (*func)(PC, PetscInt, const IS[], const IS[], Mat[], void *), void *ctx)
1043: {
1045: pc->modifysubmatrices = func;
1046: pc->modifysubmatricesP = ctx;
1047: return 0;
1048: }
1050: /*@C
1051: PCModifySubMatrices - Calls an optional user-defined routine within
1052: certain preconditioners if one has been set with `PCSetModifySubMatrices()`.
1054: Collective on pc
1056: Input Parameters:
1057: + pc - the preconditioner context
1058: . nsub - the number of local submatrices
1059: . row - an array of index sets that contain the global row numbers
1060: that comprise each local submatrix
1061: . col - an array of index sets that contain the global column numbers
1062: that comprise each local submatrix
1063: . submat - array of local submatrices
1064: - ctx - optional user-defined context for private data for the
1065: user-defined routine (may be null)
1067: Output Parameter:
1068: . submat - array of local submatrices (the entries of which may
1069: have been modified)
1071: Notes:
1072: The user should NOT generally call this routine, as it will
1073: automatically be called within certain preconditioners (currently
1074: block Jacobi, additive Schwarz) if set.
1076: The basic submatrices are extracted from the preconditioner matrix
1077: as usual; the user can then alter these (for example, to set different
1078: boundary conditions for each submatrix) before they are used for the
1079: local solves.
1081: Level: developer
1083: .seealso: `PC`, `PCSetModifySubMatrices()`
1084: @*/
1085: PetscErrorCode PCModifySubMatrices(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx)
1086: {
1088: if (!pc->modifysubmatrices) return 0;
1089: PetscLogEventBegin(PC_ModifySubMatrices, pc, 0, 0, 0);
1090: (*pc->modifysubmatrices)(pc, nsub, row, col, submat, ctx);
1091: PetscLogEventEnd(PC_ModifySubMatrices, pc, 0, 0, 0);
1092: return 0;
1093: }
1095: /*@
1096: PCSetOperators - Sets the matrix associated with the linear system and
1097: a (possibly) different one associated with the preconditioner.
1099: Logically Collective on pc
1101: Input Parameters:
1102: + pc - the preconditioner context
1103: . Amat - the matrix that defines the linear system
1104: - Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
1106: Notes:
1107: Passing a NULL for Amat or Pmat removes the matrix that is currently used.
1109: If you wish to replace either Amat or Pmat but leave the other one untouched then
1110: first call `KSPGetOperators()` to get the one you wish to keep, call `PetscObjectReference()`
1111: on it and then pass it back in in your call to `KSPSetOperators()`.
1113: More Notes about Repeated Solution of Linear Systems:
1114: PETSc does NOT reset the matrix entries of either Amat or Pmat
1115: to zero after a linear solve; the user is completely responsible for
1116: matrix assembly. See the routine `MatZeroEntries()` if desiring to
1117: zero all elements of a matrix.
1119: Level: intermediate
1121: .seealso: `PC`, `PCGetOperators()`, `MatZeroEntries()`
1122: @*/
1123: PetscErrorCode PCSetOperators(PC pc, Mat Amat, Mat Pmat)
1124: {
1125: PetscInt m1, n1, m2, n2;
1132: if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) {
1133: MatGetLocalSize(Amat, &m1, &n1);
1134: MatGetLocalSize(pc->mat, &m2, &n2);
1136: MatGetLocalSize(Pmat, &m1, &n1);
1137: MatGetLocalSize(pc->pmat, &m2, &n2);
1139: }
1141: if (Pmat != pc->pmat) {
1142: /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */
1143: pc->matnonzerostate = -1;
1144: pc->matstate = -1;
1145: }
1147: /* reference first in case the matrices are the same */
1148: if (Amat) PetscObjectReference((PetscObject)Amat);
1149: MatDestroy(&pc->mat);
1150: if (Pmat) PetscObjectReference((PetscObject)Pmat);
1151: MatDestroy(&pc->pmat);
1152: pc->mat = Amat;
1153: pc->pmat = Pmat;
1154: return 0;
1155: }
1157: /*@
1158: PCSetReusePreconditioner - reuse the current preconditioner even if the operator in the preconditioner has changed.
1160: Logically Collective on pc
1162: Input Parameters:
1163: + pc - the preconditioner context
1164: - flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner
1166: Level: intermediate
1168: Note:
1169: Normally if a matrix inside a `PC` changes the `PC` automatically updates itself using information from the changed matrix. This option
1170: prevents this.
1172: .seealso: `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCGetReusePreconditioner()`, `KSPSetReusePreconditioner()`
1173: @*/
1174: PetscErrorCode PCSetReusePreconditioner(PC pc, PetscBool flag)
1175: {
1178: pc->reusepreconditioner = flag;
1179: return 0;
1180: }
1182: /*@
1183: PCGetReusePreconditioner - Determines if the `PC` reuses the current preconditioner even if the operator in the preconditioner has changed.
1185: Not Collective
1187: Input Parameter:
1188: . pc - the preconditioner context
1190: Output Parameter:
1191: . flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner
1193: Level: intermediate
1195: .seealso: `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCSetReusePreconditioner()`
1196: @*/
1197: PetscErrorCode PCGetReusePreconditioner(PC pc, PetscBool *flag)
1198: {
1201: *flag = pc->reusepreconditioner;
1202: return 0;
1203: }
1205: /*@
1206: PCGetOperators - Gets the matrix associated with the linear system and
1207: possibly a different one associated with the preconditioner.
1209: Not collective, though parallel mats are returned if pc is parallel
1211: Input Parameter:
1212: . pc - the preconditioner context
1214: Output Parameters:
1215: + Amat - the matrix defining the linear system
1216: - Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat.
1218: Level: intermediate
1220: Note:
1221: Does not increase the reference count of the matrices, so you should not destroy them
1223: Alternative usage: If the operators have NOT been set with `KSPSetOperators()`/`PCSetOperators()` then the operators
1224: are created in `PC` and returned to the user. In this case, if both operators
1225: mat and pmat are requested, two DIFFERENT operators will be returned. If
1226: only one is requested both operators in the PC will be the same (i.e. as
1227: if one had called `KSPSetOperators()`/`PCSetOperators()` with the same argument for both Mats).
1228: The user must set the sizes of the returned matrices and their type etc just
1229: as if the user created them with `MatCreate()`. For example,
1231: .vb
1232: KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to
1233: set size, type, etc of Amat
1235: MatCreate(comm,&mat);
1236: KSP/PCSetOperators(ksp/pc,Amat,Amat);
1237: PetscObjectDereference((PetscObject)mat);
1238: set size, type, etc of Amat
1239: .ve
1241: and
1243: .vb
1244: KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to
1245: set size, type, etc of Amat and Pmat
1247: MatCreate(comm,&Amat);
1248: MatCreate(comm,&Pmat);
1249: KSP/PCSetOperators(ksp/pc,Amat,Pmat);
1250: PetscObjectDereference((PetscObject)Amat);
1251: PetscObjectDereference((PetscObject)Pmat);
1252: set size, type, etc of Amat and Pmat
1253: .ve
1255: The rationale for this support is so that when creating a `TS`, `SNES`, or `KSP` the hierarchy
1256: of underlying objects (i.e. `SNES`, `KSP`, `PC`, `Mat`) and their livespans can be completely
1257: managed by the top most level object (i.e. the `TS`, `SNES`, or `KSP`). Another way to look
1258: at this is when you create a `SNES` you do not NEED to create a `KSP` and attach it to
1259: the `SNES` object (the `SNES` object manages it for you). Similarly when you create a KSP
1260: you do not need to attach a `PC` to it (the `KSP` object manages the `PC` object for you).
1261: Thus, why should YOU have to create the `Mat` and attach it to the `SNES`/`KSP`/`PC`, when
1262: it can be created for you?
1264: .seealso: `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperatorsSet()`
1265: @*/
1266: PetscErrorCode PCGetOperators(PC pc, Mat *Amat, Mat *Pmat)
1267: {
1269: if (Amat) {
1270: if (!pc->mat) {
1271: if (pc->pmat && !Pmat) { /* Apmat has been set, but user did not request it, so use for Amat */
1272: pc->mat = pc->pmat;
1273: PetscObjectReference((PetscObject)pc->mat);
1274: } else { /* both Amat and Pmat are empty */
1275: MatCreate(PetscObjectComm((PetscObject)pc), &pc->mat);
1276: if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */
1277: pc->pmat = pc->mat;
1278: PetscObjectReference((PetscObject)pc->pmat);
1279: }
1280: }
1281: }
1282: *Amat = pc->mat;
1283: }
1284: if (Pmat) {
1285: if (!pc->pmat) {
1286: if (pc->mat && !Amat) { /* Amat has been set but was not requested, so use for pmat */
1287: pc->pmat = pc->mat;
1288: PetscObjectReference((PetscObject)pc->pmat);
1289: } else {
1290: MatCreate(PetscObjectComm((PetscObject)pc), &pc->pmat);
1291: if (!Amat) { /* user did NOT request Amat, so make same as Pmat */
1292: pc->mat = pc->pmat;
1293: PetscObjectReference((PetscObject)pc->mat);
1294: }
1295: }
1296: }
1297: *Pmat = pc->pmat;
1298: }
1299: return 0;
1300: }
1302: /*@C
1303: PCGetOperatorsSet - Determines if the matrix associated with the linear system and
1304: possibly a different one associated with the preconditioner have been set in the `PC`.
1306: Not collective, though the results on all processes should be the same
1308: Input Parameter:
1309: . pc - the preconditioner context
1311: Output Parameters:
1312: + mat - the matrix associated with the linear system was set
1313: - pmat - matrix associated with the preconditioner was set, usually the same
1315: Level: intermediate
1317: .seealso: `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperators()`
1318: @*/
1319: PetscErrorCode PCGetOperatorsSet(PC pc, PetscBool *mat, PetscBool *pmat)
1320: {
1322: if (mat) *mat = (pc->mat) ? PETSC_TRUE : PETSC_FALSE;
1323: if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE;
1324: return 0;
1325: }
1327: /*@
1328: PCFactorGetMatrix - Gets the factored matrix from the
1329: preconditioner context. This routine is valid only for the `PCLU`,
1330: `PCILU`, `PCCHOLESKY`, and `PCICC` methods.
1332: Not Collective on pc though mat is parallel if pc is parallel
1334: Input Parameter:
1335: . pc - the preconditioner context
1337: Output parameters:
1338: . mat - the factored matrix
1340: Level: advanced
1342: Note:
1343: Does not increase the reference count for the matrix so DO NOT destroy it
1345: .seealso: `PC`, `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
1346: @*/
1347: PetscErrorCode PCFactorGetMatrix(PC pc, Mat *mat)
1348: {
1351: PetscUseTypeMethod(pc, getfactoredmatrix, mat);
1352: return 0;
1353: }
1355: /*@C
1356: PCSetOptionsPrefix - Sets the prefix used for searching for all
1357: `PC` options in the database.
1359: Logically Collective on pc
1361: Input Parameters:
1362: + pc - the preconditioner context
1363: - prefix - the prefix string to prepend to all `PC` option requests
1365: Note:
1366: A hyphen (-) must NOT be given at the beginning of the prefix name.
1367: The first character of all runtime options is AUTOMATICALLY the
1368: hyphen.
1370: Level: advanced
1372: .seealso: `PC`, `PCSetFromOptions`, `PCAppendOptionsPrefix()`, `PCGetOptionsPrefix()`
1373: @*/
1374: PetscErrorCode PCSetOptionsPrefix(PC pc, const char prefix[])
1375: {
1377: PetscObjectSetOptionsPrefix((PetscObject)pc, prefix);
1378: return 0;
1379: }
1381: /*@C
1382: PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1383: `PC` options in the database.
1385: Logically Collective on pc
1387: Input Parameters:
1388: + pc - the preconditioner context
1389: - prefix - the prefix string to prepend to all `PC` option requests
1391: Note:
1392: A hyphen (-) must NOT be given at the beginning of the prefix name.
1393: The first character of all runtime options is AUTOMATICALLY the
1394: hyphen.
1396: Level: advanced
1398: .seealso: `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCGetOptionsPrefix()`
1399: @*/
1400: PetscErrorCode PCAppendOptionsPrefix(PC pc, const char prefix[])
1401: {
1403: PetscObjectAppendOptionsPrefix((PetscObject)pc, prefix);
1404: return 0;
1405: }
1407: /*@C
1408: PCGetOptionsPrefix - Gets the prefix used for searching for all
1409: PC options in the database.
1411: Not Collective
1413: Input Parameter:
1414: . pc - the preconditioner context
1416: Output Parameter:
1417: . prefix - pointer to the prefix string used, is returned
1419: Fortran Note:
1420: The user should pass in a string 'prefix' of
1421: sufficient length to hold the prefix.
1423: Level: advanced
1425: .seealso: `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCAppendOptionsPrefix()`
1426: @*/
1427: PetscErrorCode PCGetOptionsPrefix(PC pc, const char *prefix[])
1428: {
1431: PetscObjectGetOptionsPrefix((PetscObject)pc, prefix);
1432: return 0;
1433: }
1435: /*
1436: Indicates the right hand side will be changed by KSPSolve(), this occurs for a few
1437: preconditioners including BDDC and Eisentat that transform the equations before applying
1438: the Krylov methods
1439: */
1440: PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC pc, PetscBool *change)
1441: {
1444: *change = PETSC_FALSE;
1445: PetscTryMethod(pc, "PCPreSolveChangeRHS_C", (PC, PetscBool *), (pc, change));
1446: return 0;
1447: }
1449: /*@
1450: PCPreSolve - Optional pre-solve phase, intended for any
1451: preconditioner-specific actions that must be performed before
1452: the iterative solve itself.
1454: Collective on pc
1456: Input Parameters:
1457: + pc - the preconditioner context
1458: - ksp - the Krylov subspace context
1460: Level: developer
1462: Sample of Usage:
1463: .vb
1464: PCPreSolve(pc,ksp);
1465: KSPSolve(ksp,b,x);
1466: PCPostSolve(pc,ksp);
1467: .ve
1469: Notes:
1470: The pre-solve phase is distinct from the `PCSetUp()` phase.
1472: `KSPSolve()` calls this directly, so is rarely called by the user.
1474: .seealso: `PC`, `PCPostSolve()`
1475: @*/
1476: PetscErrorCode PCPreSolve(PC pc, KSP ksp)
1477: {
1478: Vec x, rhs;
1482: pc->presolvedone++;
1484: KSPGetSolution(ksp, &x);
1485: KSPGetRhs(ksp, &rhs);
1487: if (pc->ops->presolve) PetscUseTypeMethod(pc, presolve, ksp, rhs, x);
1488: else if (pc->presolve) (pc->presolve)(pc, ksp);
1489: return 0;
1490: }
1492: /*@C
1493: PCSetPreSolve - Sets function used by `PCPreSolve()` which is intended for any
1494: preconditioner-specific actions that must be performed before
1495: the iterative solve itself.
1497: Logically Collective on pc
1499: Input Parameters:
1500: + pc - the preconditioner object
1501: - presolve - the function to call before the solve
1503: Calling sequence of presolve:
1504: $ func(PC pc,KSP ksp)
1506: + pc - the PC context
1507: - ksp - the KSP context
1509: Level: developer
1511: .seealso: `PC`, `PCSetUp()`, `PCPreSolve()`
1512: @*/
1513: PetscErrorCode PCSetPreSolve(PC pc, PetscErrorCode (*presolve)(PC, KSP))
1514: {
1516: pc->presolve = presolve;
1517: return 0;
1518: }
1520: /*@
1521: PCPostSolve - Optional post-solve phase, intended for any
1522: preconditioner-specific actions that must be performed after
1523: the iterative solve itself.
1525: Collective on pc
1527: Input Parameters:
1528: + pc - the preconditioner context
1529: - ksp - the Krylov subspace context
1531: Sample of Usage:
1532: .vb
1533: PCPreSolve(pc,ksp);
1534: KSPSolve(ksp,b,x);
1535: PCPostSolve(pc,ksp);
1536: .ve
1538: Note:
1539: `KSPSolve()` calls this routine directly, so it is rarely called by the user.
1541: Level: developer
1543: .seealso: `PC`, `PCSetPostSolve()`, `PCSetPresolve()`, `PCPreSolve()`, `KSPSolve()`
1544: @*/
1545: PetscErrorCode PCPostSolve(PC pc, KSP ksp)
1546: {
1547: Vec x, rhs;
1551: pc->presolvedone--;
1552: KSPGetSolution(ksp, &x);
1553: KSPGetRhs(ksp, &rhs);
1554: PetscTryTypeMethod(pc, postsolve, ksp, rhs, x);
1555: return 0;
1556: }
1558: /*@C
1559: PCLoad - Loads a `PC` that has been stored in binary with `PCView()`.
1561: Collective on newdm
1563: Input Parameters:
1564: + newdm - the newly loaded `PC`, this needs to have been created with `PCCreate()` or
1565: some related function before a call to `PCLoad()`.
1566: - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
1568: Level: intermediate
1570: Note:
1571: The type is determined by the data in the file, any type set into the PC before this call is ignored.
1573: .seealso: `PC`, `PetscViewerBinaryOpen()`, `PCView()`, `MatLoad()`, `VecLoad()`
1574: @*/
1575: PetscErrorCode PCLoad(PC newdm, PetscViewer viewer)
1576: {
1577: PetscBool isbinary;
1578: PetscInt classid;
1579: char type[256];
1583: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary);
1586: PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT);
1588: PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR);
1589: PCSetType(newdm, type);
1590: PetscTryTypeMethod(newdm, load, viewer);
1591: return 0;
1592: }
1594: #include <petscdraw.h>
1595: #if defined(PETSC_HAVE_SAWS)
1596: #include <petscviewersaws.h>
1597: #endif
1599: /*@C
1600: PCViewFromOptions - View from the `PC` based on options in the database
1602: Collective on pc
1604: Input Parameters:
1605: + A - the PC context
1606: . obj - Optional object that provides the options prefix
1607: - name - command line option
1609: Level: intermediate
1611: .seealso: `PC`, `PCView`, `PetscObjectViewFromOptions()`, `PCCreate()`
1612: @*/
1613: PetscErrorCode PCViewFromOptions(PC A, PetscObject obj, const char name[])
1614: {
1616: PetscObjectViewFromOptions((PetscObject)A, obj, name);
1617: return 0;
1618: }
1620: /*@C
1621: PCView - Prints information about the `PC`
1623: Collective on pc
1625: Input Parameters:
1626: + PC - the `PC` context
1627: - viewer - optional visualization context
1629: Notes:
1630: The available visualization contexts include
1631: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
1632: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
1633: output where only the first processor opens
1634: the file. All other processors send their
1635: data to the first processor to print.
1637: The user can open an alternative visualization contexts with
1638: `PetscViewerASCIIOpen()` (output to a specified file).
1640: Level: developer
1642: .seealso: `PC`, `PetscViewer`, `KSPView()`, `PetscViewerASCIIOpen()`
1643: @*/
1644: PetscErrorCode PCView(PC pc, PetscViewer viewer)
1645: {
1646: PCType cstr;
1647: PetscBool iascii, isstring, isbinary, isdraw;
1648: #if defined(PETSC_HAVE_SAWS)
1649: PetscBool issaws;
1650: #endif
1653: if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer);
1657: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
1658: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
1659: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary);
1660: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw);
1661: #if defined(PETSC_HAVE_SAWS)
1662: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws);
1663: #endif
1665: if (iascii) {
1666: PetscObjectPrintClassNamePrefixType((PetscObject)pc, viewer);
1667: if (!pc->setupcalled) PetscViewerASCIIPrintf(viewer, " PC has not been set up so information may be incomplete\n");
1668: PetscViewerASCIIPushTab(viewer);
1669: PetscTryTypeMethod(pc, view, viewer);
1670: PetscViewerASCIIPopTab(viewer);
1671: if (pc->mat) {
1672: PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO);
1673: if (pc->pmat == pc->mat) {
1674: PetscViewerASCIIPrintf(viewer, " linear system matrix = precond matrix:\n");
1675: PetscViewerASCIIPushTab(viewer);
1676: MatView(pc->mat, viewer);
1677: PetscViewerASCIIPopTab(viewer);
1678: } else {
1679: if (pc->pmat) {
1680: PetscViewerASCIIPrintf(viewer, " linear system matrix followed by preconditioner matrix:\n");
1681: } else {
1682: PetscViewerASCIIPrintf(viewer, " linear system matrix:\n");
1683: }
1684: PetscViewerASCIIPushTab(viewer);
1685: MatView(pc->mat, viewer);
1686: if (pc->pmat) MatView(pc->pmat, viewer);
1687: PetscViewerASCIIPopTab(viewer);
1688: }
1689: PetscViewerPopFormat(viewer);
1690: }
1691: } else if (isstring) {
1692: PCGetType(pc, &cstr);
1693: PetscViewerStringSPrintf(viewer, " PCType: %-7.7s", cstr);
1694: PetscTryTypeMethod(pc, view, viewer);
1695: if (pc->mat) MatView(pc->mat, viewer);
1696: if (pc->pmat && pc->pmat != pc->mat) MatView(pc->pmat, viewer);
1697: } else if (isbinary) {
1698: PetscInt classid = PC_FILE_CLASSID;
1699: MPI_Comm comm;
1700: PetscMPIInt rank;
1701: char type[256];
1703: PetscObjectGetComm((PetscObject)pc, &comm);
1704: MPI_Comm_rank(comm, &rank);
1705: if (rank == 0) {
1706: PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT);
1707: PetscStrncpy(type, ((PetscObject)pc)->type_name, 256);
1708: PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR);
1709: }
1710: PetscTryTypeMethod(pc, view, viewer);
1711: } else if (isdraw) {
1712: PetscDraw draw;
1713: char str[25];
1714: PetscReal x, y, bottom, h;
1715: PetscInt n;
1717: PetscViewerDrawGetDraw(viewer, 0, &draw);
1718: PetscDrawGetCurrentPoint(draw, &x, &y);
1719: if (pc->mat) {
1720: MatGetSize(pc->mat, &n, NULL);
1721: PetscSNPrintf(str, 25, "PC: %s (%" PetscInt_FMT ")", ((PetscObject)pc)->type_name, n);
1722: } else {
1723: PetscSNPrintf(str, 25, "PC: %s", ((PetscObject)pc)->type_name);
1724: }
1725: PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_RED, PETSC_DRAW_BLACK, str, NULL, &h);
1726: bottom = y - h;
1727: PetscDrawPushCurrentPoint(draw, x, bottom);
1728: PetscTryTypeMethod(pc, view, viewer);
1729: PetscDrawPopCurrentPoint(draw);
1730: #if defined(PETSC_HAVE_SAWS)
1731: } else if (issaws) {
1732: PetscMPIInt rank;
1734: PetscObjectName((PetscObject)pc);
1735: MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1736: if (!((PetscObject)pc)->amsmem && rank == 0) PetscObjectViewSAWs((PetscObject)pc, viewer);
1737: if (pc->mat) MatView(pc->mat, viewer);
1738: if (pc->pmat && pc->pmat != pc->mat) MatView(pc->pmat, viewer);
1739: #endif
1740: }
1741: return 0;
1742: }
1744: /*@C
1745: PCRegister - Adds a method to the preconditioner package.
1747: Not collective
1749: Input Parameters:
1750: + name_solver - name of a new user-defined solver
1751: - routine_create - routine to create method context
1753: Note:
1754: `PCRegister()` may be called multiple times to add several user-defined preconditioners.
1756: Sample usage:
1757: .vb
1758: PCRegister("my_solver", MySolverCreate);
1759: .ve
1761: Then, your solver can be chosen with the procedural interface via
1762: $ PCSetType(pc,"my_solver")
1763: or at runtime via the option
1764: $ -pc_type my_solver
1766: Level: advanced
1768: .seealso: `PC`, `PCType`, `PCRegisterAll()`
1769: @*/
1770: PetscErrorCode PCRegister(const char sname[], PetscErrorCode (*function)(PC))
1771: {
1772: PCInitializePackage();
1773: PetscFunctionListAdd(&PCList, sname, function);
1774: return 0;
1775: }
1777: static PetscErrorCode MatMult_PC(Mat A, Vec X, Vec Y)
1778: {
1779: PC pc;
1781: MatShellGetContext(A, &pc);
1782: PCApply(pc, X, Y);
1783: return 0;
1784: }
1786: /*@
1787: PCComputeOperator - Computes the explicit preconditioned operator.
1789: Collective on pc
1791: Input Parameters:
1792: + pc - the preconditioner object
1793: - mattype - the matrix type to be used for the operator
1795: Output Parameter:
1796: . mat - the explicit preconditioned operator
1798: Note:
1799: This computation is done by applying the operators to columns of the identity matrix.
1800: This routine is costly in general, and is recommended for use only with relatively small systems.
1801: Currently, this routine uses a dense matrix format when mattype == NULL
1803: Level: advanced
1805: .seealso: `PC`, `KSPComputeOperator()`, `MatType`
1807: @*/
1808: PetscErrorCode PCComputeOperator(PC pc, MatType mattype, Mat *mat)
1809: {
1810: PetscInt N, M, m, n;
1811: Mat A, Apc;
1815: PCGetOperators(pc, &A, NULL);
1816: MatGetLocalSize(A, &m, &n);
1817: MatGetSize(A, &M, &N);
1818: MatCreateShell(PetscObjectComm((PetscObject)pc), m, n, M, N, pc, &Apc);
1819: MatShellSetOperation(Apc, MATOP_MULT, (void (*)(void))MatMult_PC);
1820: MatComputeOperator(Apc, mattype, mat);
1821: MatDestroy(&Apc);
1822: return 0;
1823: }
1825: /*@
1826: PCSetCoordinates - sets the coordinates of all the nodes on the local process
1828: Collective on pc
1830: Input Parameters:
1831: + pc - the solver context
1832: . dim - the dimension of the coordinates 1, 2, or 3
1833: . nloc - the blocked size of the coordinates array
1834: - coords - the coordinates array
1836: Level: intermediate
1838: Note:
1839: coords is an array of the dim coordinates for the nodes on
1840: the local processor, of size dim*nloc.
1841: If there are 108 equation on a processor
1842: for a displacement finite element discretization of elasticity (so
1843: that there are nloc = 36 = 108/3 nodes) then the array must have 108
1844: double precision values (ie, 3 * 36). These x y z coordinates
1845: should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x,
1846: ... , N-1.z ].
1848: .seealso: `PC`, `MatSetNearNullSpace()`
1849: @*/
1850: PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal coords[])
1851: {
1854: PetscTryMethod(pc, "PCSetCoordinates_C", (PC, PetscInt, PetscInt, PetscReal *), (pc, dim, nloc, coords));
1855: return 0;
1856: }
1858: /*@
1859: PCGetInterpolations - Gets interpolation matrices for all levels (except level 0)
1861: Logically Collective on pc
1863: Input Parameter:
1864: . pc - the precondition context
1866: Output Parameters:
1867: + num_levels - the number of levels
1868: - interpolations - the interpolation matrices (size of num_levels-1)
1870: Level: advanced
1872: Developer Note:
1873: Why is this here instead of in `PCMG` etc?
1875: .seealso: `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetInterpolation()`, `PCGetCoarseOperators()`
1876: @*/
1877: PetscErrorCode PCGetInterpolations(PC pc, PetscInt *num_levels, Mat *interpolations[])
1878: {
1882: PetscUseMethod(pc, "PCGetInterpolations_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, interpolations));
1883: return 0;
1884: }
1886: /*@
1887: PCGetCoarseOperators - Gets coarse operator matrices for all levels (except the finest level)
1889: Logically Collective on pc
1891: Input Parameter:
1892: . pc - the precondition context
1894: Output Parameters:
1895: + num_levels - the number of levels
1896: - coarseOperators - the coarse operator matrices (size of num_levels-1)
1898: Level: advanced
1900: Developer Note:
1901: Why is this here instead of in `PCMG` etc?
1903: .seealso: `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
1904: @*/
1905: PetscErrorCode PCGetCoarseOperators(PC pc, PetscInt *num_levels, Mat *coarseOperators[])
1906: {
1910: PetscUseMethod(pc, "PCGetCoarseOperators_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, coarseOperators));
1911: return 0;
1912: }