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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: if (bnorm == 0) {
411: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP %s resid norm %14.12e true resid norm %14.12e ||r(i)||/||b|| inf\n", n, normtype, (double)rnorm, (double)truenorm));
412: } else {
413: 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)));
414: }
415: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
416: PetscCall(PetscViewerPopFormat(viewer));
417: PetscFunctionReturn(PETSC_SUCCESS);
418: }
420: /*@C
421: KSPMonitorTrueResidualDraw - Plots the true residual at each iteration of an iterative solver.
423: Collective
425: Input Parameters:
426: + ksp - iterative context
427: . n - iteration number
428: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
429: - vf - The viewer context of type `PETSCVIEWERDRAW`
431: Options Database Key:
432: . -ksp_monitor_true_residual draw - Activates `KSPMonitorResidualDraw()`
434: Level: intermediate
436: Note:
437: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
438: to be used during the `KSP` solve.
440: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidual()`,
441: `KSPMonitorTrueResidualDrawLG()`, `PetscViewerAndFormat`
442: @*/
443: PetscErrorCode KSPMonitorTrueResidualDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
444: {
445: PetscViewer viewer = vf->viewer;
446: PetscViewerFormat format = vf->format;
447: Vec r;
449: PetscFunctionBegin;
451: PetscCall(PetscViewerPushFormat(viewer, format));
452: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
453: PetscCall(PetscObjectSetName((PetscObject)r, "Residual"));
454: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", (PetscObject)ksp));
455: PetscCall(VecView(r, viewer));
456: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", NULL));
457: PetscCall(VecDestroy(&r));
458: PetscCall(PetscViewerPopFormat(viewer));
459: PetscFunctionReturn(PETSC_SUCCESS);
460: }
462: /*@C
463: KSPMonitorTrueResidualDrawLG - Plots the true residual norm at each iteration of an iterative solver.
465: Collective
467: Input Parameters:
468: + ksp - iterative context
469: . n - iteration number
470: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
471: - vf - The viewer context
473: Options Database Key:
474: . -ksp_monitor_true_residual draw::draw_lg - Activates `KSPMonitorTrueResidualDrawLG()`
476: Level: intermediate
478: Notes:
479: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
480: to be used during the `KSP` solve.
482: Call `KSPMonitorTrueResidualDrawLGCreate()` to create the context needed for this monitor
484: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorTrueResidualDraw()`, `KSPMonitorResidual`,
485: `KSPMonitorTrueResidualDrawLGCreate()`
486: @*/
487: PetscErrorCode KSPMonitorTrueResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
488: {
489: PetscViewer viewer = vf->viewer;
490: PetscViewerFormat format = vf->format;
491: PetscDrawLG lg = vf->lg;
492: Vec r;
493: KSPConvergedReason reason;
494: PetscReal truenorm, x[2], y[2];
496: PetscFunctionBegin;
499: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
500: PetscCall(VecNorm(r, NORM_2, &truenorm));
501: PetscCall(VecDestroy(&r));
502: PetscCall(PetscViewerPushFormat(viewer, format));
503: if (!n) PetscCall(PetscDrawLGReset(lg));
504: x[0] = (PetscReal)n;
505: if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
506: else y[0] = -15.0;
507: x[1] = (PetscReal)n;
508: if (truenorm > 0.0) y[1] = PetscLog10Real(truenorm);
509: else y[1] = -15.0;
510: PetscCall(PetscDrawLGAddPoint(lg, x, y));
511: PetscCall(KSPGetConvergedReason(ksp, &reason));
512: if (n <= 20 || !(n % 5) || reason) {
513: PetscCall(PetscDrawLGDraw(lg));
514: PetscCall(PetscDrawLGSave(lg));
515: }
516: PetscCall(PetscViewerPopFormat(viewer));
517: PetscFunctionReturn(PETSC_SUCCESS);
518: }
520: /*@C
521: KSPMonitorTrueResidualDrawLGCreate - Creates the context for the true residual monitor `KSPMonitorTrueResidualDrawLG()`
523: Collective
525: Input Parameters:
526: + viewer - The `PetscViewer` of type `PETSCVIEWERDRAW`
527: . format - The viewer format
528: - ctx - An optional user context
530: Output Parameter:
531: . vf - The viewer context
533: Level: intermediate
535: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `PetscViewerAndFormat`
536: @*/
537: PetscErrorCode KSPMonitorTrueResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
538: {
539: const char *names[] = {"preconditioned", "true"};
541: PetscFunctionBegin;
542: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
543: (*vf)->data = ctx;
544: PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg));
545: PetscFunctionReturn(PETSC_SUCCESS);
546: }
548: /*@C
549: KSPMonitorTrueResidualMax - Prints the true residual max norm at each iteration of an iterative solver.
551: Collective
553: Input Parameters:
554: + ksp - iterative context
555: . n - iteration number
556: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
557: - vf - The viewer context
559: Options Database Key:
560: . -ksp_monitor_true_residual_max - Activates `KSPMonitorTrueResidualMax()`
562: Level: intermediate
564: Note:
565: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
566: to be used during the `KSP` solve.
568: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`
569: @*/
570: PetscErrorCode KSPMonitorTrueResidualMax(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
571: {
572: PetscViewer viewer = vf->viewer;
573: PetscViewerFormat format = vf->format;
574: Vec r;
575: PetscReal truenorm, bnorm;
576: char normtype[256];
577: PetscInt tablevel;
578: const char *prefix;
580: PetscFunctionBegin;
582: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
583: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
584: PetscCall(PetscStrncpy(normtype, KSPNormTypes[ksp->normtype], sizeof(normtype)));
585: PetscCall(PetscStrtolower(normtype));
586: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
587: PetscCall(VecNorm(r, NORM_INFINITY, &truenorm));
588: PetscCall(VecNorm(ksp->vec_rhs, NORM_INFINITY, &bnorm));
589: PetscCall(VecDestroy(&r));
591: PetscCall(PetscViewerPushFormat(viewer, format));
592: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
593: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
594: 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)));
595: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
596: PetscCall(PetscViewerPopFormat(viewer));
597: PetscFunctionReturn(PETSC_SUCCESS);
598: }
600: /*@C
601: KSPMonitorError - Prints the error norm, as well as the (possibly preconditioned) residual norm, at each iteration of an iterative solver.
603: Collective
605: Input Parameters:
606: + ksp - iterative context
607: . n - iteration number
608: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
609: - vf - The viewer context
611: Options Database Key:
612: . -ksp_monitor_error - Activates `KSPMonitorError()`
614: Level: intermediate
616: Note:
617: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
618: to be used during the `KSP` solve.
620: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`
621: @*/
622: PetscErrorCode KSPMonitorError(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
623: {
624: PetscViewer viewer = vf->viewer;
625: PetscViewerFormat format = vf->format;
626: DM dm;
627: Vec sol;
628: PetscReal *errors;
629: PetscInt Nf, f;
630: PetscInt tablevel;
631: const char *prefix;
633: PetscFunctionBegin;
635: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
636: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
637: PetscCall(KSPGetDM(ksp, &dm));
638: PetscCall(DMGetNumFields(dm, &Nf));
639: PetscCall(DMGetGlobalVector(dm, &sol));
640: PetscCall(KSPBuildSolution(ksp, sol, NULL));
641: /* TODO: Make a different monitor that flips sign for SNES, Newton system is A dx = -b, so we need to negate the solution */
642: PetscCall(VecScale(sol, -1.0));
643: PetscCall(PetscCalloc1(Nf, &errors));
644: PetscCall(DMComputeError(dm, sol, errors, NULL));
646: PetscCall(PetscViewerPushFormat(viewer, format));
647: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
648: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Error norms for %s solve.\n", prefix));
649: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Error norm %s", n, Nf > 1 ? "[" : ""));
650: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
651: for (f = 0; f < Nf; ++f) {
652: if (f > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
653: PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)errors[f]));
654: }
655: PetscCall(PetscViewerASCIIPrintf(viewer, "%s resid norm %14.12e\n", Nf > 1 ? "]" : "", (double)rnorm));
656: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
657: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
658: PetscCall(PetscViewerPopFormat(viewer));
659: PetscCall(DMRestoreGlobalVector(dm, &sol));
660: PetscFunctionReturn(PETSC_SUCCESS);
661: }
663: /*@C
664: KSPMonitorErrorDraw - Plots the error at each iteration of an iterative solver.
666: Collective
668: Input Parameters:
669: + ksp - iterative context
670: . n - iteration number
671: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
672: - vf - The viewer context
674: Options Database Key:
675: . -ksp_monitor_error draw - Activates `KSPMonitorErrorDraw()`
677: Level: intermediate
679: Note:
680: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
681: to be used during the `KSP` solve.
683: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDrawLG()`
684: @*/
685: PetscErrorCode KSPMonitorErrorDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
686: {
687: PetscViewer viewer = vf->viewer;
688: PetscViewerFormat format = vf->format;
689: DM dm;
690: Vec sol, e;
692: PetscFunctionBegin;
694: PetscCall(PetscViewerPushFormat(viewer, format));
695: PetscCall(KSPGetDM(ksp, &dm));
696: PetscCall(DMGetGlobalVector(dm, &sol));
697: PetscCall(KSPBuildSolution(ksp, sol, NULL));
698: PetscCall(DMComputeError(dm, sol, NULL, &e));
699: PetscCall(PetscObjectSetName((PetscObject)e, "Error"));
700: PetscCall(PetscObjectCompose((PetscObject)e, "__Vec_bc_zero__", (PetscObject)ksp));
701: PetscCall(VecView(e, viewer));
702: PetscCall(PetscObjectCompose((PetscObject)e, "__Vec_bc_zero__", NULL));
703: PetscCall(VecDestroy(&e));
704: PetscCall(DMRestoreGlobalVector(dm, &sol));
705: PetscCall(PetscViewerPopFormat(viewer));
706: PetscFunctionReturn(PETSC_SUCCESS);
707: }
709: /*@C
710: KSPMonitorErrorDrawLG - Plots the error and residual norm at each iteration of an iterative solver.
712: Collective
714: Input Parameters:
715: + ksp - iterative context
716: . n - iteration number
717: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
718: - vf - The viewer context
720: Options Database Key:
721: . -ksp_monitor_error draw::draw_lg - Activates `KSPMonitorTrueResidualDrawLG()`
723: Level: intermediate
725: Notes:
726: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
727: to be used during the `KSP` solve.
729: Call `KSPMonitorErrorDrawLGCreate()` to create the context used with this monitor
731: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDraw()`
732: @*/
733: PetscErrorCode KSPMonitorErrorDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
734: {
735: PetscViewer viewer = vf->viewer;
736: PetscViewerFormat format = vf->format;
737: PetscDrawLG lg = vf->lg;
738: DM dm;
739: Vec sol;
740: KSPConvergedReason reason;
741: PetscReal *x, *errors;
742: PetscInt Nf, f;
744: PetscFunctionBegin;
747: PetscCall(KSPGetDM(ksp, &dm));
748: PetscCall(DMGetNumFields(dm, &Nf));
749: PetscCall(DMGetGlobalVector(dm, &sol));
750: PetscCall(KSPBuildSolution(ksp, sol, NULL));
751: /* TODO: Make a different monitor that flips sign for SNES, Newton system is A dx = -b, so we need to negate the solution */
752: PetscCall(VecScale(sol, -1.0));
753: PetscCall(PetscCalloc2(Nf + 1, &x, Nf + 1, &errors));
754: PetscCall(DMComputeError(dm, sol, errors, NULL));
756: PetscCall(PetscViewerPushFormat(viewer, format));
757: if (!n) PetscCall(PetscDrawLGReset(lg));
758: for (f = 0; f < Nf; ++f) {
759: x[f] = (PetscReal)n;
760: errors[f] = errors[f] > 0.0 ? PetscLog10Real(errors[f]) : -15.;
761: }
762: x[Nf] = (PetscReal)n;
763: errors[Nf] = rnorm > 0.0 ? PetscLog10Real(rnorm) : -15.;
764: PetscCall(PetscDrawLGAddPoint(lg, x, errors));
765: PetscCall(KSPGetConvergedReason(ksp, &reason));
766: if (n <= 20 || !(n % 5) || reason) {
767: PetscCall(PetscDrawLGDraw(lg));
768: PetscCall(PetscDrawLGSave(lg));
769: }
770: PetscCall(PetscViewerPopFormat(viewer));
771: PetscFunctionReturn(PETSC_SUCCESS);
772: }
774: /*@C
775: KSPMonitorErrorDrawLGCreate - Creates the context for the error and preconditioned residual plotter `KSPMonitorErrorDrawLG()`
777: Collective
779: Input Parameters:
780: + viewer - The `PetscViewer`
781: . format - The viewer format
782: - ctx - An optional user context
784: Output Parameter:
785: . vf - The viewer context
787: Level: intermediate
789: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDrawLG()`, `KSPMonitorErrorDrawLG()`
790: @*/
791: PetscErrorCode KSPMonitorErrorDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
792: {
793: KSP ksp = (KSP)ctx;
794: DM dm;
795: char **names;
796: PetscInt Nf, f;
798: PetscFunctionBegin;
799: PetscCall(KSPGetDM(ksp, &dm));
800: PetscCall(DMGetNumFields(dm, &Nf));
801: PetscCall(PetscMalloc1(Nf + 1, &names));
802: for (f = 0; f < Nf; ++f) {
803: PetscObject disc;
804: const char *fname;
805: char lname[PETSC_MAX_PATH_LEN];
807: PetscCall(DMGetField(dm, f, NULL, &disc));
808: PetscCall(PetscObjectGetName(disc, &fname));
809: PetscCall(PetscStrncpy(lname, fname, PETSC_MAX_PATH_LEN));
810: PetscCall(PetscStrlcat(lname, " Error", PETSC_MAX_PATH_LEN));
811: PetscCall(PetscStrallocpy(lname, &names[f]));
812: }
813: PetscCall(PetscStrallocpy("residual", &names[Nf]));
814: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
815: (*vf)->data = ctx;
816: PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Error Norm", Nf + 1, (const char **)names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg));
817: for (f = 0; f <= Nf; ++f) PetscCall(PetscFree(names[f]));
818: PetscCall(PetscFree(names));
819: PetscFunctionReturn(PETSC_SUCCESS);
820: }
822: /*@C
823: KSPMonitorSolution - Print the solution norm at each iteration of an iterative solver.
825: Collective
827: Input Parameters:
828: + ksp - iterative context
829: . n - iteration number
830: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
831: - vf - The viewer context
833: Options Database Key:
834: . -ksp_monitor_solution - Activates `KSPMonitorSolution()`
836: Level: intermediate
838: Note:
839: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
840: to be used during the `KSP` solve.
842: .seealso: [](ch_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
843: @*/
844: PetscErrorCode KSPMonitorSolution(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
845: {
846: PetscViewer viewer = vf->viewer;
847: PetscViewerFormat format = vf->format;
848: Vec x;
849: PetscReal snorm;
850: PetscInt tablevel;
851: const char *prefix;
853: PetscFunctionBegin;
855: PetscCall(KSPBuildSolution(ksp, NULL, &x));
856: PetscCall(VecNorm(x, NORM_2, &snorm));
857: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
858: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
859: PetscCall(PetscViewerPushFormat(viewer, format));
860: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
861: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Solution norms for %s solve.\n", prefix));
862: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Solution norm %14.12e \n", n, (double)snorm));
863: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
864: PetscCall(PetscViewerPopFormat(viewer));
865: PetscFunctionReturn(PETSC_SUCCESS);
866: }
868: /*@C
869: KSPMonitorSolutionDraw - Plots the solution at each iteration of an iterative solver.
871: Collective
873: Input Parameters:
874: + ksp - iterative context
875: . n - iteration number
876: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
877: - vf - The viewer context
879: Options Database Key:
880: . -ksp_monitor_solution draw - Activates `KSPMonitorSolutionDraw()`
882: Level: intermediate
884: Note:
885: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
886: to be used during the `KSP` solve.
888: .seealso: [](ch_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
889: @*/
890: PetscErrorCode KSPMonitorSolutionDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
891: {
892: PetscViewer viewer = vf->viewer;
893: PetscViewerFormat format = vf->format;
894: Vec x;
896: PetscFunctionBegin;
898: PetscCall(KSPBuildSolution(ksp, NULL, &x));
899: PetscCall(PetscViewerPushFormat(viewer, format));
900: PetscCall(PetscObjectSetName((PetscObject)x, "Solution"));
901: PetscCall(PetscObjectCompose((PetscObject)x, "__Vec_bc_zero__", (PetscObject)ksp));
902: PetscCall(VecView(x, viewer));
903: PetscCall(PetscObjectCompose((PetscObject)x, "__Vec_bc_zero__", NULL));
904: PetscCall(PetscViewerPopFormat(viewer));
905: PetscFunctionReturn(PETSC_SUCCESS);
906: }
908: /*@C
909: KSPMonitorSolutionDrawLG - Plots the solution norm at each iteration of an iterative solver.
911: Collective
913: Input Parameters:
914: + ksp - iterative context
915: . n - iteration number
916: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
917: - vf - The viewer context
919: Options Database Key:
920: . -ksp_monitor_solution draw::draw_lg - Activates `KSPMonitorSolutionDrawLG()`
922: Level: intermediate
924: Notes:
925: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
926: to be used during the `KSP` solve.
928: Call `KSPMonitorSolutionDrawLGCreate()` to create the context needed with this monitor
930: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorSolutionDrawLGCreate()`
931: @*/
932: PetscErrorCode KSPMonitorSolutionDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
933: {
934: PetscViewer viewer = vf->viewer;
935: PetscViewerFormat format = vf->format;
936: PetscDrawLG lg = vf->lg;
937: Vec u;
938: KSPConvergedReason reason;
939: PetscReal snorm, x, y;
941: PetscFunctionBegin;
944: PetscCall(KSPBuildSolution(ksp, NULL, &u));
945: PetscCall(VecNorm(u, NORM_2, &snorm));
946: PetscCall(PetscViewerPushFormat(viewer, format));
947: if (!n) PetscCall(PetscDrawLGReset(lg));
948: x = (PetscReal)n;
949: if (snorm > 0.0) y = PetscLog10Real(snorm);
950: else y = -15.0;
951: PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
952: PetscCall(KSPGetConvergedReason(ksp, &reason));
953: if (n <= 20 || !(n % 5) || reason) {
954: PetscCall(PetscDrawLGDraw(lg));
955: PetscCall(PetscDrawLGSave(lg));
956: }
957: PetscCall(PetscViewerPopFormat(viewer));
958: PetscFunctionReturn(PETSC_SUCCESS);
959: }
961: /*@C
962: KSPMonitorSolutionDrawLGCreate - Creates the context for the `KSP` monitor `KSPMonitorSolutionDrawLG()`
964: Collective
966: Input Parameters:
967: + viewer - The `PetscViewer`
968: . format - The viewer format
969: - ctx - An optional user context
971: Output Parameter:
972: . vf - The viewer context
974: Level: intermediate
976: Note:
977: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
978: to be used during the `KSP` solve.
980: .seealso: [](ch_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
981: @*/
982: PetscErrorCode KSPMonitorSolutionDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
983: {
984: PetscFunctionBegin;
985: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
986: (*vf)->data = ctx;
987: PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Solution Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg));
988: PetscFunctionReturn(PETSC_SUCCESS);
989: }
991: /*@C
992: KSPMonitorSingularValue - Prints the two norm of the true residual and estimation of the extreme singular values of the preconditioned problem at each iteration.
994: Logically Collective
996: Input Parameters:
997: + ksp - the iterative context
998: . n - the iteration
999: . rnorm - the two norm of the residual
1000: - vf - The viewer context
1002: Options Database Key:
1003: . -ksp_monitor_singular_value - Activates `KSPMonitorSingularValue()`
1005: Level: intermediate
1007: Notes:
1008: The `KSPCG` solver uses the Lanczos technique for eigenvalue computation,
1009: while `KSPGMRES` uses the Arnoldi technique; other iterative methods do
1010: not currently compute singular values.
1012: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
1013: to be used during the `KSP` solve.
1015: Call `KSPMonitorSingularValueCreate()` to create the context needed by this monitor
1017: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPComputeExtremeSingularValues()`, `KSPMonitorSingularValueCreate()`
1018: @*/
1019: PetscErrorCode KSPMonitorSingularValue(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
1020: {
1021: PetscViewer viewer = vf->viewer;
1022: PetscViewerFormat format = vf->format;
1023: PetscReal emin, emax;
1024: PetscInt tablevel;
1025: const char *prefix;
1027: PetscFunctionBegin;
1030: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
1031: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
1032: PetscCall(PetscViewerPushFormat(viewer, format));
1033: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
1034: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
1035: if (!ksp->calc_sings) {
1036: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm %14.12e \n", n, (double)rnorm));
1037: } else {
1038: PetscCall(KSPComputeExtremeSingularValues(ksp, &emax, &emin));
1039: 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)));
1040: }
1041: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
1042: PetscCall(PetscViewerPopFormat(viewer));
1043: PetscFunctionReturn(PETSC_SUCCESS);
1044: }
1046: /*@C
1047: KSPMonitorSingularValueCreate - Creates the singular value monitor context needed by `KSPMonitorSingularValue()`
1049: Collective
1051: Input Parameters:
1052: + viewer - The PetscViewer
1053: . format - The viewer format
1054: - ctx - An optional user context
1056: Output Parameter:
1057: . vf - The viewer context
1059: Level: intermediate
1061: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorSingularValue()`, `PetscViewer`
1062: @*/
1063: PetscErrorCode KSPMonitorSingularValueCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
1064: {
1065: KSP ksp = (KSP)ctx;
1067: PetscFunctionBegin;
1068: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
1069: (*vf)->data = ctx;
1070: PetscCall(KSPSetComputeSingularValues(ksp, PETSC_TRUE));
1071: PetscFunctionReturn(PETSC_SUCCESS);
1072: }
1074: /*@C
1075: KSPMonitorDynamicToleranceCreate - Creates the context used by `KSPMonitorDynamicTolerance()`
1077: Logically Collective
1079: Output Parameter:
1080: . ctx - a void pointer
1082: Options Database Key:
1083: . -sub_ksp_dynamic_tolerance <coef> - coefficient of dynamic tolerance for inner solver, default is 1.0
1085: Level: advanced
1087: Note:
1088: Use before calling `KSPMonitorSet()` with `KSPMonitorDynamicTolerance()`
1090: The default coefficient for the tolerance can be changed with `KSPMonitorDynamicToleranceSetCoefficient()`
1092: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceSetCoefficient()`
1093: @*/
1094: PetscErrorCode KSPMonitorDynamicToleranceCreate(void *ctx)
1095: {
1096: KSPDynTolCtx *scale;
1098: PetscFunctionBegin;
1099: PetscCall(PetscMalloc1(1, &scale));
1100: scale->bnrm = -1.0;
1101: scale->coef = 1.0;
1102: *(void **)ctx = scale;
1103: PetscFunctionReturn(PETSC_SUCCESS);
1104: }
1106: /*@C
1107: KSPMonitorDynamicToleranceSetCoefficient - Sets the coefficient in the context used by `KSPMonitorDynamicTolerance()`
1109: Logically Collective
1111: Output Parameters:
1112: + ctx - the context for `KSPMonitorDynamicTolerance()`
1113: - coeff - the coefficient, default is 1.0
1115: Options Database Key:
1116: . -sub_ksp_dynamic_tolerance <coef> - coefficient of dynamic tolerance for inner solver, default is 1.0
1118: Level: advanced
1120: Note:
1121: Use before calling `KSPMonitorSet()` and after `KSPMonitorDynamicToleranceCreate()`
1123: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceCreate()`
1124: @*/
1125: PetscErrorCode KSPMonitorDynamicToleranceSetCoefficient(void *ctx, PetscReal coeff)
1126: {
1127: KSPDynTolCtx *scale = (KSPDynTolCtx *)ctx;
1129: PetscFunctionBegin;
1130: scale->coef = coeff;
1131: PetscFunctionReturn(PETSC_SUCCESS);
1132: }
1134: /*@C
1135: KSPMonitorDynamicTolerance - A monitor that changes the inner tolerance of nested preconditioners in every outer iteration in an adaptive way.
1137: Collective
1139: Input Parameters:
1140: + ksp - iterative context
1141: . n - iteration number (not used)
1142: . fnorm - the current residual norm
1143: - ctx - context used by monitor
1145: Options Database Key:
1146: . -sub_ksp_dynamic_tolerance <coef> - coefficient of dynamic tolerance for inner solver, default is 1.0
1148: Level: advanced
1150: Notes:
1151: Applies for `PCKSP`, `PCBJACOBI`, and `PCDEFLATION` preconditioners
1153: This may be useful for a flexible preconditioned Krylov method, such as `KSPFGMRES`, [](sec_flexibleksp) to
1154: control the accuracy of the inner solves needed to guarantee convergence of the outer iterations.
1156: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
1157: to be used during the `KSP` solve.
1159: Use `KSPMonitorDynamicToleranceCreate()` and `KSPMonitorDynamicToleranceSetCoefficient()` to create the context needed by this
1160: monitor function.
1162: Pass the context and `KSPMonitorDynamicToleranceDestroy()` to `KSPMonitorSet()`
1164: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicToleranceCreate()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceSetCoefficient()`
1165: @*/
1166: PetscErrorCode KSPMonitorDynamicTolerance(KSP ksp, PetscInt its, PetscReal fnorm, void *dummy)
1167: {
1168: PC pc;
1169: PetscReal outer_rtol, outer_abstol, outer_dtol, inner_rtol;
1170: PetscInt outer_maxits, nksp, first, i;
1171: KSPDynTolCtx *scale = (KSPDynTolCtx *)dummy;
1172: KSP *subksp = NULL;
1173: KSP kspinner;
1174: PetscBool flg;
1176: PetscFunctionBegin;
1177: PetscCall(KSPGetPC(ksp, &pc));
1179: /* compute inner_rtol */
1180: if (scale->bnrm < 0.0) {
1181: Vec b;
1182: PetscCall(KSPGetRhs(ksp, &b));
1183: PetscCall(VecNorm(b, NORM_2, &(scale->bnrm)));
1184: }
1185: PetscCall(KSPGetTolerances(ksp, &outer_rtol, &outer_abstol, &outer_dtol, &outer_maxits));
1186: inner_rtol = PetscMin(scale->coef * scale->bnrm * outer_rtol / fnorm, 0.999);
1188: /* if pc is ksp */
1189: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCKSP, &flg));
1190: if (flg) {
1191: PetscCall(PCKSPGetKSP(pc, &kspinner));
1192: PetscCall(KSPSetTolerances(kspinner, inner_rtol, outer_abstol, outer_dtol, outer_maxits));
1193: PetscFunctionReturn(PETSC_SUCCESS);
1194: }
1196: /* if pc is bjacobi */
1197: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCBJACOBI, &flg));
1198: if (flg) {
1199: PetscCall(PCBJacobiGetSubKSP(pc, &nksp, &first, &subksp));
1200: if (subksp) {
1201: for (i = 0; i < nksp; i++) PetscCall(KSPSetTolerances(subksp[i], inner_rtol, outer_abstol, outer_dtol, outer_maxits));
1202: PetscFunctionReturn(PETSC_SUCCESS);
1203: }
1204: }
1206: /* if pc is deflation*/
1207: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCDEFLATION, &flg));
1208: if (flg) {
1209: PetscCall(PCDeflationGetCoarseKSP(pc, &kspinner));
1210: PetscCall(KSPSetTolerances(kspinner, inner_rtol, outer_abstol, outer_dtol, PETSC_DEFAULT));
1211: PetscFunctionReturn(PETSC_SUCCESS);
1212: }
1214: /* todo: dynamic tolerance may apply to other types of pc */
1215: PetscFunctionReturn(PETSC_SUCCESS);
1216: }
1218: /*@C
1219: KSPMonitorDynamicToleranceDestroy - Destroy the monitor context used in `KSPMonitorDynamicTolerance()`
1221: Input Parameter:
1222: . ctx - the monitor context
1224: Level: advanced
1226: Note:
1227: This is not called directly but is passed to `KSPMonitorSet()` along with `KSPMonitorDynamicTolerance()`
1229: .seealso: `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorSet()`, `KSPMonitorDynamicToleranceCreate()`
1230: @*/
1231: PetscErrorCode KSPMonitorDynamicToleranceDestroy(void **ctx)
1232: {
1233: PetscFunctionBegin;
1234: PetscCall(PetscFree(*ctx));
1235: PetscFunctionReturn(PETSC_SUCCESS);
1236: }
1238: /*@C
1239: KSPConvergedSkip - Convergence test that do not return as converged
1240: until the maximum number of iterations is reached.
1242: Collective
1244: Input Parameters:
1245: + ksp - iterative context
1246: . n - iteration number
1247: . rnorm - 2-norm residual value (may be estimated)
1248: - dummy - unused convergence context
1250: Output Parameter:
1251: . reason - `KSP_CONVERGED_ITERATING`, `KSP_CONVERGED_ITS`
1253: Level: advanced
1255: Notes:
1256: This should be used as the convergence test with the option
1257: `KSPSetNormType`(ksp,`KSP_NORM_NONE`), since norms of the residual are
1258: not computed. Convergence is then declared after the maximum number
1259: of iterations have been reached. Useful when one is using `KSPCG` or
1260: `KSPBCGS`. [](sec_flexibleksp)
1262: .seealso: [](ch_ksp), `KSP`, `KSPCG`, `KSPBCGS`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPSetNormType()`, [](sec_flexibleksp),
1263: `KSPConvergedReason`
1264: @*/
1265: PetscErrorCode KSPConvergedSkip(KSP ksp, PetscInt n, PetscReal rnorm, KSPConvergedReason *reason, void *dummy)
1266: {
1267: PetscFunctionBegin;
1270: *reason = KSP_CONVERGED_ITERATING;
1271: if (n >= ksp->max_it) *reason = KSP_CONVERGED_ITS;
1272: PetscFunctionReturn(PETSC_SUCCESS);
1273: }
1275: /*@
1276: KSPSetConvergedNegativeCurvature - Allows to declare convergence and return `KSP_CONVERGED_NEG_CURVE` when negative curvature is detected
1278: Collective
1280: Input Parameters:
1281: + ksp - iterative context
1282: - flg - the Boolean value
1284: Options Database Key:
1285: . -ksp_converged_neg_curve <bool> - Declare convergence if negative curvature is detected
1287: Level: advanced
1289: Notes:
1290: This is currently used only by a subset of the Krylov solvers, namely `KSPCG`, `KSPSTCG`, `KSPQCG`, `KSPGLTR`, `KSPNASH`, and `KSPMINRES`.
1292: .seealso: [](ch_ksp), `KSP`, `KSPConvergedReason`, `KSPGetConvergedNegativeCurvature()`
1293: @*/
1294: PetscErrorCode KSPSetConvergedNegativeCurvature(KSP ksp, PetscBool flg)
1295: {
1296: PetscFunctionBegin;
1299: ksp->converged_neg_curve = flg;
1300: PetscFunctionReturn(PETSC_SUCCESS);
1301: }
1303: /*@
1304: KSPGetConvergedNegativeCurvature - Get the flag to declare convergence if negative curvature is detected
1306: Collective
1308: Input Parameter:
1309: . ksp - iterative context
1311: Output Parameter:
1312: . flg - the Boolean value
1314: Level: advanced
1316: .seealso: [](ch_ksp), `KSP`, `KSPConvergedReason`, `KSPSetConvergedNegativeCurvature()`
1317: @*/
1318: PetscErrorCode KSPGetConvergedNegativeCurvature(KSP ksp, PetscBool *flg)
1319: {
1320: PetscFunctionBegin;
1323: *flg = ksp->converged_neg_curve;
1324: PetscFunctionReturn(PETSC_SUCCESS);
1325: }
1327: /*@C
1328: KSPConvergedDefaultCreate - Creates and initializes the context used by the `KSPConvergedDefault()` function
1330: Not Collective
1332: Output Parameter:
1333: . ctx - convergence context
1335: Level: intermediate
1337: .seealso: [](ch_ksp), `KSP`, `KSPConvergedDefault()`, `KSPConvergedDefaultDestroy()`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`,
1338: `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`,
1339: `KSPConvergedDefaultSetConvergedMaxits()`
1340: @*/
1341: PetscErrorCode KSPConvergedDefaultCreate(void **ctx)
1342: {
1343: KSPConvergedDefaultCtx *cctx;
1345: PetscFunctionBegin;
1346: PetscCall(PetscNew(&cctx));
1347: *ctx = cctx;
1348: PetscFunctionReturn(PETSC_SUCCESS);
1349: }
1351: /*@
1352: KSPConvergedDefaultSetUIRNorm - makes the default convergence test use || B*(b - A*(initial guess))||
1353: instead of || B*b ||. In the case of right preconditioner or if `KSPSetNormType`(ksp,`KSP_NORM_UNPRECONDITIONED`)
1354: is used there is no B in the above formula. UIRNorm is short for Use Initial Residual Norm.
1356: Collective
1358: Input Parameters:
1359: . ksp - iterative context
1361: Options Database Key:
1362: . -ksp_converged_use_initial_residual_norm <bool> - Use initial residual norm for computing relative convergence
1364: Level: intermediate
1366: Notes:
1367: Use `KSPSetTolerances()` to alter the defaults for rtol, abstol, dtol.
1369: The precise values of reason are macros such as `KSP_CONVERGED_RTOL`, which
1370: are defined in petscksp.h.
1372: If the convergence test is not `KSPConvergedDefault()` then this is ignored.
1374: If right preconditioning is being used then B does not appear in the above formula.
1376: .seealso: [](ch_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`
1377: @*/
1378: PetscErrorCode KSPConvergedDefaultSetUIRNorm(KSP ksp)
1379: {
1380: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1382: PetscFunctionBegin;
1384: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1385: PetscCheck(!ctx->mininitialrtol, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "Cannot use KSPConvergedDefaultSetUIRNorm() and KSPConvergedDefaultSetUMIRNorm() together");
1386: ctx->initialrtol = PETSC_TRUE;
1387: PetscFunctionReturn(PETSC_SUCCESS);
1388: }
1390: /*@
1391: KSPConvergedDefaultSetUMIRNorm - makes the default convergence test use min(|| B*(b - A*(initial guess))||,|| B*b ||)
1392: In the case of right preconditioner or if `KSPSetNormType`(ksp,`KSP_NORM_UNPRECONDITIONED`)
1393: is used there is no B in the above formula. UMIRNorm is short for Use Minimum Initial Residual Norm.
1395: Collective
1397: Input Parameters:
1398: . ksp - iterative context
1400: Options Database Key:
1401: . -ksp_converged_use_min_initial_residual_norm <bool> - Use minimum of initial residual norm and b for computing relative convergence
1403: Level: intermediate
1405: Use `KSPSetTolerances()` to alter the defaults for rtol, abstol, dtol.
1407: The precise values of reason are macros such as `KSP_CONVERGED_RTOL`, which
1408: are defined in petscksp.h.
1410: .seealso: [](ch_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`
1411: @*/
1412: PetscErrorCode KSPConvergedDefaultSetUMIRNorm(KSP ksp)
1413: {
1414: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1416: PetscFunctionBegin;
1418: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1419: PetscCheck(!ctx->initialrtol, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "Cannot use KSPConvergedDefaultSetUIRNorm() and KSPConvergedDefaultSetUMIRNorm() together");
1420: ctx->mininitialrtol = PETSC_TRUE;
1421: PetscFunctionReturn(PETSC_SUCCESS);
1422: }
1424: /*@
1425: KSPConvergedDefaultSetConvergedMaxits - allows the default convergence test to declare convergence and return `KSP_CONVERGED_ITS` if the maximum number of iterations is reached
1427: Collective
1429: Input Parameters:
1430: + ksp - iterative context
1431: - flg - boolean flag
1433: Options Database Key:
1434: . -ksp_converged_maxits <bool> - Declare convergence if the maximum number of iterations is reached
1436: Level: intermediate
1438: Note:
1439: The precise values of reason available in `KSPConvergedReason`
1441: .seealso: [](ch_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetUIRNorm()`
1442: @*/
1443: PetscErrorCode KSPConvergedDefaultSetConvergedMaxits(KSP ksp, PetscBool flg)
1444: {
1445: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1447: PetscFunctionBegin;
1450: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1451: ctx->convmaxits = flg;
1452: PetscFunctionReturn(PETSC_SUCCESS);
1453: }
1455: /*@C
1456: KSPConvergedDefault - Default code to determine convergence of the linear iterative solvers
1458: Collective
1460: Input Parameters:
1461: + ksp - iterative context
1462: . n - iteration number
1463: . rnorm - residual norm (may be estimated, depending on the method may be the preconditioned residual norm)
1464: - ctx - convergence context which must be created by `KSPConvergedDefaultCreate()`
1466: Output Parameter:
1467: . reason - the convergence reason; it is positive if the iteration has converged,
1468: negative if the iteration has diverged, and `KSP_CONVERGED_ITERATING` otherwise
1470: Options Database Keys:
1471: + -ksp_max_it - maximum number of linear iterations
1472: . -ksp_rtol rtol - relative tolerance used in default determination of convergence, i.e. if residual norm decreases by this factor than convergence is declared
1473: . -ksp_atol abstol - absolute tolerance used in default convergence test, i.e. if residual norm is less than this then convergence is declared
1474: . -ksp_divtol tol - if residual norm increases by this factor than divergence is declared
1475: . -ksp_converged_use_initial_residual_norm - see `KSPConvergedDefaultSetUIRNorm()`
1476: . -ksp_converged_use_min_initial_residual_norm - see `KSPConvergedDefaultSetUMIRNorm()`
1477: - -ksp_converged_maxits - see `KSPConvergedDefaultSetConvergedMaxits()`
1479: Level: advanced
1481: Notes:
1482: `KSPConvergedDefault()` reaches convergence when rnorm < MAX (rtol * rnorm_0, abstol);
1483: Divergence is detected if rnorm > dtol * rnorm_0, or when failures are detected throughout the iteration.
1484: By default, reaching the maximum number of iterations is considered divergence (i.e. KSP_DIVERGED_ITS).
1485: In order to have PETSc declaring convergence in such a case (i.e. `KSP_CONVERGED_ITS`), users can use `KSPConvergedDefaultSetConvergedMaxits()`
1487: where:
1488: + rtol - relative tolerance,
1489: . abstol - absolute tolerance.
1490: . dtol - divergence tolerance,
1491: - rnorm_0 - the two norm of the right hand side (or the preconditioned norm, depending on what was set with
1492: `KSPSetNormType()`. When initial guess is non-zero you
1493: can call `KSPConvergedDefaultSetUIRNorm()` to use the norm of (b - A*(initial guess))
1494: as the starting point for relative norm convergence testing, that is as rnorm_0.
1495: Call `KSPConvergedDefaultSetUMIRNorm()` to use the minimum of the norm of (b - A*(initial guess)) and the norm of b as the starting point.
1497: Use `KSPSetTolerances()` to alter the defaults for rtol, abstol, dtol.
1499: Use `KSPSetNormType()` (or -ksp_norm_type <none,preconditioned,unpreconditioned,natural>) to change the norm used for computing rnorm
1501: The precise values of reason are available in `KSPConvergedReason`
1503: This routine is used by `KSP` by default so the user generally never needs call it directly.
1505: Use `KSPSetConvergenceTest()` to provide your own test instead of using this one.
1507: Call `KSPSetConvergenceTest()` with the ctx, as created above and the destruction function `KSPConvergedDefaultDestroy()`
1509: .seealso: [](ch_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`,
1510: `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`, `KSPConvergedDefaultCreate()`, `KSPConvergedDefaultDestroy()`
1511: @*/
1512: PetscErrorCode KSPConvergedDefault(KSP ksp, PetscInt n, PetscReal rnorm, KSPConvergedReason *reason, void *ctx)
1513: {
1514: KSPConvergedDefaultCtx *cctx = (KSPConvergedDefaultCtx *)ctx;
1515: KSPNormType normtype;
1517: PetscFunctionBegin;
1521: PetscCheck(cctx, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_NULL, "Convergence context must have been created with KSPConvergedDefaultCreate()");
1522: *reason = KSP_CONVERGED_ITERATING;
1524: if (cctx->convmaxits && n >= ksp->max_it) {
1525: *reason = KSP_CONVERGED_ITS;
1526: PetscCall(PetscInfo(ksp, "Linear solver has converged. Maximum number of iterations reached %" PetscInt_FMT "\n", n));
1527: PetscFunctionReturn(PETSC_SUCCESS);
1528: }
1529: PetscCall(KSPGetNormType(ksp, &normtype));
1530: if (normtype == KSP_NORM_NONE) PetscFunctionReturn(PETSC_SUCCESS);
1532: if (!n) {
1533: /* if user gives initial guess need to compute norm of b */
1534: if (!ksp->guess_zero && !cctx->initialrtol) {
1535: PetscReal snorm = 0.0;
1536: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->pc_side == PC_RIGHT) {
1537: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing 2-norm of RHS\n"));
1538: PetscCall(VecNorm(ksp->vec_rhs, NORM_2, &snorm)); /* <- b'*b */
1539: } else {
1540: Vec z;
1541: /* Should avoid allocating the z vector each time but cannot stash it in cctx because if KSPReset() is called the vector size might change */
1542: PetscCall(VecDuplicate(ksp->vec_rhs, &z));
1543: PetscCall(KSP_PCApply(ksp, ksp->vec_rhs, z));
1544: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
1545: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing 2-norm of preconditioned RHS\n"));
1546: PetscCall(VecNorm(z, NORM_2, &snorm)); /* dp <- b'*B'*B*b */
1547: } else if (ksp->normtype == KSP_NORM_NATURAL) {
1548: PetscScalar norm;
1549: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing natural norm of RHS\n"));
1550: PetscCall(VecDot(ksp->vec_rhs, z, &norm));
1551: snorm = PetscSqrtReal(PetscAbsScalar(norm)); /* dp <- b'*B*b */
1552: }
1553: PetscCall(VecDestroy(&z));
1554: }
1555: /* handle special case of zero RHS and nonzero guess */
1556: if (!snorm) {
1557: PetscCall(PetscInfo(ksp, "Special case, user has provided nonzero initial guess and zero RHS\n"));
1558: snorm = rnorm;
1559: }
1560: if (cctx->mininitialrtol) ksp->rnorm0 = PetscMin(snorm, rnorm);
1561: else ksp->rnorm0 = snorm;
1562: } else {
1563: ksp->rnorm0 = rnorm;
1564: }
1565: ksp->ttol = PetscMax(ksp->rtol * ksp->rnorm0, ksp->abstol);
1566: }
1568: if (n <= ksp->chknorm) PetscFunctionReturn(PETSC_SUCCESS);
1570: if (PetscIsInfOrNanReal(rnorm)) {
1571: PCFailedReason pcreason;
1572: PetscInt sendbuf, recvbuf;
1573: PetscCall(PCGetFailedReasonRank(ksp->pc, &pcreason));
1574: sendbuf = (PetscInt)pcreason;
1575: PetscCall(MPIU_Allreduce(&sendbuf, &recvbuf, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)ksp)));
1576: if (recvbuf) {
1577: *reason = KSP_DIVERGED_PC_FAILED;
1578: PetscCall(PCSetFailedReason(ksp->pc, (PCFailedReason)recvbuf));
1579: PetscCall(PetscInfo(ksp, "Linear solver pcsetup fails, declaring divergence \n"));
1580: } else {
1581: *reason = KSP_DIVERGED_NANORINF;
1582: PetscCall(PetscInfo(ksp, "Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n"));
1583: }
1584: } else if (rnorm <= ksp->ttol) {
1585: if (rnorm < ksp->abstol) {
1586: 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));
1587: *reason = KSP_CONVERGED_ATOL;
1588: } else {
1589: if (cctx->initialrtol) {
1590: 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));
1591: } else {
1592: 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));
1593: }
1594: *reason = KSP_CONVERGED_RTOL;
1595: }
1596: } else if (rnorm >= ksp->divtol * ksp->rnorm0) {
1597: 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));
1598: *reason = KSP_DIVERGED_DTOL;
1599: }
1600: PetscFunctionReturn(PETSC_SUCCESS);
1601: }
1603: /*@C
1604: KSPConvergedDefaultDestroy - Frees the space used by the `KSPConvergedDefault()` function context
1606: Not Collective
1608: Input Parameter:
1609: . ctx - convergence context
1611: Level: intermediate
1613: Note:
1614: Pass this function name into `KSPSetConvergenceTest()` along with the context obtained with `KSPConvergedDefaultCreate()` and `KSPConvergedDefault()`
1616: .seealso: [](ch_ksp), `KSP`, `KSPConvergedDefault()`, `KSPConvergedDefaultCreate()`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`,
1617: `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`
1618: @*/
1619: PetscErrorCode KSPConvergedDefaultDestroy(void *ctx)
1620: {
1621: KSPConvergedDefaultCtx *cctx = (KSPConvergedDefaultCtx *)ctx;
1623: PetscFunctionBegin;
1624: PetscCall(VecDestroy(&cctx->work));
1625: PetscCall(PetscFree(ctx));
1626: PetscFunctionReturn(PETSC_SUCCESS);
1627: }
1629: /*
1630: KSPBuildSolutionDefault - Default code to create/move the solution.
1632: Collective
1634: Input Parameters:
1635: + ksp - iterative context
1636: - v - pointer to the user's vector
1638: Output Parameter:
1639: . V - pointer to a vector containing the solution
1641: Level: advanced
1643: Developers Note:
1644: This is PETSC_EXTERN because it may be used by user written plugin `KSPType` implementations
1646: .seealso: [](ch_ksp), `KSP`, `KSPGetSolution()`, `KSPBuildResidualDefault()`
1647: */
1648: PetscErrorCode KSPBuildSolutionDefault(KSP ksp, Vec v, Vec *V)
1649: {
1650: PetscFunctionBegin;
1651: if (ksp->pc_side == PC_RIGHT) {
1652: if (ksp->pc) {
1653: PetscCheck(v, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with right preconditioner");
1654: PetscCall(KSP_PCApply(ksp, ksp->vec_sol, v));
1655: *V = v;
1656: } else {
1657: if (v) {
1658: PetscCall(VecCopy(ksp->vec_sol, v));
1659: *V = v;
1660: } else *V = ksp->vec_sol;
1661: }
1662: } else if (ksp->pc_side == PC_SYMMETRIC) {
1663: if (ksp->pc) {
1664: PetscCheck(!ksp->transpose_solve, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with symmetric preconditioner and transpose solve");
1665: PetscCheck(v, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with symmetric preconditioner");
1666: PetscCall(PCApplySymmetricRight(ksp->pc, ksp->vec_sol, v));
1667: *V = v;
1668: } else {
1669: if (v) {
1670: PetscCall(VecCopy(ksp->vec_sol, v));
1671: *V = v;
1672: } else *V = ksp->vec_sol;
1673: }
1674: } else {
1675: if (v) {
1676: PetscCall(VecCopy(ksp->vec_sol, v));
1677: *V = v;
1678: } else *V = ksp->vec_sol;
1679: }
1680: PetscFunctionReturn(PETSC_SUCCESS);
1681: }
1683: /*
1684: KSPBuildResidualDefault - Default code to compute the residual.
1686: Collecive on ksp
1688: Input Parameters:
1689: . ksp - iterative context
1690: . t - pointer to temporary vector
1691: . v - pointer to user vector
1693: Output Parameter:
1694: . V - pointer to a vector containing the residual
1696: Level: advanced
1698: Developers Note:
1699: This is PETSC_EXTERN because it may be used by user written plugin `KSPType` implementations
1701: .seealso: [](ch_ksp), `KSP`, `KSPBuildSolutionDefault()`
1702: */
1703: PetscErrorCode KSPBuildResidualDefault(KSP ksp, Vec t, Vec v, Vec *V)
1704: {
1705: Mat Amat, Pmat;
1707: PetscFunctionBegin;
1708: if (!ksp->pc) PetscCall(KSPGetPC(ksp, &ksp->pc));
1709: PetscCall(PCGetOperators(ksp->pc, &Amat, &Pmat));
1710: PetscCall(KSPBuildSolution(ksp, t, NULL));
1711: PetscCall(KSP_MatMult(ksp, Amat, t, v));
1712: PetscCall(VecAYPX(v, -1.0, ksp->vec_rhs));
1713: *V = v;
1714: PetscFunctionReturn(PETSC_SUCCESS);
1715: }
1717: /*@C
1718: KSPCreateVecs - Gets a number of work vectors suitably sized for the operator in the `KSP`
1720: Collective
1722: Input Parameters:
1723: + ksp - iterative context
1724: . rightn - number of right work vectors
1725: - leftn - number of left work vectors to allocate
1727: Output Parameters:
1728: + right - the array of vectors created
1729: - left - the array of left vectors
1731: Level: advanced
1733: Notes:
1734: The right vector has as many elements as the matrix has columns. The left
1735: vector has as many elements as the matrix has rows.
1737: The vectors are new vectors that are not owned by the `KSP`, they should be destroyed with calls to `VecDestroyVecs()` when no longer needed.
1739: Developers Note:
1740: 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
1741: that does not exist tries to get them from the `DM` (if it is provided).
1743: .seealso: [](ch_ksp), `MatCreateVecs()`, `VecDestroyVecs()`, `KSPSetWorkVecs()`
1744: @*/
1745: PetscErrorCode KSPCreateVecs(KSP ksp, PetscInt rightn, Vec **right, PetscInt leftn, Vec **left)
1746: {
1747: Vec vecr = NULL, vecl = NULL;
1748: PetscBool matset, pmatset, isshell, preferdm = PETSC_FALSE;
1749: Mat mat = NULL;
1751: PetscFunctionBegin;
1752: if (ksp->dm) {
1753: PetscCall(PetscObjectTypeCompare((PetscObject)ksp->dm, DMSHELL, &isshell));
1754: preferdm = isshell ? PETSC_FALSE : PETSC_TRUE;
1755: }
1756: if (rightn) {
1757: PetscCheck(right, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_INCOMP, "You asked for right vectors but did not pass a pointer to hold them");
1758: if (ksp->vec_sol) vecr = ksp->vec_sol;
1759: else {
1760: if (preferdm) {
1761: PetscCall(DMGetGlobalVector(ksp->dm, &vecr));
1762: } else if (ksp->pc) {
1763: PetscCall(PCGetOperatorsSet(ksp->pc, &matset, &pmatset));
1764: /* check for mat before pmat because for KSPLSQR pmat may be a different size than mat since pmat maybe mat'*mat */
1765: if (matset) {
1766: PetscCall(PCGetOperators(ksp->pc, &mat, NULL));
1767: PetscCall(MatCreateVecs(mat, &vecr, NULL));
1768: } else if (pmatset) {
1769: PetscCall(PCGetOperators(ksp->pc, NULL, &mat));
1770: PetscCall(MatCreateVecs(mat, &vecr, NULL));
1771: }
1772: }
1773: if (!vecr && ksp->dm) PetscCall(DMGetGlobalVector(ksp->dm, &vecr));
1774: PetscCheck(vecr, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "You requested a vector from a KSP that cannot provide one");
1775: }
1776: PetscCall(VecDuplicateVecs(vecr, rightn, right));
1777: if (!ksp->vec_sol) {
1778: if (preferdm) {
1779: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecr));
1780: } else if (mat) {
1781: PetscCall(VecDestroy(&vecr));
1782: } else if (ksp->dm) {
1783: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecr));
1784: }
1785: }
1786: }
1787: if (leftn) {
1788: PetscCheck(left, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_INCOMP, "You asked for left vectors but did not pass a pointer to hold them");
1789: if (ksp->vec_rhs) vecl = ksp->vec_rhs;
1790: else {
1791: if (preferdm) {
1792: PetscCall(DMGetGlobalVector(ksp->dm, &vecl));
1793: } else if (ksp->pc) {
1794: PetscCall(PCGetOperatorsSet(ksp->pc, &matset, &pmatset));
1795: /* check for mat before pmat because for KSPLSQR pmat may be a different size than mat since pmat maybe mat'*mat */
1796: if (matset) {
1797: PetscCall(PCGetOperators(ksp->pc, &mat, NULL));
1798: PetscCall(MatCreateVecs(mat, NULL, &vecl));
1799: } else if (pmatset) {
1800: PetscCall(PCGetOperators(ksp->pc, NULL, &mat));
1801: PetscCall(MatCreateVecs(mat, NULL, &vecl));
1802: }
1803: }
1804: if (!vecl && ksp->dm) PetscCall(DMGetGlobalVector(ksp->dm, &vecl));
1805: PetscCheck(vecl, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "You requested a vector from a KSP that cannot provide one");
1806: }
1807: PetscCall(VecDuplicateVecs(vecl, leftn, left));
1808: if (!ksp->vec_rhs) {
1809: if (preferdm) {
1810: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecl));
1811: } else if (mat) {
1812: PetscCall(VecDestroy(&vecl));
1813: } else if (ksp->dm) {
1814: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecl));
1815: }
1816: }
1817: }
1818: PetscFunctionReturn(PETSC_SUCCESS);
1819: }
1821: /*@C
1822: KSPSetWorkVecs - Sets a number of work vectors into a `KSP` object
1824: Collective
1826: Input Parameters:
1827: + ksp - iterative context
1828: - nw - number of work vectors to allocate
1830: Level: developer
1832: Developers Note:
1833: This is PETSC_EXTERN because it may be used by user written plugin `KSPType` implementations
1835: .seealso: [](ch_ksp), `KSP`, `KSPCreateVecs()`
1836: @*/
1837: PetscErrorCode KSPSetWorkVecs(KSP ksp, PetscInt nw)
1838: {
1839: PetscFunctionBegin;
1840: PetscCall(VecDestroyVecs(ksp->nwork, &ksp->work));
1841: ksp->nwork = nw;
1842: PetscCall(KSPCreateVecs(ksp, nw, &ksp->work, 0, NULL));
1843: PetscFunctionReturn(PETSC_SUCCESS);
1844: }
1846: /*
1847: KSPDestroyDefault - Destroys a iterative context variable for methods with no separate context. Preferred calling sequence `KSPDestroy()`.
1849: Input Parameter:
1850: . ksp - the iterative context
1852: Developers Note:
1853: This is PETSC_EXTERN because it may be used by user written plugin `KSPType` implementations
1855: */
1856: PetscErrorCode KSPDestroyDefault(KSP ksp)
1857: {
1858: PetscFunctionBegin;
1860: PetscCall(PetscFree(ksp->data));
1861: PetscFunctionReturn(PETSC_SUCCESS);
1862: }
1864: /*@
1865: KSPGetConvergedReason - Gets the reason the `KSP` iteration was stopped.
1867: Not Collective
1869: Input Parameter:
1870: . ksp - the `KSP` context
1872: Output Parameter:
1873: . reason - negative value indicates diverged, positive value converged, see `KSPConvergedReason` for the possible values
1875: Options Database Key:
1876: . -ksp_converged_reason - prints the reason to standard out
1878: Level: intermediate
1880: Notes:
1881: If this routine is called before or doing the `KSPSolve()` the value of `KSP_CONVERGED_ITERATING` is returned
1883: .seealso: [](ch_ksp), `KSPConvergedReason`, `KSP`, `KSPSetConvergenceTest()`, `KSPConvergedDefault()`, `KSPSetTolerances()`, `KSPConvergedReason`,
1884: `KSPConvergedReasonView()`
1885: @*/
1886: PetscErrorCode KSPGetConvergedReason(KSP ksp, KSPConvergedReason *reason)
1887: {
1888: PetscFunctionBegin;
1891: *reason = ksp->reason;
1892: PetscFunctionReturn(PETSC_SUCCESS);
1893: }
1895: /*@C
1896: KSPGetConvergedReasonString - Return a human readable string for a `KSPConvergedReason`
1898: Not Collective
1900: Input Parameter:
1901: . ksp - the `KSP` context
1903: Output Parameter:
1904: . strreason - a human readable string that describes ksp converged reason
1906: Level: beginner
1908: .seealso: [](ch_ksp), `KSP`, `KSPGetConvergedReason()`
1909: @*/
1910: PetscErrorCode KSPGetConvergedReasonString(KSP ksp, const char **strreason)
1911: {
1912: PetscFunctionBegin;
1915: *strreason = KSPConvergedReasons[ksp->reason];
1916: PetscFunctionReturn(PETSC_SUCCESS);
1917: }
1919: #include <petsc/private/dmimpl.h>
1920: /*@
1921: KSPSetDM - Sets the `DM` that may be used by some preconditioners
1923: Logically Collective
1925: Input Parameters:
1926: + ksp - the `KSP`
1927: - dm - the `DM`, cannot be `NULL` to remove a previously set `DM`
1929: Level: intermediate
1931: Notes:
1932: If this is used then the `KSP` will attempt to use the `DM` to create the matrix and use the routine set with
1933: `DMKSPSetComputeOperators()`. Use `KSPSetDMActive`(ksp,`PETSC_FALSE`) to instead use the matrix you've provided with
1934: `KSPSetOperators()`.
1936: A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
1937: even when not using interfaces like `DMKSPSetComputeOperators()`. Use `DMClone()` to get a distinct `DM` when solving
1938: different problems using the same function space.
1940: .seealso: [](ch_ksp), `KSP`, `DM`, `KSPGetDM()`, `KSPSetDMActive()`, `KSPSetComputeOperators()`, `KSPSetComputeRHS()`, `KSPSetComputeInitialGuess()`, `DMKSPSetComputeOperators()`, `DMKSPSetComputeRHS()`, `DMKSPSetComputeInitialGuess()`
1941: @*/
1942: PetscErrorCode KSPSetDM(KSP ksp, DM dm)
1943: {
1944: PC pc;
1946: PetscFunctionBegin;
1949: PetscCall(PetscObjectReference((PetscObject)dm));
1950: if (ksp->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
1951: if (ksp->dm->dmksp && !dm->dmksp) {
1952: DMKSP kdm;
1953: PetscCall(DMCopyDMKSP(ksp->dm, dm));
1954: PetscCall(DMGetDMKSP(ksp->dm, &kdm));
1955: if (kdm->originaldm == ksp->dm) kdm->originaldm = dm; /* Grant write privileges to the replacement DM */
1956: }
1957: PetscCall(DMDestroy(&ksp->dm));
1958: }
1959: ksp->dm = dm;
1960: ksp->dmAuto = PETSC_FALSE;
1961: PetscCall(KSPGetPC(ksp, &pc));
1962: PetscCall(PCSetDM(pc, dm));
1963: ksp->dmActive = PETSC_TRUE;
1964: PetscFunctionReturn(PETSC_SUCCESS);
1965: }
1967: /*@
1968: KSPSetDMActive - Indicates the `DM` should be used to generate the linear system matrix and right hand side vector
1970: Logically Collective
1972: Input Parameters:
1973: + ksp - the `KSP`
1974: - flg - use the `DM`
1976: Level: intermediate
1978: Note:
1979: 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.
1981: .seealso: [](ch_ksp), `KSP`, `DM`, `KSPGetDM()`, `KSPSetDM()`, `SNESSetDM()`, `KSPSetComputeOperators()`, `KSPSetComputeRHS()`, `KSPSetComputeInitialGuess()`
1982: @*/
1983: PetscErrorCode KSPSetDMActive(KSP ksp, PetscBool flg)
1984: {
1985: PetscFunctionBegin;
1988: ksp->dmActive = flg;
1989: PetscFunctionReturn(PETSC_SUCCESS);
1990: }
1992: /*@
1993: KSPGetDM - Gets the `DM` that may be used by some preconditioners
1995: Not Collective
1997: Input Parameter:
1998: . ksp - the `KSP`
2000: Output Parameter:
2001: . dm - the `DM`
2003: Level: intermediate
2005: .seealso: [](ch_ksp), `KSP`, `DM`, `KSPSetDM()`, `KSPSetDMActive()`
2006: @*/
2007: PetscErrorCode KSPGetDM(KSP ksp, DM *dm)
2008: {
2009: PetscFunctionBegin;
2011: if (!ksp->dm) {
2012: PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ksp), &ksp->dm));
2013: ksp->dmAuto = PETSC_TRUE;
2014: }
2015: *dm = ksp->dm;
2016: PetscFunctionReturn(PETSC_SUCCESS);
2017: }
2019: /*@
2020: KSPSetApplicationContext - Sets the optional user-defined context for the linear solver.
2022: Logically Collective
2024: Input Parameters:
2025: + ksp - the `KSP` context
2026: - usrP - optional user context
2028: Level: intermediate
2030: Notes:
2031: 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`
2033: Use `KSPGetApplicationContext()` to get access to the context at a later time.
2035: Fortran Note:
2036: To use this from Fortran you must write a Fortran interface definition for this
2037: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2039: .seealso: [](ch_ksp), `KSP`, `KSPGetApplicationContext()`
2040: @*/
2041: PetscErrorCode KSPSetApplicationContext(KSP ksp, void *usrP)
2042: {
2043: PC pc;
2045: PetscFunctionBegin;
2047: ksp->user = usrP;
2048: PetscCall(KSPGetPC(ksp, &pc));
2049: PetscCall(PCSetApplicationContext(pc, usrP));
2050: PetscFunctionReturn(PETSC_SUCCESS);
2051: }
2053: /*@
2054: KSPGetApplicationContext - Gets the user-defined context for the linear solver set with `KSPSetApplicationContext()`
2056: Not Collective
2058: Input Parameter:
2059: . ksp - `KSP` context
2061: Output Parameter:
2062: . usrP - user context
2064: Level: intermediate
2066: Fortran Notes:
2067: To use this from Fortran you must write a Fortran interface definition for this
2068: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2070: .seealso: [](ch_ksp), `KSP`, `KSPSetApplicationContext()`
2071: @*/
2072: PetscErrorCode KSPGetApplicationContext(KSP ksp, void *usrP)
2073: {
2074: PetscFunctionBegin;
2076: *(void **)usrP = ksp->user;
2077: PetscFunctionReturn(PETSC_SUCCESS);
2078: }
2080: #include <petsc/private/pcimpl.h>
2082: /*@
2083: KSPCheckSolve - Checks if the `PCSetUp()` or `KSPSolve()` failed and set the error flag for the outer `PC`. A `KSP_DIVERGED_ITS` is
2084: not considered a failure in this context
2086: Collective
2088: Input Parameters:
2089: + ksp - the linear solver `KSP` context.
2090: . pc - the preconditioner context
2091: - vec - a vector that will be initialized with Inf to indicate lack of convergence
2093: Level: developer
2095: Note:
2096: This is called within `KSPSolve()` and `PCApply()` to check if an error has been detected on any particular MPI ranks. By initializing the vector
2097: with Inf the next call to `KSPCheckNorm()` or `KSPCheckDot()` will provide the same information to all the MPI ranks that an error occurred on
2098: at least one of the ranks.
2100: This may be called by a subset of the processes in the `PC`.
2102: Developer Note:
2103: This is used to manage returning with appropriate information from preconditioners whose inner `KSP` solvers have failed in some way
2105: .seealso: [](ch_ksp), `KSP`, `KSPCreate()`, `KSPSetType()`, `KSP`, `KSPCheckNorm()`, `KSPCheckDot()`
2106: @*/
2107: PetscErrorCode KSPCheckSolve(KSP ksp, PC pc, Vec vec)
2108: {
2109: PCFailedReason pcreason;
2110: PC subpc;
2112: PetscFunctionBegin;
2113: PetscCall(KSPGetPC(ksp, &subpc));
2114: PetscCall(PCGetFailedReason(subpc, &pcreason));
2115: if (pcreason || (ksp->reason < 0 && ksp->reason != KSP_DIVERGED_ITS)) {
2116: 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]);
2117: PetscCall(PetscInfo(ksp, "Detected not converged in KSP inner solve: KSP reason %s PC reason %s\n", KSPConvergedReasons[ksp->reason], PCFailedReasons[pcreason]));
2118: pc->failedreason = PC_SUBPC_ERROR;
2119: if (vec) PetscCall(VecSetInf(vec));
2120: }
2121: PetscFunctionReturn(PETSC_SUCCESS);
2122: }