Actual source code: iterativ.c
1: /*
2: This file contains some simple default routines.
3: These routines should be SHORT, since they will be included in every
4: executable image that uses the iterative routines (note that, through
5: the registry system, we provide a way to load only the truly necessary
6: files)
7: */
8: #include <petsc/private/kspimpl.h>
9: #include <petscdmshell.h>
10: #include <petscdraw.h>
12: /*@
13: KSPGetResidualNorm - Gets the last (possibly approximate and/or preconditioned) residual norm that has been computed.
15: Not Collective
17: Input Parameter:
18: . ksp - the iterative context
20: Output Parameter:
21: . rnorm - residual norm
23: Level: intermediate
25: Note:
26: For some methods, such as `KSPGMRES`, the norm is not computed directly from the residual.
28: The type of norm used by the method can be controlled with `KSPSetNormType()`
30: .seealso: [](chapter_ksp), `KSP`, `KSPSetNormType()`, `KSPBuildResidual()`, `KSPNormType`
31: @*/
32: PetscErrorCode KSPGetResidualNorm(KSP ksp, PetscReal *rnorm)
33: {
34: PetscFunctionBegin;
37: *rnorm = ksp->rnorm;
38: PetscFunctionReturn(PETSC_SUCCESS);
39: }
41: /*@
42: KSPGetIterationNumber - Gets the current iteration number; if the `KSPSolve()` is complete, returns the number of iterations used.
44: Not Collective
46: Input Parameter:
47: . ksp - the iterative context
49: Output Parameter:
50: . its - number of iterations
52: Level: intermediate
54: Note:
55: During the ith iteration this returns i-1
57: .seealso: [](chapter_ksp), `KSP`, `KSPGetResidualNorm()`, `KSPBuildResidual()`, `KSPGetResidualNorm()`, `KSPGetTotalIterations()`
58: @*/
59: PetscErrorCode KSPGetIterationNumber(KSP ksp, PetscInt *its)
60: {
61: PetscFunctionBegin;
64: *its = ksp->its;
65: PetscFunctionReturn(PETSC_SUCCESS);
66: }
68: /*@
69: KSPGetTotalIterations - Gets the total number of iterations this `KSP` object has performed since was created, counted over all linear solves
71: Not Collective
73: Input Parameter:
74: . ksp - the iterative context
76: Output Parameter:
77: . its - total number of iterations
79: Level: intermediate
81: Note:
82: Use `KSPGetIterationNumber()` to get the count for the most recent solve only
83: If this is called within a `KSPSolve()` (such as in a `KSPMonitor` routine) then it does not include iterations within that current solve
85: .seealso: [](chapter_ksp), `KSP`, `KSPBuildResidual()`, `KSPGetResidualNorm()`, `KSPGetIterationNumber()`
86: @*/
87: PetscErrorCode KSPGetTotalIterations(KSP ksp, PetscInt *its)
88: {
89: PetscFunctionBegin;
92: *its = ksp->totalits;
93: PetscFunctionReturn(PETSC_SUCCESS);
94: }
96: /*@C
97: KSPMonitorResidual - Print the (possibly preconditioned) residual norm at each iteration of an iterative solver.
99: Collective
101: Input Parameters:
102: + ksp - iterative context
103: . n - iteration number
104: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
105: - vf - The viewer context
107: Options Database Key:
108: . -ksp_monitor - Activates `KSPMonitorResidual()`
110: Level: intermediate
112: Note:
113: For some methods, such as `KSPGMRES`, the norm is not computed directly from the residual.
115: The type of norm used by the method can be controlled with `KSPSetNormType()`
117: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
118: to be used during the KSP solve.
120: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidualDraw()`, `KSPMonitorResidualDrawLG()`,
121: `KSPMonitorResidualRange()`, `KSPMonitorTrueResidualDraw()`, `KSPMonitorTrueResidualDrawLG()`, `KSPMonitorTrueResidualMax()`,
122: `KSPMonitorSingularValue()`, `KSPMonitorSolutionDrawLG()`, `KSPMonitorSolutionDraw()`, `KSPMonitorSolution()`,
123: `KSPMonitorErrorDrawLG()`, `KSPMonitorErrorDraw()`, KSPMonitorError()`
124: @*/
125: PetscErrorCode KSPMonitorResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
126: {
127: PetscViewer viewer = vf->viewer;
128: PetscViewerFormat format = vf->format;
129: PetscInt tablevel;
130: const char *prefix;
132: PetscFunctionBegin;
134: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
135: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
136: PetscCall(PetscViewerPushFormat(viewer, format));
137: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
138: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
139: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm %14.12e \n", n, (double)rnorm));
140: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
141: PetscCall(PetscViewerPopFormat(viewer));
142: PetscFunctionReturn(PETSC_SUCCESS);
143: }
145: /*@C
146: KSPMonitorResidualDraw - Plots the (possibly preconditioned) residual at each iteration of an iterative solver.
148: Collective
150: Input Parameters:
151: + ksp - iterative context
152: . n - iteration number
153: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
154: - vf - The viewer context
156: Options Database Key:
157: . -ksp_monitor draw - Activates `KSPMonitorResidualDraw()`
159: Level: intermediate
161: Note:
162: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
163: to be used during the `KSP` solve.
165: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidual()`, `KSPMonitorResidualDrawLG()`
166: @*/
167: PetscErrorCode KSPMonitorResidualDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
168: {
169: PetscViewer viewer = vf->viewer;
170: PetscViewerFormat format = vf->format;
171: Vec r;
173: PetscFunctionBegin;
175: PetscCall(PetscViewerPushFormat(viewer, format));
176: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
177: PetscCall(PetscObjectSetName((PetscObject)r, "Residual"));
178: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", (PetscObject)ksp));
179: PetscCall(VecView(r, viewer));
180: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", NULL));
181: PetscCall(VecDestroy(&r));
182: PetscCall(PetscViewerPopFormat(viewer));
183: PetscFunctionReturn(PETSC_SUCCESS);
184: }
186: /*@C
187: KSPMonitorResidualDrawLG - Plots the (possibly preconditioned) residual norm at each iteration of an iterative solver.
189: Collective
191: Input Parameters:
192: + ksp - iterative context
193: . n - iteration number
194: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
195: - vf - The viewer context
197: Options Database Key:
198: . -ksp_monitor draw::draw_lg - Activates `KSPMonitorResidualDrawLG()`
200: Level: intermediate
202: Notes:
203: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
204: to be used during the `KSP` solve.
206: Use `KSPMonitorResidualDrawLGCreate()` to create the context used with this monitor
208: .seealso: [](chapter_ksp), `KSP`, `PETSCVIEWERDRAW`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidualDraw()`, `KSPMonitorResidual()`
209: @*/
210: PetscErrorCode KSPMonitorResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
211: {
212: PetscViewer viewer = vf->viewer;
213: PetscViewerFormat format = vf->format;
214: PetscDrawLG lg = vf->lg;
215: KSPConvergedReason reason;
216: PetscReal x, y;
218: PetscFunctionBegin;
221: PetscCall(PetscViewerPushFormat(viewer, format));
222: if (!n) PetscCall(PetscDrawLGReset(lg));
223: x = (PetscReal)n;
224: if (rnorm > 0.0) y = PetscLog10Real(rnorm);
225: else y = -15.0;
226: PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
227: PetscCall(KSPGetConvergedReason(ksp, &reason));
228: if (n <= 20 || !(n % 5) || reason) {
229: PetscCall(PetscDrawLGDraw(lg));
230: PetscCall(PetscDrawLGSave(lg));
231: }
232: PetscCall(PetscViewerPopFormat(viewer));
233: PetscFunctionReturn(PETSC_SUCCESS);
234: }
236: /*@C
237: KSPMonitorResidualDrawLGCreate - Creates the context for the (possibly preconditioned) residual norm monitor `KSPMonitorResidualDrawLG()`
239: Collective
241: Input Parameters:
242: + viewer - The `PetscViewer` of type `PETSCVIEWERDRAW`
243: . format - The viewer format
244: - ctx - An optional user context
246: Output Parameter:
247: . vf - The viewer context
249: Level: intermediate
251: .seealso: [](chapter_ksp), `KSP`, `PETSCVIEWERDRAW`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidualDrawLG()`,
252: `PetscViewerFormat`, `PetscViewer`, `PetscViewerAndFormat`
253: @*/
254: PetscErrorCode KSPMonitorResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
255: {
256: PetscFunctionBegin;
257: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
258: (*vf)->data = ctx;
259: PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Residual Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg));
260: PetscFunctionReturn(PETSC_SUCCESS);
261: }
263: /*
264: This is the same as KSPMonitorResidual() except it prints fewer digits of the residual as the residual gets smaller.
265: This is because the later digits are meaningless and are often different on different machines; by using this routine different
266: machines will usually generate the same output.
268: Deprecated: Intentionally has no manual page
269: */
270: PetscErrorCode KSPMonitorResidualShort(KSP ksp, PetscInt its, PetscReal fnorm, PetscViewerAndFormat *vf)
271: {
272: PetscViewer viewer = vf->viewer;
273: PetscViewerFormat format = vf->format;
274: PetscInt tablevel;
275: const char *prefix;
277: PetscFunctionBegin;
279: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
280: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
281: PetscCall(PetscViewerPushFormat(viewer, format));
282: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
283: if (its == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
284: if (fnorm > 1.e-9) PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm %g \n", its, (double)fnorm));
285: else if (fnorm > 1.e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm %5.3e \n", its, (double)fnorm));
286: else PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm < 1.e-11\n", its));
287: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
288: PetscCall(PetscViewerPopFormat(viewer));
289: PetscFunctionReturn(PETSC_SUCCESS);
290: }
292: PetscErrorCode KSPMonitorRange_Private(KSP ksp, PetscInt it, PetscReal *per)
293: {
294: Vec resid;
295: const PetscScalar *r;
296: PetscReal rmax, pwork;
297: PetscInt i, n, N;
299: PetscFunctionBegin;
300: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &resid));
301: PetscCall(VecNorm(resid, NORM_INFINITY, &rmax));
302: PetscCall(VecGetLocalSize(resid, &n));
303: PetscCall(VecGetSize(resid, &N));
304: PetscCall(VecGetArrayRead(resid, &r));
305: pwork = 0.0;
306: for (i = 0; i < n; ++i) pwork += (PetscAbsScalar(r[i]) > .20 * rmax);
307: PetscCall(VecRestoreArrayRead(resid, &r));
308: PetscCall(VecDestroy(&resid));
309: PetscCall(MPIU_Allreduce(&pwork, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ksp)));
310: *per = *per / N;
311: PetscFunctionReturn(PETSC_SUCCESS);
312: }
314: /*@C
315: KSPMonitorResidualRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value.
317: Collective
319: Input Parameters:
320: + ksp - iterative context
321: . it - iteration number
322: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
323: - vf - The viewer context
325: Options Database Key:
326: . -ksp_monitor_range - Activates `KSPMonitorResidualRange()`
328: Level: intermediate
330: Note:
331: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
332: to be used during the `KSP` solve.
334: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`
335: @*/
336: PetscErrorCode KSPMonitorResidualRange(KSP ksp, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf)
337: {
338: static PetscReal prev;
339: PetscViewer viewer = vf->viewer;
340: PetscViewerFormat format = vf->format;
341: PetscInt tablevel;
342: const char *prefix;
343: PetscReal perc, rel;
345: PetscFunctionBegin;
347: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
348: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
349: PetscCall(PetscViewerPushFormat(viewer, format));
350: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
351: if (!it) prev = rnorm;
352: if (it == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
353: PetscCall(KSPMonitorRange_Private(ksp, it, &perc));
354: rel = (prev - rnorm) / prev;
355: prev = rnorm;
356: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP preconditioned resid norm %14.12e Percent values above 20 percent of maximum %5.2f relative decrease %5.2e ratio %5.2e \n", it, (double)rnorm, (double)(100.0 * perc), (double)rel, (double)(rel / perc)));
357: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
358: PetscCall(PetscViewerPopFormat(viewer));
359: PetscFunctionReturn(PETSC_SUCCESS);
360: }
362: /*@C
363: KSPMonitorTrueResidual - Prints the true residual norm, as well as the (possibly preconditioned) approximate residual norm, at each iteration of an iterative solver.
365: Collective
367: Input Parameters:
368: + ksp - iterative context
369: . n - iteration number
370: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
371: - vf - The viewer context
373: Options Database Key:
374: . -ksp_monitor_true_residual - Activates `KSPMonitorTrueResidual()`
376: Level: intermediate
378: Notes:
379: When using right preconditioning, these values are equivalent.
381: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
382: to be used during the `KSP` solve.
384: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`, `PetscViewerAndFormat`
385: @*/
386: PetscErrorCode KSPMonitorTrueResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
387: {
388: PetscViewer viewer = vf->viewer;
389: PetscViewerFormat format = vf->format;
390: Vec r;
391: PetscReal truenorm, bnorm;
392: char normtype[256];
393: PetscInt tablevel;
394: const char *prefix;
396: PetscFunctionBegin;
398: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
399: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
400: PetscCall(PetscStrncpy(normtype, KSPNormTypes[ksp->normtype], sizeof(normtype)));
401: PetscCall(PetscStrtolower(normtype));
402: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
403: PetscCall(VecNorm(r, NORM_2, &truenorm));
404: PetscCall(VecNorm(ksp->vec_rhs, NORM_2, &bnorm));
405: PetscCall(VecDestroy(&r));
407: PetscCall(PetscViewerPushFormat(viewer, format));
408: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
409: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
410: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP %s resid norm %14.12e true resid norm %14.12e ||r(i)||/||b|| %14.12e\n", n, normtype, (double)rnorm, (double)truenorm, (double)(truenorm / bnorm)));
411: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
412: PetscCall(PetscViewerPopFormat(viewer));
413: PetscFunctionReturn(PETSC_SUCCESS);
414: }
416: /*@C
417: KSPMonitorTrueResidualDraw - Plots the true residual at each iteration of an iterative solver.
419: Collective
421: Input Parameters:
422: + ksp - iterative context
423: . n - iteration number
424: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
425: - vf - The viewer context of type `PETSCVIEWERDRAW`
427: Options Database Key:
428: . -ksp_monitor_true_residual draw - Activates `KSPMonitorResidualDraw()`
430: Level: intermediate
432: Note:
433: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
434: to be used during the `KSP` solve.
436: .seealso: [](chapter_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidual()`,
437: `KSPMonitorTrueResidualDrawLG()`, `PetscViewerAndFormat`
438: @*/
439: PetscErrorCode KSPMonitorTrueResidualDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
440: {
441: PetscViewer viewer = vf->viewer;
442: PetscViewerFormat format = vf->format;
443: Vec r;
445: PetscFunctionBegin;
447: PetscCall(PetscViewerPushFormat(viewer, format));
448: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
449: PetscCall(PetscObjectSetName((PetscObject)r, "Residual"));
450: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", (PetscObject)ksp));
451: PetscCall(VecView(r, viewer));
452: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", NULL));
453: PetscCall(VecDestroy(&r));
454: PetscCall(PetscViewerPopFormat(viewer));
455: PetscFunctionReturn(PETSC_SUCCESS);
456: }
458: /*@C
459: KSPMonitorTrueResidualDrawLG - Plots the true residual norm at each iteration of an iterative solver.
461: Collective
463: Input Parameters:
464: + ksp - iterative context
465: . n - iteration number
466: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
467: - vf - The viewer context
469: Options Database Key:
470: . -ksp_monitor_true_residual draw::draw_lg - Activates `KSPMonitorTrueResidualDrawLG()`
472: Level: intermediate
474: Notes:
475: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
476: to be used during the `KSP` solve.
478: Call `KSPMonitorTrueResidualDrawLGCreate()` to create the context needed for this monitor
480: .seealso: [](chapter_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorTrueResidualDraw()`, `KSPMonitorResidual`,
481: `KSPMonitorTrueResidualDrawLGCreate()`
482: @*/
483: PetscErrorCode KSPMonitorTrueResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
484: {
485: PetscViewer viewer = vf->viewer;
486: PetscViewerFormat format = vf->format;
487: PetscDrawLG lg = vf->lg;
488: Vec r;
489: KSPConvergedReason reason;
490: PetscReal truenorm, x[2], y[2];
492: PetscFunctionBegin;
495: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
496: PetscCall(VecNorm(r, NORM_2, &truenorm));
497: PetscCall(VecDestroy(&r));
498: PetscCall(PetscViewerPushFormat(viewer, format));
499: if (!n) PetscCall(PetscDrawLGReset(lg));
500: x[0] = (PetscReal)n;
501: if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
502: else y[0] = -15.0;
503: x[1] = (PetscReal)n;
504: if (truenorm > 0.0) y[1] = PetscLog10Real(truenorm);
505: else y[1] = -15.0;
506: PetscCall(PetscDrawLGAddPoint(lg, x, y));
507: PetscCall(KSPGetConvergedReason(ksp, &reason));
508: if (n <= 20 || !(n % 5) || reason) {
509: PetscCall(PetscDrawLGDraw(lg));
510: PetscCall(PetscDrawLGSave(lg));
511: }
512: PetscCall(PetscViewerPopFormat(viewer));
513: PetscFunctionReturn(PETSC_SUCCESS);
514: }
516: /*@C
517: KSPMonitorTrueResidualDrawLGCreate - Creates the context for the true residual monitor `KSPMonitorTrueResidualDrawLG()`
519: Collective
521: Input Parameters:
522: + viewer - The `PetscViewer` of type `PETSCVIEWERDRAW`
523: . format - The viewer format
524: - ctx - An optional user context
526: Output Parameter:
527: . vf - The viewer context
529: Level: intermediate
531: .seealso: [](chapter_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `PetscViewerAndFormat`
532: @*/
533: PetscErrorCode KSPMonitorTrueResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
534: {
535: const char *names[] = {"preconditioned", "true"};
537: PetscFunctionBegin;
538: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
539: (*vf)->data = ctx;
540: PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg));
541: PetscFunctionReturn(PETSC_SUCCESS);
542: }
544: /*@C
545: KSPMonitorTrueResidualMax - Prints the true residual max norm at each iteration of an iterative solver.
547: Collective
549: Input Parameters:
550: + ksp - iterative context
551: . n - iteration number
552: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
553: - vf - The viewer context
555: Options Database Key:
556: . -ksp_monitor_true_residual_max - Activates `KSPMonitorTrueResidualMax()`
558: Level: intermediate
560: Note:
561: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
562: to be used during the `KSP` solve.
564: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`
565: @*/
566: PetscErrorCode KSPMonitorTrueResidualMax(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
567: {
568: PetscViewer viewer = vf->viewer;
569: PetscViewerFormat format = vf->format;
570: Vec r;
571: PetscReal truenorm, bnorm;
572: char normtype[256];
573: PetscInt tablevel;
574: const char *prefix;
576: PetscFunctionBegin;
578: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
579: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
580: PetscCall(PetscStrncpy(normtype, KSPNormTypes[ksp->normtype], sizeof(normtype)));
581: PetscCall(PetscStrtolower(normtype));
582: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
583: PetscCall(VecNorm(r, NORM_INFINITY, &truenorm));
584: PetscCall(VecNorm(ksp->vec_rhs, NORM_INFINITY, &bnorm));
585: PetscCall(VecDestroy(&r));
587: PetscCall(PetscViewerPushFormat(viewer, format));
588: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
589: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
590: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP %s true resid max norm %14.12e ||r(i)||/||b|| %14.12e\n", n, normtype, (double)truenorm, (double)(truenorm / bnorm)));
591: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
592: PetscCall(PetscViewerPopFormat(viewer));
593: PetscFunctionReturn(PETSC_SUCCESS);
594: }
596: /*@C
597: KSPMonitorError - Prints the error norm, as well as the (possibly preconditioned) residual norm, at each iteration of an iterative solver.
599: Collective
601: Input Parameters:
602: + ksp - iterative context
603: . n - iteration number
604: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
605: - vf - The viewer context
607: Options Database Key:
608: . -ksp_monitor_error - Activates `KSPMonitorError()`
610: Level: intermediate
612: Note:
613: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
614: to be used during the `KSP` solve.
616: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`
617: @*/
618: PetscErrorCode KSPMonitorError(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
619: {
620: PetscViewer viewer = vf->viewer;
621: PetscViewerFormat format = vf->format;
622: DM dm;
623: Vec sol;
624: PetscReal *errors;
625: PetscInt Nf, f;
626: PetscInt tablevel;
627: const char *prefix;
629: PetscFunctionBegin;
631: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
632: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
633: PetscCall(KSPGetDM(ksp, &dm));
634: PetscCall(DMGetNumFields(dm, &Nf));
635: PetscCall(DMGetGlobalVector(dm, &sol));
636: PetscCall(KSPBuildSolution(ksp, sol, NULL));
637: /* TODO: Make a different monitor that flips sign for SNES, Newton system is A dx = -b, so we need to negate the solution */
638: PetscCall(VecScale(sol, -1.0));
639: PetscCall(PetscCalloc1(Nf, &errors));
640: PetscCall(DMComputeError(dm, sol, errors, NULL));
642: PetscCall(PetscViewerPushFormat(viewer, format));
643: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
644: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Error norms for %s solve.\n", prefix));
645: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Error norm %s", n, Nf > 1 ? "[" : ""));
646: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
647: for (f = 0; f < Nf; ++f) {
648: if (f > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
649: PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)errors[f]));
650: }
651: PetscCall(PetscViewerASCIIPrintf(viewer, "%s resid norm %14.12e\n", Nf > 1 ? "]" : "", (double)rnorm));
652: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
653: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
654: PetscCall(PetscViewerPopFormat(viewer));
655: PetscCall(DMRestoreGlobalVector(dm, &sol));
656: PetscFunctionReturn(PETSC_SUCCESS);
657: }
659: /*@C
660: KSPMonitorErrorDraw - Plots the error at each iteration of an iterative solver.
662: Collective
664: Input Parameters:
665: + ksp - iterative context
666: . n - iteration number
667: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
668: - vf - The viewer context
670: Options Database Key:
671: . -ksp_monitor_error draw - Activates `KSPMonitorErrorDraw()`
673: Level: intermediate
675: Note:
676: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
677: to be used during the `KSP` solve.
679: .seealso: [](chapter_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDrawLG()`
680: @*/
681: PetscErrorCode KSPMonitorErrorDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
682: {
683: PetscViewer viewer = vf->viewer;
684: PetscViewerFormat format = vf->format;
685: DM dm;
686: Vec sol, e;
688: PetscFunctionBegin;
690: PetscCall(PetscViewerPushFormat(viewer, format));
691: PetscCall(KSPGetDM(ksp, &dm));
692: PetscCall(DMGetGlobalVector(dm, &sol));
693: PetscCall(KSPBuildSolution(ksp, sol, NULL));
694: PetscCall(DMComputeError(dm, sol, NULL, &e));
695: PetscCall(PetscObjectSetName((PetscObject)e, "Error"));
696: PetscCall(PetscObjectCompose((PetscObject)e, "__Vec_bc_zero__", (PetscObject)ksp));
697: PetscCall(VecView(e, viewer));
698: PetscCall(PetscObjectCompose((PetscObject)e, "__Vec_bc_zero__", NULL));
699: PetscCall(VecDestroy(&e));
700: PetscCall(DMRestoreGlobalVector(dm, &sol));
701: PetscCall(PetscViewerPopFormat(viewer));
702: PetscFunctionReturn(PETSC_SUCCESS);
703: }
705: /*@C
706: KSPMonitorErrorDrawLG - Plots the error and residual norm at each iteration of an iterative solver.
708: Collective
710: Input Parameters:
711: + ksp - iterative context
712: . n - iteration number
713: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
714: - vf - The viewer context
716: Options Database Key:
717: . -ksp_monitor_error draw::draw_lg - Activates `KSPMonitorTrueResidualDrawLG()`
719: Level: intermediate
721: Notes:
722: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
723: to be used during the `KSP` solve.
725: Call `KSPMonitorErrorDrawLGCreate()` to create the context used with this monitor
727: .seealso: [](chapter_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDraw()`
728: @*/
729: PetscErrorCode KSPMonitorErrorDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
730: {
731: PetscViewer viewer = vf->viewer;
732: PetscViewerFormat format = vf->format;
733: PetscDrawLG lg = vf->lg;
734: DM dm;
735: Vec sol;
736: KSPConvergedReason reason;
737: PetscReal *x, *errors;
738: PetscInt Nf, f;
740: PetscFunctionBegin;
743: PetscCall(KSPGetDM(ksp, &dm));
744: PetscCall(DMGetNumFields(dm, &Nf));
745: PetscCall(DMGetGlobalVector(dm, &sol));
746: PetscCall(KSPBuildSolution(ksp, sol, NULL));
747: /* TODO: Make a different monitor that flips sign for SNES, Newton system is A dx = -b, so we need to negate the solution */
748: PetscCall(VecScale(sol, -1.0));
749: PetscCall(PetscCalloc2(Nf + 1, &x, Nf + 1, &errors));
750: PetscCall(DMComputeError(dm, sol, errors, NULL));
752: PetscCall(PetscViewerPushFormat(viewer, format));
753: if (!n) PetscCall(PetscDrawLGReset(lg));
754: for (f = 0; f < Nf; ++f) {
755: x[f] = (PetscReal)n;
756: errors[f] = errors[f] > 0.0 ? PetscLog10Real(errors[f]) : -15.;
757: }
758: x[Nf] = (PetscReal)n;
759: errors[Nf] = rnorm > 0.0 ? PetscLog10Real(rnorm) : -15.;
760: PetscCall(PetscDrawLGAddPoint(lg, x, errors));
761: PetscCall(KSPGetConvergedReason(ksp, &reason));
762: if (n <= 20 || !(n % 5) || reason) {
763: PetscCall(PetscDrawLGDraw(lg));
764: PetscCall(PetscDrawLGSave(lg));
765: }
766: PetscCall(PetscViewerPopFormat(viewer));
767: PetscFunctionReturn(PETSC_SUCCESS);
768: }
770: /*@C
771: KSPMonitorErrorDrawLGCreate - Creates the context for the error and preconditioned residual plotter `KSPMonitorErrorDrawLG()`
773: Collective
775: Input Parameters:
776: + viewer - The `PetscViewer`
777: . format - The viewer format
778: - ctx - An optional user context
780: Output Parameter:
781: . vf - The viewer context
783: Level: intermediate
785: .seealso: [](chapter_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDrawLG()`, `KSPMonitorErrorDrawLG()`
786: @*/
787: PetscErrorCode KSPMonitorErrorDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
788: {
789: KSP ksp = (KSP)ctx;
790: DM dm;
791: char **names;
792: PetscInt Nf, f;
794: PetscFunctionBegin;
795: PetscCall(KSPGetDM(ksp, &dm));
796: PetscCall(DMGetNumFields(dm, &Nf));
797: PetscCall(PetscMalloc1(Nf + 1, &names));
798: for (f = 0; f < Nf; ++f) {
799: PetscObject disc;
800: const char *fname;
801: char lname[PETSC_MAX_PATH_LEN];
803: PetscCall(DMGetField(dm, f, NULL, &disc));
804: PetscCall(PetscObjectGetName(disc, &fname));
805: PetscCall(PetscStrncpy(lname, fname, PETSC_MAX_PATH_LEN));
806: PetscCall(PetscStrlcat(lname, " Error", PETSC_MAX_PATH_LEN));
807: PetscCall(PetscStrallocpy(lname, &names[f]));
808: }
809: PetscCall(PetscStrallocpy("residual", &names[Nf]));
810: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
811: (*vf)->data = ctx;
812: PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Error Norm", Nf + 1, (const char **)names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg));
813: for (f = 0; f <= Nf; ++f) PetscCall(PetscFree(names[f]));
814: PetscCall(PetscFree(names));
815: PetscFunctionReturn(PETSC_SUCCESS);
816: }
818: /*@C
819: KSPMonitorSolution - Print the solution norm at each iteration of an iterative solver.
821: Collective
823: Input Parameters:
824: + ksp - iterative context
825: . n - iteration number
826: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
827: - vf - The viewer context
829: Options Database Key:
830: . -ksp_monitor_solution - Activates `KSPMonitorSolution()`
832: Level: intermediate
834: Note:
835: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
836: to be used during the `KSP` solve.
838: .seealso: [](chapter_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
839: @*/
840: PetscErrorCode KSPMonitorSolution(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
841: {
842: PetscViewer viewer = vf->viewer;
843: PetscViewerFormat format = vf->format;
844: Vec x;
845: PetscReal snorm;
846: PetscInt tablevel;
847: const char *prefix;
849: PetscFunctionBegin;
851: PetscCall(KSPBuildSolution(ksp, NULL, &x));
852: PetscCall(VecNorm(x, NORM_2, &snorm));
853: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
854: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
855: PetscCall(PetscViewerPushFormat(viewer, format));
856: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
857: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Solution norms for %s solve.\n", prefix));
858: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Solution norm %14.12e \n", n, (double)snorm));
859: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
860: PetscCall(PetscViewerPopFormat(viewer));
861: PetscFunctionReturn(PETSC_SUCCESS);
862: }
864: /*@C
865: KSPMonitorSolutionDraw - Plots the solution at each iteration of an iterative solver.
867: Collective
869: Input Parameters:
870: + ksp - iterative context
871: . n - iteration number
872: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
873: - vf - The viewer context
875: Options Database Key:
876: . -ksp_monitor_solution draw - Activates `KSPMonitorSolutionDraw()`
878: Level: intermediate
880: Note:
881: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
882: to be used during the `KSP` solve.
884: .seealso: [](chapter_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
885: @*/
886: PetscErrorCode KSPMonitorSolutionDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
887: {
888: PetscViewer viewer = vf->viewer;
889: PetscViewerFormat format = vf->format;
890: Vec x;
892: PetscFunctionBegin;
894: PetscCall(KSPBuildSolution(ksp, NULL, &x));
895: PetscCall(PetscViewerPushFormat(viewer, format));
896: PetscCall(PetscObjectSetName((PetscObject)x, "Solution"));
897: PetscCall(PetscObjectCompose((PetscObject)x, "__Vec_bc_zero__", (PetscObject)ksp));
898: PetscCall(VecView(x, viewer));
899: PetscCall(PetscObjectCompose((PetscObject)x, "__Vec_bc_zero__", NULL));
900: PetscCall(PetscViewerPopFormat(viewer));
901: PetscFunctionReturn(PETSC_SUCCESS);
902: }
904: /*@C
905: KSPMonitorSolutionDrawLG - Plots the solution norm at each iteration of an iterative solver.
907: Collective
909: Input Parameters:
910: + ksp - iterative context
911: . n - iteration number
912: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
913: - vf - The viewer context
915: Options Database Key:
916: . -ksp_monitor_solution draw::draw_lg - Activates `KSPMonitorSolutionDrawLG()`
918: Level: intermediate
920: Notes:
921: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
922: to be used during the `KSP` solve.
924: Call `KSPMonitorSolutionDrawLGCreate()` to create the context needed with this monitor
926: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorSolutionDrawLGCreate()`
927: @*/
928: PetscErrorCode KSPMonitorSolutionDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
929: {
930: PetscViewer viewer = vf->viewer;
931: PetscViewerFormat format = vf->format;
932: PetscDrawLG lg = vf->lg;
933: Vec u;
934: KSPConvergedReason reason;
935: PetscReal snorm, x, y;
937: PetscFunctionBegin;
940: PetscCall(KSPBuildSolution(ksp, NULL, &u));
941: PetscCall(VecNorm(u, NORM_2, &snorm));
942: PetscCall(PetscViewerPushFormat(viewer, format));
943: if (!n) PetscCall(PetscDrawLGReset(lg));
944: x = (PetscReal)n;
945: if (snorm > 0.0) y = PetscLog10Real(snorm);
946: else y = -15.0;
947: PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
948: PetscCall(KSPGetConvergedReason(ksp, &reason));
949: if (n <= 20 || !(n % 5) || reason) {
950: PetscCall(PetscDrawLGDraw(lg));
951: PetscCall(PetscDrawLGSave(lg));
952: }
953: PetscCall(PetscViewerPopFormat(viewer));
954: PetscFunctionReturn(PETSC_SUCCESS);
955: }
957: /*@C
958: KSPMonitorSolutionDrawLGCreate - Creates the context for the `KSP` monitor `KSPMonitorSolutionDrawLG()`
960: Collective
962: Input Parameters:
963: + viewer - The `PetscViewer`
964: . format - The viewer format
965: - ctx - An optional user context
967: Output Parameter:
968: . vf - The viewer context
970: Level: intermediate
972: Note:
973: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
974: to be used during the `KSP` solve.
976: .seealso: [](chapter_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
977: @*/
978: PetscErrorCode KSPMonitorSolutionDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
979: {
980: PetscFunctionBegin;
981: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
982: (*vf)->data = ctx;
983: PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Solution Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg));
984: PetscFunctionReturn(PETSC_SUCCESS);
985: }
987: /*@C
988: KSPMonitorSingularValue - Prints the two norm of the true residual and estimation of the extreme singular values of the preconditioned problem at each iteration.
990: Logically Collective
992: Input Parameters:
993: + ksp - the iterative context
994: . n - the iteration
995: . rnorm - the two norm of the residual
996: - vf - The viewer context
998: Options Database Key:
999: . -ksp_monitor_singular_value - Activates `KSPMonitorSingularValue()`
1001: Level: intermediate
1003: Notes:
1004: The `KSPCG` solver uses the Lanczos technique for eigenvalue computation,
1005: while `KSPGMRES` uses the Arnoldi technique; other iterative methods do
1006: not currently compute singular values.
1008: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
1009: to be used during the `KSP` solve.
1011: Call `KSPMonitorSingularValueCreate()` to create the context needed by this monitor
1013: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPComputeExtremeSingularValues()`, `KSPMonitorSingularValueCreate()`
1014: @*/
1015: PetscErrorCode KSPMonitorSingularValue(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
1016: {
1017: PetscViewer viewer = vf->viewer;
1018: PetscViewerFormat format = vf->format;
1019: PetscReal emin, emax;
1020: PetscInt tablevel;
1021: const char *prefix;
1023: PetscFunctionBegin;
1026: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
1027: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
1028: PetscCall(PetscViewerPushFormat(viewer, format));
1029: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
1030: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
1031: if (!ksp->calc_sings) {
1032: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm %14.12e \n", n, (double)rnorm));
1033: } else {
1034: PetscCall(KSPComputeExtremeSingularValues(ksp, &emax, &emin));
1035: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm %14.12e %% max %14.12e min %14.12e max/min %14.12e\n", n, (double)rnorm, (double)emax, (double)emin, (double)(emax / emin)));
1036: }
1037: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
1038: PetscCall(PetscViewerPopFormat(viewer));
1039: PetscFunctionReturn(PETSC_SUCCESS);
1040: }
1042: /*@C
1043: KSPMonitorSingularValueCreate - Creates the singular value monitor context needed by `KSPMonitorSingularValue()`
1045: Collective
1047: Input Parameters:
1048: + viewer - The PetscViewer
1049: . format - The viewer format
1050: - ctx - An optional user context
1052: Output Parameter:
1053: . vf - The viewer context
1055: Level: intermediate
1057: .seealso: [](chapter_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorSingularValue()`, `PetscViewer`
1058: @*/
1059: PetscErrorCode KSPMonitorSingularValueCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
1060: {
1061: KSP ksp = (KSP)ctx;
1063: PetscFunctionBegin;
1064: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
1065: (*vf)->data = ctx;
1066: PetscCall(KSPSetComputeSingularValues(ksp, PETSC_TRUE));
1067: PetscFunctionReturn(PETSC_SUCCESS);
1068: }
1070: /*@C
1071: KSPMonitorDynamicToleranceCreate - Creates the context used by `KSPMonitorDynamicTolerance()`
1073: Logically Collective
1075: Output Parameter:
1076: . ctx - a void pointer
1078: Options Database Key:
1079: . -sub_ksp_dynamic_tolerance <coef> - coefficient of dynamic tolerance for inner solver, default is 1.0
1081: Level: advanced
1083: Note:
1084: Use before calling `KSPMonitorSet()` with `KSPMonitorDynamicTolerance()`
1086: The default coefficient for the tolerance can be changed with `KSPMonitorDynamicToleranceSetCoefficient()`
1088: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceSetCoefficient()`
1089: @*/
1090: PetscErrorCode KSPMonitorDynamicToleranceCreate(void *ctx)
1091: {
1092: KSPDynTolCtx *scale;
1094: PetscFunctionBegin;
1095: PetscCall(PetscMalloc1(1, &scale));
1096: scale->bnrm = -1.0;
1097: scale->coef = 1.0;
1098: *(void **)ctx = scale;
1099: PetscFunctionReturn(PETSC_SUCCESS);
1100: }
1102: /*@C
1103: KSPMonitorDynamicToleranceSetCoefficient - Sets the coefficient in the context used by `KSPMonitorDynamicTolerance()`
1105: Logically Collective
1107: Output Parameters:
1108: + ctx - the context for `KSPMonitorDynamicTolerance()`
1109: - coeff - the coefficient, default is 1.0
1111: Options Database Key:
1112: . -sub_ksp_dynamic_tolerance <coef> - coefficient of dynamic tolerance for inner solver, default is 1.0
1114: Level: advanced
1116: Note:
1117: Use before calling `KSPMonitorSet()` and after `KSPMonitorDynamicToleranceCreate()`
1119: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceCreate()`
1120: @*/
1121: PetscErrorCode KSPMonitorDynamicToleranceSetCoefficient(void *ctx, PetscReal coeff)
1122: {
1123: KSPDynTolCtx *scale = (KSPDynTolCtx *)ctx;
1125: PetscFunctionBegin;
1126: scale->coef = coeff;
1127: PetscFunctionReturn(PETSC_SUCCESS);
1128: }
1130: /*@C
1131: KSPMonitorDynamicTolerance - A monitor that changes the inner tolerance of nested preconditioners in every outer iteration in an adaptive way.
1133: Collective
1135: Input Parameters:
1136: + ksp - iterative context
1137: . n - iteration number (not used)
1138: . fnorm - the current residual norm
1139: - ctx - context used by monitor
1141: Options Database Key:
1142: . -sub_ksp_dynamic_tolerance <coef> - coefficient of dynamic tolerance for inner solver, default is 1.0
1144: Level: advanced
1146: Notes:
1147: Applies for `PCKSP`, `PCBJACOBI`, and `PCDEFLATION` preconditioners
1149: This may be useful for a flexible preconditioned Krylov method, such as `KSPFGMRES`, [](sec_flexibleksp) to
1150: control the accuracy of the inner solves needed to guarantee convergence of the outer iterations.
1152: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
1153: to be used during the `KSP` solve.
1155: Use `KSPMonitorDynamicToleranceCreate()` and `KSPMonitorDynamicToleranceSetCoefficient()` to create the context needed by this
1156: monitor function.
1158: Pass the context and `KSPMonitorDynamicToleranceDestroy()` to `KSPMonitorSet()`
1160: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicToleranceCreate()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceSetCoefficient()`
1161: @*/
1162: PetscErrorCode KSPMonitorDynamicTolerance(KSP ksp, PetscInt its, PetscReal fnorm, void *dummy)
1163: {
1164: PC pc;
1165: PetscReal outer_rtol, outer_abstol, outer_dtol, inner_rtol;
1166: PetscInt outer_maxits, nksp, first, i;
1167: KSPDynTolCtx *scale = (KSPDynTolCtx *)dummy;
1168: KSP *subksp = NULL;
1169: KSP kspinner;
1170: PetscBool flg;
1172: PetscFunctionBegin;
1173: PetscCall(KSPGetPC(ksp, &pc));
1175: /* compute inner_rtol */
1176: if (scale->bnrm < 0.0) {
1177: Vec b;
1178: PetscCall(KSPGetRhs(ksp, &b));
1179: PetscCall(VecNorm(b, NORM_2, &(scale->bnrm)));
1180: }
1181: PetscCall(KSPGetTolerances(ksp, &outer_rtol, &outer_abstol, &outer_dtol, &outer_maxits));
1182: inner_rtol = PetscMin(scale->coef * scale->bnrm * outer_rtol / fnorm, 0.999);
1184: /* if pc is ksp */
1185: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCKSP, &flg));
1186: if (flg) {
1187: PetscCall(PCKSPGetKSP(pc, &kspinner));
1188: PetscCall(KSPSetTolerances(kspinner, inner_rtol, outer_abstol, outer_dtol, outer_maxits));
1189: PetscFunctionReturn(PETSC_SUCCESS);
1190: }
1192: /* if pc is bjacobi */
1193: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCBJACOBI, &flg));
1194: if (flg) {
1195: PetscCall(PCBJacobiGetSubKSP(pc, &nksp, &first, &subksp));
1196: if (subksp) {
1197: for (i = 0; i < nksp; i++) PetscCall(KSPSetTolerances(subksp[i], inner_rtol, outer_abstol, outer_dtol, outer_maxits));
1198: PetscFunctionReturn(PETSC_SUCCESS);
1199: }
1200: }
1202: /* if pc is deflation*/
1203: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCDEFLATION, &flg));
1204: if (flg) {
1205: PetscCall(PCDeflationGetCoarseKSP(pc, &kspinner));
1206: PetscCall(KSPSetTolerances(kspinner, inner_rtol, outer_abstol, outer_dtol, PETSC_DEFAULT));
1207: PetscFunctionReturn(PETSC_SUCCESS);
1208: }
1210: /* todo: dynamic tolerance may apply to other types of pc */
1211: PetscFunctionReturn(PETSC_SUCCESS);
1212: }
1214: /*@C
1215: KSPMonitorDynamicToleranceDestroy - Destroy the monitor context used in `KSPMonitorDynamicTolerance()`
1217: Input Parameter:
1218: . ctx - the monitor context
1220: Level: advanced
1222: Note:
1223: This is not called directly but is passed to `KSPMonitorSet()` along with `KSPMonitorDynamicTolerance()`
1225: .seealso: `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorSet()`, `KSPMonitorDynamicToleranceCreate()`
1226: @*/
1227: PetscErrorCode KSPMonitorDynamicToleranceDestroy(void **ctx)
1228: {
1229: PetscFunctionBegin;
1230: PetscCall(PetscFree(*ctx));
1231: PetscFunctionReturn(PETSC_SUCCESS);
1232: }
1234: /*@C
1235: KSPConvergedSkip - Convergence test that do not return as converged
1236: until the maximum number of iterations is reached.
1238: Collective
1240: Input Parameters:
1241: + ksp - iterative context
1242: . n - iteration number
1243: . rnorm - 2-norm residual value (may be estimated)
1244: - dummy - unused convergence context
1246: Output Parameter:
1247: . reason - `KSP_CONVERGED_ITERATING`, `KSP_CONVERGED_ITS`
1249: Level: advanced
1251: Notes:
1252: This should be used as the convergence test with the option
1253: `KSPSetNormType`(ksp,`KSP_NORM_NONE`), since norms of the residual are
1254: not computed. Convergence is then declared after the maximum number
1255: of iterations have been reached. Useful when one is using `KSPCG` or
1256: `KSPBCGS`. [](sec_flexibleksp)
1258: .seealso: [](chapter_ksp), `KSP`, `KSPCG`, `KSPBCGS`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPSetNormType()`, [](sec_flexibleksp),
1259: `KSPConvergedReason`
1260: @*/
1261: PetscErrorCode KSPConvergedSkip(KSP ksp, PetscInt n, PetscReal rnorm, KSPConvergedReason *reason, void *dummy)
1262: {
1263: PetscFunctionBegin;
1266: *reason = KSP_CONVERGED_ITERATING;
1267: if (n >= ksp->max_it) *reason = KSP_CONVERGED_ITS;
1268: PetscFunctionReturn(PETSC_SUCCESS);
1269: }
1271: /*@
1272: KSPSetConvergedNegativeCurvature - Allows to declare convergence and return `KSP_CONVERGED_NEG_CURVE` when negative curvature is detected
1274: Collective
1276: Input Parameters:
1277: + ksp - iterative context
1278: - flg - the Boolean value
1280: Options Database Key:
1281: . -ksp_converged_neg_curve <bool> - Declare convergence if negative curvature is detected
1283: Level: advanced
1285: Notes:
1286: This is currently used only by a subset of the Krylov solvers, namely `KSPCG`, `KSPSTCG`, `KSPQCG`, `KSPGLTR`, `KSPNASH`, and `KSPMINRES`.
1288: .seealso: [](chapter_ksp), `KSP`, `KSPConvergedReason`, `KSPGetConvergedNegativeCurvature()`
1289: @*/
1290: PetscErrorCode KSPSetConvergedNegativeCurvature(KSP ksp, PetscBool flg)
1291: {
1292: PetscFunctionBegin;
1295: ksp->converged_neg_curve = flg;
1296: PetscFunctionReturn(PETSC_SUCCESS);
1297: }
1299: /*@
1300: KSPGetConvergedNegativeCurvature - Get the flag to declare convergence if negative curvature is detected
1302: Collective
1304: Input Parameter:
1305: . ksp - iterative context
1307: Output Parameter:
1308: . flg - the Boolean value
1310: Level: advanced
1312: .seealso: [](chapter_ksp), `KSP`, `KSPConvergedReason`, `KSPSetConvergedNegativeCurvature()`
1313: @*/
1314: PetscErrorCode KSPGetConvergedNegativeCurvature(KSP ksp, PetscBool *flg)
1315: {
1316: PetscFunctionBegin;
1319: *flg = ksp->converged_neg_curve;
1320: PetscFunctionReturn(PETSC_SUCCESS);
1321: }
1323: /*@C
1324: KSPConvergedDefaultCreate - Creates and initializes the context used by the `KSPConvergedDefault()` function
1326: Not Collective
1328: Output Parameter:
1329: . ctx - convergence context
1331: Level: intermediate
1333: .seealso: [](chapter_ksp), `KSP`, `KSPConvergedDefault()`, `KSPConvergedDefaultDestroy()`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`,
1334: `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`,
1335: `KSPConvergedDefaultSetConvergedMaxits()`
1336: @*/
1337: PetscErrorCode KSPConvergedDefaultCreate(void **ctx)
1338: {
1339: KSPConvergedDefaultCtx *cctx;
1341: PetscFunctionBegin;
1342: PetscCall(PetscNew(&cctx));
1343: *ctx = cctx;
1344: PetscFunctionReturn(PETSC_SUCCESS);
1345: }
1347: /*@
1348: KSPConvergedDefaultSetUIRNorm - makes the default convergence test use || B*(b - A*(initial guess))||
1349: instead of || B*b ||. In the case of right preconditioner or if `KSPSetNormType`(ksp,`KSP_NORM_UNPRECONDITIONED`)
1350: is used there is no B in the above formula. UIRNorm is short for Use Initial Residual Norm.
1352: Collective
1354: Input Parameters:
1355: . ksp - iterative context
1357: Options Database Key:
1358: . -ksp_converged_use_initial_residual_norm <bool> - Use initial residual norm for computing relative convergence
1360: Level: intermediate
1362: Notes:
1363: Use `KSPSetTolerances()` to alter the defaults for rtol, abstol, dtol.
1365: The precise values of reason are macros such as `KSP_CONVERGED_RTOL`, which
1366: are defined in petscksp.h.
1368: If the convergence test is not `KSPConvergedDefault()` then this is ignored.
1370: If right preconditioning is being used then B does not appear in the above formula.
1372: .seealso: [](chapter_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`
1373: @*/
1374: PetscErrorCode KSPConvergedDefaultSetUIRNorm(KSP ksp)
1375: {
1376: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1378: PetscFunctionBegin;
1380: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1381: PetscCheck(!ctx->mininitialrtol, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "Cannot use KSPConvergedDefaultSetUIRNorm() and KSPConvergedDefaultSetUMIRNorm() together");
1382: ctx->initialrtol = PETSC_TRUE;
1383: PetscFunctionReturn(PETSC_SUCCESS);
1384: }
1386: /*@
1387: KSPConvergedDefaultSetUMIRNorm - makes the default convergence test use min(|| B*(b - A*(initial guess))||,|| B*b ||)
1388: In the case of right preconditioner or if `KSPSetNormType`(ksp,`KSP_NORM_UNPRECONDITIONED`)
1389: is used there is no B in the above formula. UMIRNorm is short for Use Minimum Initial Residual Norm.
1391: Collective
1393: Input Parameters:
1394: . ksp - iterative context
1396: Options Database Key:
1397: . -ksp_converged_use_min_initial_residual_norm <bool> - Use minimum of initial residual norm and b for computing relative convergence
1399: Level: intermediate
1401: Use `KSPSetTolerances()` to alter the defaults for rtol, abstol, dtol.
1403: The precise values of reason are macros such as `KSP_CONVERGED_RTOL`, which
1404: are defined in petscksp.h.
1406: .seealso: [](chapter_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`
1407: @*/
1408: PetscErrorCode KSPConvergedDefaultSetUMIRNorm(KSP ksp)
1409: {
1410: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1412: PetscFunctionBegin;
1414: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1415: PetscCheck(!ctx->initialrtol, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "Cannot use KSPConvergedDefaultSetUIRNorm() and KSPConvergedDefaultSetUMIRNorm() together");
1416: ctx->mininitialrtol = PETSC_TRUE;
1417: PetscFunctionReturn(PETSC_SUCCESS);
1418: }
1420: /*@
1421: KSPConvergedDefaultSetConvergedMaxits - allows the default convergence test to declare convergence and return `KSP_CONVERGED_ITS` if the maximum number of iterations is reached
1423: Collective
1425: Input Parameters:
1426: + ksp - iterative context
1427: - flg - boolean flag
1429: Options Database Key:
1430: . -ksp_converged_maxits <bool> - Declare convergence if the maximum number of iterations is reached
1432: Level: intermediate
1434: Note:
1435: The precise values of reason available in `KSPConvergedReason`
1437: .seealso: [](chapter_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetUIRNorm()`
1438: @*/
1439: PetscErrorCode KSPConvergedDefaultSetConvergedMaxits(KSP ksp, PetscBool flg)
1440: {
1441: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1443: PetscFunctionBegin;
1446: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1447: ctx->convmaxits = flg;
1448: PetscFunctionReturn(PETSC_SUCCESS);
1449: }
1451: /*@C
1452: KSPConvergedDefault - Default code to determine convergence of the linear iterative solvers
1454: Collective
1456: Input Parameters:
1457: + ksp - iterative context
1458: . n - iteration number
1459: . rnorm - residual norm (may be estimated, depending on the method may be the preconditioned residual norm)
1460: - ctx - convergence context which must be created by `KSPConvergedDefaultCreate()`
1462: Output Parameter:
1463: . reason - the convergence reason; it is positive if the iteration has converged,
1464: negative if the iteration has diverged, and `KSP_CONVERGED_ITERATING` otherwise
1466: Options Database Keys:
1467: + -ksp_max_it - maximum number of linear iterations
1468: . -ksp_rtol rtol - relative tolerance used in default determination of convergence, i.e. if residual norm decreases by this factor than convergence is declared
1469: . -ksp_atol abstol - absolute tolerance used in default convergence test, i.e. if residual norm is less than this then convergence is declared
1470: . -ksp_divtol tol - if residual norm increases by this factor than divergence is declared
1471: . -ksp_converged_use_initial_residual_norm - see `KSPConvergedDefaultSetUIRNorm()`
1472: . -ksp_converged_use_min_initial_residual_norm - see `KSPConvergedDefaultSetUMIRNorm()`
1473: - -ksp_converged_maxits - see `KSPConvergedDefaultSetConvergedMaxits()`
1475: Level: advanced
1477: Notes:
1478: `KSPConvergedDefault()` reaches convergence when rnorm < MAX (rtol * rnorm_0, abstol);
1479: Divergence is detected if rnorm > dtol * rnorm_0, or when failures are detected throughout the iteration.
1480: By default, reaching the maximum number of iterations is considered divergence (i.e. KSP_DIVERGED_ITS).
1481: In order to have PETSc declaring convergence in such a case (i.e. `KSP_CONVERGED_ITS`), users can use `KSPConvergedDefaultSetConvergedMaxits()`
1483: where:
1484: + rtol - relative tolerance,
1485: . abstol - absolute tolerance.
1486: . dtol - divergence tolerance,
1487: - rnorm_0 - the two norm of the right hand side (or the preconditioned norm, depending on what was set with
1488: `KSPSetNormType()`. When initial guess is non-zero you
1489: can call `KSPConvergedDefaultSetUIRNorm()` to use the norm of (b - A*(initial guess))
1490: as the starting point for relative norm convergence testing, that is as rnorm_0.
1491: Call `KSPConvergedDefaultSetUMIRNorm()` to use the minimum of the norm of (b - A*(initial guess)) and the norm of b as the starting point.
1493: Use `KSPSetTolerances()` to alter the defaults for rtol, abstol, dtol.
1495: Use `KSPSetNormType()` (or -ksp_norm_type <none,preconditioned,unpreconditioned,natural>) to change the norm used for computing rnorm
1497: The precise values of reason are available in `KSPConvergedReason`
1499: This routine is used by `KSP` by default so the user generally never needs call it directly.
1501: Use `KSPSetConvergenceTest()` to provide your own test instead of using this one.
1503: Call `KSPSetConvergenceTest()` with the ctx, as created above and the destruction function `KSPConvergedDefaultDestroy()`
1505: .seealso: [](chapter_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`,
1506: `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`, `KSPConvergedDefaultCreate()`, `KSPConvergedDefaultDestroy()`
1507: @*/
1508: PetscErrorCode KSPConvergedDefault(KSP ksp, PetscInt n, PetscReal rnorm, KSPConvergedReason *reason, void *ctx)
1509: {
1510: KSPConvergedDefaultCtx *cctx = (KSPConvergedDefaultCtx *)ctx;
1511: KSPNormType normtype;
1513: PetscFunctionBegin;
1517: PetscCheck(cctx, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_NULL, "Convergence context must have been created with KSPConvergedDefaultCreate()");
1518: *reason = KSP_CONVERGED_ITERATING;
1520: if (cctx->convmaxits && n >= ksp->max_it) {
1521: *reason = KSP_CONVERGED_ITS;
1522: PetscCall(PetscInfo(ksp, "Linear solver has converged. Maximum number of iterations reached %" PetscInt_FMT "\n", n));
1523: PetscFunctionReturn(PETSC_SUCCESS);
1524: }
1525: PetscCall(KSPGetNormType(ksp, &normtype));
1526: if (normtype == KSP_NORM_NONE) PetscFunctionReturn(PETSC_SUCCESS);
1528: if (!n) {
1529: /* if user gives initial guess need to compute norm of b */
1530: if (!ksp->guess_zero && !cctx->initialrtol) {
1531: PetscReal snorm = 0.0;
1532: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->pc_side == PC_RIGHT) {
1533: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing 2-norm of RHS\n"));
1534: PetscCall(VecNorm(ksp->vec_rhs, NORM_2, &snorm)); /* <- b'*b */
1535: } else {
1536: Vec z;
1537: /* Should avoid allocating the z vector each time but cannot stash it in cctx because if KSPReset() is called the vector size might change */
1538: PetscCall(VecDuplicate(ksp->vec_rhs, &z));
1539: PetscCall(KSP_PCApply(ksp, ksp->vec_rhs, z));
1540: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
1541: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing 2-norm of preconditioned RHS\n"));
1542: PetscCall(VecNorm(z, NORM_2, &snorm)); /* dp <- b'*B'*B*b */
1543: } else if (ksp->normtype == KSP_NORM_NATURAL) {
1544: PetscScalar norm;
1545: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing natural norm of RHS\n"));
1546: PetscCall(VecDot(ksp->vec_rhs, z, &norm));
1547: snorm = PetscSqrtReal(PetscAbsScalar(norm)); /* dp <- b'*B*b */
1548: }
1549: PetscCall(VecDestroy(&z));
1550: }
1551: /* handle special case of zero RHS and nonzero guess */
1552: if (!snorm) {
1553: PetscCall(PetscInfo(ksp, "Special case, user has provided nonzero initial guess and zero RHS\n"));
1554: snorm = rnorm;
1555: }
1556: if (cctx->mininitialrtol) ksp->rnorm0 = PetscMin(snorm, rnorm);
1557: else ksp->rnorm0 = snorm;
1558: } else {
1559: ksp->rnorm0 = rnorm;
1560: }
1561: ksp->ttol = PetscMax(ksp->rtol * ksp->rnorm0, ksp->abstol);
1562: }
1564: if (n <= ksp->chknorm) PetscFunctionReturn(PETSC_SUCCESS);
1566: if (PetscIsInfOrNanReal(rnorm)) {
1567: PCFailedReason pcreason;
1568: PetscInt sendbuf, recvbuf;
1569: PetscCall(PCGetFailedReasonRank(ksp->pc, &pcreason));
1570: sendbuf = (PetscInt)pcreason;
1571: PetscCall(MPIU_Allreduce(&sendbuf, &recvbuf, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)ksp)));
1572: if (recvbuf) {
1573: *reason = KSP_DIVERGED_PC_FAILED;
1574: PetscCall(PCSetFailedReason(ksp->pc, (PCFailedReason)recvbuf));
1575: PetscCall(PetscInfo(ksp, "Linear solver pcsetup fails, declaring divergence \n"));
1576: } else {
1577: *reason = KSP_DIVERGED_NANORINF;
1578: PetscCall(PetscInfo(ksp, "Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n"));
1579: }
1580: } else if (rnorm <= ksp->ttol) {
1581: if (rnorm < ksp->abstol) {
1582: PetscCall(PetscInfo(ksp, "Linear solver has converged. Residual norm %14.12e is less than absolute tolerance %14.12e at iteration %" PetscInt_FMT "\n", (double)rnorm, (double)ksp->abstol, n));
1583: *reason = KSP_CONVERGED_ATOL;
1584: } else {
1585: if (cctx->initialrtol) {
1586: PetscCall(PetscInfo(ksp, "Linear solver has converged. Residual norm %14.12e is less than relative tolerance %14.12e times initial residual norm %14.12e at iteration %" PetscInt_FMT "\n", (double)rnorm, (double)ksp->rtol, (double)ksp->rnorm0, n));
1587: } else {
1588: PetscCall(PetscInfo(ksp, "Linear solver has converged. Residual norm %14.12e is less than relative tolerance %14.12e times initial right hand side norm %14.12e at iteration %" PetscInt_FMT "\n", (double)rnorm, (double)ksp->rtol, (double)ksp->rnorm0, n));
1589: }
1590: *reason = KSP_CONVERGED_RTOL;
1591: }
1592: } else if (rnorm >= ksp->divtol * ksp->rnorm0) {
1593: PetscCall(PetscInfo(ksp, "Linear solver is diverging. Initial right hand size norm %14.12e, current residual norm %14.12e at iteration %" PetscInt_FMT "\n", (double)ksp->rnorm0, (double)rnorm, n));
1594: *reason = KSP_DIVERGED_DTOL;
1595: }
1596: PetscFunctionReturn(PETSC_SUCCESS);
1597: }
1599: /*@C
1600: KSPConvergedDefaultDestroy - Frees the space used by the `KSPConvergedDefault()` function context
1602: Not Collective
1604: Input Parameter:
1605: . ctx - convergence context
1607: Level: intermediate
1609: Note:
1610: Pass this function name into `KSPSetConvergenceTest()` along with the context obtained with `KSPConvergedDefaultCreate()` and `KSPConvergedDefault()`
1612: .seealso: [](chapter_ksp), `KSP`, `KSPConvergedDefault()`, `KSPConvergedDefaultCreate()`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`,
1613: `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`
1614: @*/
1615: PetscErrorCode KSPConvergedDefaultDestroy(void *ctx)
1616: {
1617: KSPConvergedDefaultCtx *cctx = (KSPConvergedDefaultCtx *)ctx;
1619: PetscFunctionBegin;
1620: PetscCall(VecDestroy(&cctx->work));
1621: PetscCall(PetscFree(ctx));
1622: PetscFunctionReturn(PETSC_SUCCESS);
1623: }
1625: /*
1626: KSPBuildSolutionDefault - Default code to create/move the solution.
1628: Collective
1630: Input Parameters:
1631: + ksp - iterative context
1632: - v - pointer to the user's vector
1634: Output Parameter:
1635: . V - pointer to a vector containing the solution
1637: Level: advanced
1639: Developers Note:
1640: This is PETSC_EXTERN because it may be used by user written plugin `KSPType` implementations
1642: .seealso: [](chapter_ksp), `KSP`, `KSPGetSolution()`, `KSPBuildResidualDefault()`
1643: */
1644: PetscErrorCode KSPBuildSolutionDefault(KSP ksp, Vec v, Vec *V)
1645: {
1646: PetscFunctionBegin;
1647: if (ksp->pc_side == PC_RIGHT) {
1648: if (ksp->pc) {
1649: PetscCheck(v, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with right preconditioner");
1650: PetscCall(KSP_PCApply(ksp, ksp->vec_sol, v));
1651: *V = v;
1652: } else {
1653: if (v) {
1654: PetscCall(VecCopy(ksp->vec_sol, v));
1655: *V = v;
1656: } else *V = ksp->vec_sol;
1657: }
1658: } else if (ksp->pc_side == PC_SYMMETRIC) {
1659: if (ksp->pc) {
1660: PetscCheck(!ksp->transpose_solve, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with symmetric preconditioner and transpose solve");
1661: PetscCheck(v, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with symmetric preconditioner");
1662: PetscCall(PCApplySymmetricRight(ksp->pc, ksp->vec_sol, v));
1663: *V = v;
1664: } else {
1665: if (v) {
1666: PetscCall(VecCopy(ksp->vec_sol, v));
1667: *V = v;
1668: } else *V = ksp->vec_sol;
1669: }
1670: } else {
1671: if (v) {
1672: PetscCall(VecCopy(ksp->vec_sol, v));
1673: *V = v;
1674: } else *V = ksp->vec_sol;
1675: }
1676: PetscFunctionReturn(PETSC_SUCCESS);
1677: }
1679: /*
1680: KSPBuildResidualDefault - Default code to compute the residual.
1682: Collecive on ksp
1684: Input Parameters:
1685: . ksp - iterative context
1686: . t - pointer to temporary vector
1687: . v - pointer to user vector
1689: Output Parameter:
1690: . V - pointer to a vector containing the residual
1692: Level: advanced
1694: Developers Note:
1695: This is PETSC_EXTERN because it may be used by user written plugin `KSPType` implementations
1697: .seealso: [](chapter_ksp), `KSP`, `KSPBuildSolutionDefault()`
1698: */
1699: PetscErrorCode KSPBuildResidualDefault(KSP ksp, Vec t, Vec v, Vec *V)
1700: {
1701: Mat Amat, Pmat;
1703: PetscFunctionBegin;
1704: if (!ksp->pc) PetscCall(KSPGetPC(ksp, &ksp->pc));
1705: PetscCall(PCGetOperators(ksp->pc, &Amat, &Pmat));
1706: PetscCall(KSPBuildSolution(ksp, t, NULL));
1707: PetscCall(KSP_MatMult(ksp, Amat, t, v));
1708: PetscCall(VecAYPX(v, -1.0, ksp->vec_rhs));
1709: *V = v;
1710: PetscFunctionReturn(PETSC_SUCCESS);
1711: }
1713: /*@C
1714: KSPCreateVecs - Gets a number of work vectors suitably sized for the operator in the `KSP`
1716: Collective
1718: Input Parameters:
1719: + ksp - iterative context
1720: . rightn - number of right work vectors
1721: - leftn - number of left work vectors to allocate
1723: Output Parameters:
1724: + right - the array of vectors created
1725: - left - the array of left vectors
1727: Level: advanced
1729: Notes:
1730: The right vector has as many elements as the matrix has columns. The left
1731: vector has as many elements as the matrix has rows.
1733: The vectors are new vectors that are not owned by the `KSP`, they should be destroyed with calls to `VecDestroyVecs()` when no longer needed.
1735: Developers Note:
1736: First tries to duplicate the rhs and solution vectors of the `KSP`, if they do not exist tries to get them from the matrix, if
1737: that does not exist tries to get them from the `DM` (if it is provided).
1739: .seealso: [](chapter_ksp), `MatCreateVecs()`, `VecDestroyVecs()`, `KSPSetWorkVecs()`
1740: @*/
1741: PetscErrorCode KSPCreateVecs(KSP ksp, PetscInt rightn, Vec **right, PetscInt leftn, Vec **left)
1742: {
1743: Vec vecr = NULL, vecl = NULL;
1744: PetscBool matset, pmatset, isshell, preferdm = PETSC_FALSE;
1745: Mat mat = NULL;
1747: PetscFunctionBegin;
1748: if (ksp->dm) {
1749: PetscCall(PetscObjectTypeCompare((PetscObject)ksp->dm, DMSHELL, &isshell));
1750: preferdm = isshell ? PETSC_FALSE : PETSC_TRUE;
1751: }
1752: if (rightn) {
1753: PetscCheck(right, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_INCOMP, "You asked for right vectors but did not pass a pointer to hold them");
1754: if (ksp->vec_sol) vecr = ksp->vec_sol;
1755: else {
1756: if (preferdm) {
1757: PetscCall(DMGetGlobalVector(ksp->dm, &vecr));
1758: } else if (ksp->pc) {
1759: PetscCall(PCGetOperatorsSet(ksp->pc, &matset, &pmatset));
1760: /* check for mat before pmat because for KSPLSQR pmat may be a different size than mat since pmat maybe mat'*mat */
1761: if (matset) {
1762: PetscCall(PCGetOperators(ksp->pc, &mat, NULL));
1763: PetscCall(MatCreateVecs(mat, &vecr, NULL));
1764: } else if (pmatset) {
1765: PetscCall(PCGetOperators(ksp->pc, NULL, &mat));
1766: PetscCall(MatCreateVecs(mat, &vecr, NULL));
1767: }
1768: }
1769: if (!vecr && ksp->dm) PetscCall(DMGetGlobalVector(ksp->dm, &vecr));
1770: PetscCheck(vecr, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "You requested a vector from a KSP that cannot provide one");
1771: }
1772: PetscCall(VecDuplicateVecs(vecr, rightn, right));
1773: if (!ksp->vec_sol) {
1774: if (preferdm) {
1775: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecr));
1776: } else if (mat) {
1777: PetscCall(VecDestroy(&vecr));
1778: } else if (ksp->dm) {
1779: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecr));
1780: }
1781: }
1782: }
1783: if (leftn) {
1784: PetscCheck(left, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_INCOMP, "You asked for left vectors but did not pass a pointer to hold them");
1785: if (ksp->vec_rhs) vecl = ksp->vec_rhs;
1786: else {
1787: if (preferdm) {
1788: PetscCall(DMGetGlobalVector(ksp->dm, &vecl));
1789: } else if (ksp->pc) {
1790: PetscCall(PCGetOperatorsSet(ksp->pc, &matset, &pmatset));
1791: /* check for mat before pmat because for KSPLSQR pmat may be a different size than mat since pmat maybe mat'*mat */
1792: if (matset) {
1793: PetscCall(PCGetOperators(ksp->pc, &mat, NULL));
1794: PetscCall(MatCreateVecs(mat, NULL, &vecl));
1795: } else if (pmatset) {
1796: PetscCall(PCGetOperators(ksp->pc, NULL, &mat));
1797: PetscCall(MatCreateVecs(mat, NULL, &vecl));
1798: }
1799: }
1800: if (!vecl && ksp->dm) PetscCall(DMGetGlobalVector(ksp->dm, &vecl));
1801: PetscCheck(vecl, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "You requested a vector from a KSP that cannot provide one");
1802: }
1803: PetscCall(VecDuplicateVecs(vecl, leftn, left));
1804: if (!ksp->vec_rhs) {
1805: if (preferdm) {
1806: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecl));
1807: } else if (mat) {
1808: PetscCall(VecDestroy(&vecl));
1809: } else if (ksp->dm) {
1810: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecl));
1811: }
1812: }
1813: }
1814: PetscFunctionReturn(PETSC_SUCCESS);
1815: }
1817: /*@C
1818: KSPSetWorkVecs - Sets a number of work vectors into a `KSP` object
1820: Collective
1822: Input Parameters:
1823: + ksp - iterative context
1824: - nw - number of work vectors to allocate
1826: Level: developer
1828: Developers Note:
1829: This is PETSC_EXTERN because it may be used by user written plugin `KSPType` implementations
1831: .seealso: [](chapter_ksp), `KSP`, `KSPCreateVecs()`
1832: @*/
1833: PetscErrorCode KSPSetWorkVecs(KSP ksp, PetscInt nw)
1834: {
1835: PetscFunctionBegin;
1836: PetscCall(VecDestroyVecs(ksp->nwork, &ksp->work));
1837: ksp->nwork = nw;
1838: PetscCall(KSPCreateVecs(ksp, nw, &ksp->work, 0, NULL));
1839: PetscFunctionReturn(PETSC_SUCCESS);
1840: }
1842: /*
1843: KSPDestroyDefault - Destroys a iterative context variable for methods with no separate context. Preferred calling sequence `KSPDestroy()`.
1845: Input Parameter:
1846: . ksp - the iterative context
1848: Developers Note:
1849: This is PETSC_EXTERN because it may be used by user written plugin `KSPType` implementations
1851: */
1852: PetscErrorCode KSPDestroyDefault(KSP ksp)
1853: {
1854: PetscFunctionBegin;
1856: PetscCall(PetscFree(ksp->data));
1857: PetscFunctionReturn(PETSC_SUCCESS);
1858: }
1860: /*@
1861: KSPGetConvergedReason - Gets the reason the `KSP` iteration was stopped.
1863: Not Collective
1865: Input Parameter:
1866: . ksp - the `KSP` context
1868: Output Parameter:
1869: . reason - negative value indicates diverged, positive value converged, see `KSPConvergedReason` for the possible values
1871: Options Database Key:
1872: . -ksp_converged_reason - prints the reason to standard out
1874: Level: intermediate
1876: Notes:
1877: If this routine is called before or doing the `KSPSolve()` the value of `KSP_CONVERGED_ITERATING` is returned
1879: .seealso: [](chapter_ksp), `KSPConvergedReason`, `KSP`, `KSPSetConvergenceTest()`, `KSPConvergedDefault()`, `KSPSetTolerances()`, `KSPConvergedReason`,
1880: `KSPConvergedReasonView()`
1881: @*/
1882: PetscErrorCode KSPGetConvergedReason(KSP ksp, KSPConvergedReason *reason)
1883: {
1884: PetscFunctionBegin;
1887: *reason = ksp->reason;
1888: PetscFunctionReturn(PETSC_SUCCESS);
1889: }
1891: /*@C
1892: KSPGetConvergedReasonString - Return a human readable string for a `KSPConvergedReason`
1894: Not Collective
1896: Input Parameter:
1897: . ksp - the `KSP` context
1899: Output Parameter:
1900: . strreason - a human readable string that describes ksp converged reason
1902: Level: beginner
1904: .seealso: [](chapter_ksp), `KSP`, `KSPGetConvergedReason()`
1905: @*/
1906: PetscErrorCode KSPGetConvergedReasonString(KSP ksp, const char **strreason)
1907: {
1908: PetscFunctionBegin;
1911: *strreason = KSPConvergedReasons[ksp->reason];
1912: PetscFunctionReturn(PETSC_SUCCESS);
1913: }
1915: #include <petsc/private/dmimpl.h>
1916: /*@
1917: KSPSetDM - Sets the `DM` that may be used by some preconditioners
1919: Logically Collective
1921: Input Parameters:
1922: + ksp - the `KSP`
1923: - dm - the `DM`, cannot be `NULL` to remove a previously set `DM`
1925: Level: intermediate
1927: Notes:
1928: If this is used then the `KSP` will attempt to use the `DM` to create the matrix and use the routine set with
1929: `DMKSPSetComputeOperators()`. Use `KSPSetDMActive`(ksp,`PETSC_FALSE`) to instead use the matrix you've provided with
1930: `KSPSetOperators()`.
1932: A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
1933: even when not using interfaces like `DMKSPSetComputeOperators()`. Use `DMClone()` to get a distinct `DM` when solving
1934: different problems using the same function space.
1936: .seealso: [](chapter_ksp), `KSP`, `DM`, `KSPGetDM()`, `KSPSetDMActive()`, `KSPSetComputeOperators()`, `KSPSetComputeRHS()`, `KSPSetComputeInitialGuess()`, `DMKSPSetComputeOperators()`, `DMKSPSetComputeRHS()`, `DMKSPSetComputeInitialGuess()`
1937: @*/
1938: PetscErrorCode KSPSetDM(KSP ksp, DM dm)
1939: {
1940: PC pc;
1942: PetscFunctionBegin;
1945: PetscCall(PetscObjectReference((PetscObject)dm));
1946: if (ksp->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
1947: if (ksp->dm->dmksp && !dm->dmksp) {
1948: DMKSP kdm;
1949: PetscCall(DMCopyDMKSP(ksp->dm, dm));
1950: PetscCall(DMGetDMKSP(ksp->dm, &kdm));
1951: if (kdm->originaldm == ksp->dm) kdm->originaldm = dm; /* Grant write privileges to the replacement DM */
1952: }
1953: PetscCall(DMDestroy(&ksp->dm));
1954: }
1955: ksp->dm = dm;
1956: ksp->dmAuto = PETSC_FALSE;
1957: PetscCall(KSPGetPC(ksp, &pc));
1958: PetscCall(PCSetDM(pc, dm));
1959: ksp->dmActive = PETSC_TRUE;
1960: PetscFunctionReturn(PETSC_SUCCESS);
1961: }
1963: /*@
1964: KSPSetDMActive - Indicates the `DM` should be used to generate the linear system matrix and right hand side vector
1966: Logically Collective
1968: Input Parameters:
1969: + ksp - the `KSP`
1970: - flg - use the `DM`
1972: Level: intermediate
1974: Note:
1975: By default `KSPSetDM()` sets the `DM` as active, call `KSPSetDMActive`(ksp,`PETSC_FALSE`); after `KSPSetDM`(ksp,dm) to not have the `KSP` object use the `DM` to generate the matrices.
1977: .seealso: [](chapter_ksp), `KSP`, `DM`, `KSPGetDM()`, `KSPSetDM()`, `SNESSetDM()`, `KSPSetComputeOperators()`, `KSPSetComputeRHS()`, `KSPSetComputeInitialGuess()`
1978: @*/
1979: PetscErrorCode KSPSetDMActive(KSP ksp, PetscBool flg)
1980: {
1981: PetscFunctionBegin;
1984: ksp->dmActive = flg;
1985: PetscFunctionReturn(PETSC_SUCCESS);
1986: }
1988: /*@
1989: KSPGetDM - Gets the `DM` that may be used by some preconditioners
1991: Not Collective
1993: Input Parameter:
1994: . ksp - the `KSP`
1996: Output Parameter:
1997: . dm - the `DM`
1999: Level: intermediate
2001: .seealso: [](chapter_ksp), `KSP`, `DM`, `KSPSetDM()`, `KSPSetDMActive()`
2002: @*/
2003: PetscErrorCode KSPGetDM(KSP ksp, DM *dm)
2004: {
2005: PetscFunctionBegin;
2007: if (!ksp->dm) {
2008: PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ksp), &ksp->dm));
2009: ksp->dmAuto = PETSC_TRUE;
2010: }
2011: *dm = ksp->dm;
2012: PetscFunctionReturn(PETSC_SUCCESS);
2013: }
2015: /*@
2016: KSPSetApplicationContext - Sets the optional user-defined context for the linear solver.
2018: Logically Collective
2020: Input Parameters:
2021: + ksp - the `KSP` context
2022: - usrP - optional user context
2024: Level: intermediate
2026: Notes:
2027: The user context is a way for users to attach any information to the `KSP` that they may need later when interacting with the `KSP`
2029: Use `KSPGetApplicationContext()` to get access to the context at a later time.
2031: Fortran Note:
2032: To use this from Fortran you must write a Fortran interface definition for this
2033: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2035: .seealso: [](chapter_ksp), `KSP`, `KSPGetApplicationContext()`
2036: @*/
2037: PetscErrorCode KSPSetApplicationContext(KSP ksp, void *usrP)
2038: {
2039: PC pc;
2041: PetscFunctionBegin;
2043: ksp->user = usrP;
2044: PetscCall(KSPGetPC(ksp, &pc));
2045: PetscCall(PCSetApplicationContext(pc, usrP));
2046: PetscFunctionReturn(PETSC_SUCCESS);
2047: }
2049: /*@
2050: KSPGetApplicationContext - Gets the user-defined context for the linear solver set with `KSPSetApplicationContext()`
2052: Not Collective
2054: Input Parameter:
2055: . ksp - `KSP` context
2057: Output Parameter:
2058: . usrP - user context
2060: Level: intermediate
2062: Fortran Notes:
2063: To use this from Fortran you must write a Fortran interface definition for this
2064: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2066: .seealso: [](chapter_ksp), `KSP`, `KSPSetApplicationContext()`
2067: @*/
2068: PetscErrorCode KSPGetApplicationContext(KSP ksp, void *usrP)
2069: {
2070: PetscFunctionBegin;
2072: *(void **)usrP = ksp->user;
2073: PetscFunctionReturn(PETSC_SUCCESS);
2074: }
2076: #include <petsc/private/pcimpl.h>
2078: /*@
2079: KSPCheckSolve - Checks if the `PCSetUp()` or `KSPSolve()` failed and set the error flag for the outer `PC`. A `KSP_DIVERGED_ITS` is
2080: not considered a failure in this context
2082: Collective
2084: Input Parameters:
2085: + ksp - the linear solver `KSP` context.
2086: . pc - the preconditioner context
2087: - vec - a vector that will be initialized with Inf to indicate lack of convergence
2089: Level: developer
2091: Note:
2092: This is called within `KSPSolve()` and `PCApply()` to check if an error has been detected on any particular MPI ranks. By initializing the vector
2093: with Inf the next call to `KSPCheckNorm()` or `KSPCheckDot()` will provide the same information to all the MPI ranks that an error occurred on
2094: at least one of the ranks.
2096: This may be called by a subset of the processes in the `PC`.
2098: Developer Note:
2099: This is used to manage returning with appropriate information from preconditioners whose inner `KSP` solvers have failed in some way
2101: .seealso: [](chapter_ksp), `KSP`, `KSPCreate()`, `KSPSetType()`, `KSP`, `KSPCheckNorm()`, `KSPCheckDot()`
2102: @*/
2103: PetscErrorCode KSPCheckSolve(KSP ksp, PC pc, Vec vec)
2104: {
2105: PCFailedReason pcreason;
2106: PC subpc;
2108: PetscFunctionBegin;
2109: PetscCall(KSPGetPC(ksp, &subpc));
2110: PetscCall(PCGetFailedReason(subpc, &pcreason));
2111: if (pcreason || (ksp->reason < 0 && ksp->reason != KSP_DIVERGED_ITS)) {
2112: PetscCheck(!pc->erroriffailure, PETSC_COMM_SELF, PETSC_ERR_NOT_CONVERGED, "Detected not converged in KSP inner solve: KSP reason %s PC reason %s", KSPConvergedReasons[ksp->reason], PCFailedReasons[pcreason]);
2113: PetscCall(PetscInfo(ksp, "Detected not converged in KSP inner solve: KSP reason %s PC reason %s\n", KSPConvergedReasons[ksp->reason], PCFailedReasons[pcreason]));
2114: pc->failedreason = PC_SUBPC_ERROR;
2115: if (vec) PetscCall(VecSetInf(vec));
2116: }
2117: PetscFunctionReturn(PETSC_SUCCESS);
2118: }