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: Notes:
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: Certain solvers, under certain conditions, may not compute the final residual norm in an iteration, in that case the previous norm is returned.
32: .seealso: [](ch_ksp), `KSP`, `KSPSetNormType()`, `KSPBuildResidual()`, `KSPNormType`
33: @*/
34: PetscErrorCode KSPGetResidualNorm(KSP ksp, PetscReal *rnorm)
35: {
36: PetscFunctionBegin;
38: PetscAssertPointer(rnorm, 2);
39: *rnorm = ksp->rnorm;
40: PetscFunctionReturn(PETSC_SUCCESS);
41: }
43: /*@
44: KSPGetIterationNumber - Gets the current iteration number; if the `KSPSolve()` is complete, returns the number of iterations used.
46: Not Collective
48: Input Parameter:
49: . ksp - the iterative context
51: Output Parameter:
52: . its - number of iterations
54: Level: intermediate
56: Note:
57: During the ith iteration this returns i-1
59: .seealso: [](ch_ksp), `KSP`, `KSPGetResidualNorm()`, `KSPBuildResidual()`, `KSPGetTotalIterations()`
60: @*/
61: PetscErrorCode KSPGetIterationNumber(KSP ksp, PetscInt *its)
62: {
63: PetscFunctionBegin;
65: PetscAssertPointer(its, 2);
66: *its = ksp->its;
67: PetscFunctionReturn(PETSC_SUCCESS);
68: }
70: /*@
71: KSPGetTotalIterations - Gets the total number of iterations this `KSP` object has performed since was created, counted over all linear solves
73: Not Collective
75: Input Parameter:
76: . ksp - the iterative context
78: Output Parameter:
79: . its - total number of iterations
81: Level: intermediate
83: Note:
84: Use `KSPGetIterationNumber()` to get the count for the most recent solve only
85: If this is called within a `KSPSolve()` (such as in a `KSPMonitor` routine) then it does not include iterations within that current solve
87: .seealso: [](ch_ksp), `KSP`, `KSPBuildResidual()`, `KSPGetResidualNorm()`, `KSPGetIterationNumber()`
88: @*/
89: PetscErrorCode KSPGetTotalIterations(KSP ksp, PetscInt *its)
90: {
91: PetscFunctionBegin;
93: PetscAssertPointer(its, 2);
94: *its = ksp->totalits;
95: PetscFunctionReturn(PETSC_SUCCESS);
96: }
98: /*@
99: KSPMonitorResidual - Print the (possibly preconditioned, possibly approximate) residual norm at each iteration of an iterative solver.
101: Collective
103: Input Parameters:
104: + ksp - iterative context
105: . n - iteration number
106: . rnorm - (preconditioned) residual norm value (may be estimated).
107: - vf - The viewer context
109: Options Database Key:
110: . -ksp_monitor - Activates `KSPMonitorResidual()` to print the norm value at each iteration
112: Level: intermediate
114: Note:
115: For some methods, such as `KSPGMRES`, the norm is not computed directly from the residual.
117: The type of norm used by the method can be controlled with `KSPSetNormType()`
119: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
120: to be used during the `KSP` solve.
122: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidualView()`, `KSPMonitorResidualDrawLG()`,
123: `KSPMonitorResidualRange()`, `KSPMonitorTrueResidualDraw()`, `KSPMonitorTrueResidualDrawLG()`, `KSPMonitorTrueResidualMax()`,
124: `KSPMonitorSingularValue()`, `KSPMonitorSolutionDrawLG()`, `KSPMonitorSolutionDraw()`, `KSPMonitorSolution()`,
125: `KSPMonitorErrorDrawLG()`, `KSPMonitorErrorDraw()`, `KSPMonitorError()`
126: @*/
127: PetscErrorCode KSPMonitorResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
128: {
129: PetscViewer viewer = vf->viewer;
130: PetscViewerFormat format = vf->format;
131: PetscInt tablevel;
132: const char *prefix;
134: PetscFunctionBegin;
136: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
137: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
138: PetscCall(PetscViewerPushFormat(viewer, format));
139: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
140: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
141: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm %14.12e\n", n, (double)rnorm));
142: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
143: PetscCall(PetscViewerPopFormat(viewer));
144: PetscFunctionReturn(PETSC_SUCCESS);
145: }
147: /*@
148: KSPMonitorResidualView - Plots the (possibly preconditioned) residual at each iteration of an iterative solver.
150: Collective
152: Input Parameters:
153: + ksp - iterative context
154: . n - iteration number
155: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
156: - vf - The viewer context
158: Options Database Key:
159: . -ksp_monitor viewertype - Activates `KSPMonitorResidualView()`
161: Level: intermediate
163: Note:
164: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
165: to be used during the `KSP` solve.
167: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidual()`, `KSPMonitorResidualDrawLG()`
168: @*/
169: PetscErrorCode KSPMonitorResidualView(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
170: {
171: PetscViewer viewer = vf->viewer;
172: PetscViewerFormat format = vf->format;
173: Vec r;
175: PetscFunctionBegin;
177: PetscCall(PetscViewerPushFormat(viewer, format));
178: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
179: PetscCall(PetscObjectSetName((PetscObject)r, "Residual"));
180: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", (PetscObject)ksp));
181: PetscCall(VecView(r, viewer));
182: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", NULL));
183: PetscCall(VecDestroy(&r));
184: PetscCall(PetscViewerPopFormat(viewer));
185: PetscFunctionReturn(PETSC_SUCCESS);
186: }
188: /*@
189: KSPMonitorResidualDrawLG - Plots the (possibly preconditioned) residual norm at each iteration of an iterative solver.
191: Collective
193: Input Parameters:
194: + ksp - iterative context
195: . n - iteration number
196: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
197: - vf - The viewer context
199: Options Database Key:
200: . -ksp_monitor draw::draw_lg - Activates `KSPMonitorResidualDrawLG()`
202: Level: intermediate
204: Notes:
205: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
206: to be used during the `KSP` solve.
208: Use `KSPMonitorResidualDrawLGCreate()` to create the context used with this monitor
210: .seealso: [](ch_ksp), `KSP`, `PETSCVIEWERDRAW`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidualView()`, `KSPMonitorResidual()`
211: @*/
212: PetscErrorCode KSPMonitorResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
213: {
214: PetscViewer viewer = vf->viewer;
215: PetscViewerFormat format = vf->format;
216: PetscDrawLG lg;
217: KSPConvergedReason reason;
218: PetscReal x, y;
220: PetscFunctionBegin;
222: PetscCall(PetscViewerPushFormat(viewer, format));
223: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
224: if (!n) PetscCall(PetscDrawLGReset(lg));
225: x = (PetscReal)n;
226: if (rnorm > 0.0) y = PetscLog10Real(rnorm);
227: else y = -15.0;
228: PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
229: PetscCall(KSPGetConvergedReason(ksp, &reason));
230: if (n <= 20 || !(n % 5) || reason) {
231: PetscCall(PetscDrawLGDraw(lg));
232: PetscCall(PetscDrawLGSave(lg));
233: }
234: PetscCall(PetscViewerPopFormat(viewer));
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: /*@
239: KSPMonitorResidualDrawLGCreate - Creates the context for the (possibly preconditioned) residual norm monitor `KSPMonitorResidualDrawLG()`
241: Collective
243: Input Parameters:
244: + viewer - The `PetscViewer` of type `PETSCVIEWERDRAW`
245: . format - The viewer format
246: - ctx - An optional application context
248: Output Parameter:
249: . vf - The viewer context
251: Level: intermediate
253: .seealso: [](ch_ksp), `KSP`, `PETSCVIEWERDRAW`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidualDrawLG()`,
254: `PetscViewerFormat`, `PetscViewer`, `PetscViewerAndFormat`
255: @*/
256: PetscErrorCode KSPMonitorResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, PetscCtx ctx, PetscViewerAndFormat **vf)
257: {
258: PetscFunctionBegin;
259: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
260: (*vf)->data = ctx;
261: PetscCall(PetscViewerMonitorLGSetUp(viewer, NULL, NULL, "Log Residual Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300));
262: PetscFunctionReturn(PETSC_SUCCESS);
263: }
265: PetscErrorCode KSPMonitorRange_Private(KSP ksp, PetscInt it, PetscReal *per)
266: {
267: Vec resid;
268: const PetscScalar *r;
269: PetscReal rmax;
270: PetscInt i, n, N;
272: PetscFunctionBegin;
273: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &resid));
274: PetscCall(VecNorm(resid, NORM_INFINITY, &rmax));
275: PetscCall(VecGetLocalSize(resid, &n));
276: PetscCall(VecGetSize(resid, &N));
277: PetscCall(VecGetArrayRead(resid, &r));
278: *per = 0.0;
279: for (i = 0; i < n; ++i) *per += (PetscAbsScalar(r[i]) > .20 * rmax);
280: PetscCall(VecRestoreArrayRead(resid, &r));
281: PetscCall(VecDestroy(&resid));
282: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ksp)));
283: *per = *per / N;
284: PetscFunctionReturn(PETSC_SUCCESS);
285: }
287: /*@
288: KSPMonitorResidualRange - Prints the percentage of residual elements that are more than 10 percent of the maximum value.
290: Collective
292: Input Parameters:
293: + ksp - iterative context
294: . it - iteration number
295: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
296: - vf - The viewer context
298: Options Database Key:
299: . -ksp_monitor_range - Activates `KSPMonitorResidualRange()`
301: Level: intermediate
303: Note:
304: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
305: to be used during the `KSP` solve.
307: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`
308: @*/
309: PetscErrorCode KSPMonitorResidualRange(KSP ksp, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf)
310: {
311: static PetscReal prev;
312: PetscViewer viewer = vf->viewer;
313: PetscViewerFormat format = vf->format;
314: PetscInt tablevel;
315: const char *prefix;
316: PetscReal perc, rel;
318: PetscFunctionBegin;
320: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
321: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
322: PetscCall(PetscViewerPushFormat(viewer, format));
323: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
324: if (!it) prev = rnorm;
325: if (it == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
326: PetscCall(KSPMonitorRange_Private(ksp, it, &perc));
327: rel = (prev - rnorm) / prev;
328: prev = rnorm;
329: 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 * perc), (double)rel, (double)(rel / perc)));
330: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
331: PetscCall(PetscViewerPopFormat(viewer));
332: PetscFunctionReturn(PETSC_SUCCESS);
333: }
335: /*@
336: KSPMonitorTrueResidual - Prints the true residual norm, as well as the (possibly preconditioned, possibly approximate) residual norm,
337: at each iteration of a `KSPSolve()` iterative solver.
339: Collective
341: Input Parameters:
342: + ksp - iterative context
343: . n - iteration number
344: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
345: - vf - The viewer context
347: Options Database Key:
348: . -ksp_monitor_true_residual - Activates `KSPMonitorTrueResidual()` to print both norm values at each iteration
350: Level: intermediate
352: Notes:
353: When using right preconditioning, the two norm values are equivalent.
355: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
356: to be used during the `KSP` solve.
358: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`, `PetscViewerAndFormat`
359: @*/
360: PetscErrorCode KSPMonitorTrueResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
361: {
362: PetscViewer viewer = vf->viewer;
363: PetscViewerFormat format = vf->format;
364: Vec r;
365: PetscReal truenorm, bnorm;
366: char normtype[256];
367: PetscInt tablevel;
368: const char *prefix;
370: PetscFunctionBegin;
372: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
373: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
374: PetscCall(PetscStrncpy(normtype, KSPNormTypes[ksp->normtype], sizeof(normtype)));
375: PetscCall(PetscStrtolower(normtype));
376: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
377: PetscCall(VecNorm(r, NORM_2, &truenorm));
378: PetscCall(VecNorm(ksp->vec_rhs, NORM_2, &bnorm));
379: PetscCall(VecDestroy(&r));
381: PetscCall(PetscViewerPushFormat(viewer, format));
382: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
383: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
384: if (bnorm == 0) {
385: 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));
386: } else {
387: 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)));
388: }
389: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
390: PetscCall(PetscViewerPopFormat(viewer));
391: PetscFunctionReturn(PETSC_SUCCESS);
392: }
394: /*@
395: KSPMonitorTrueResidualView - Plots the true residual at each iteration of an iterative solver.
397: Collective
399: Input Parameters:
400: + ksp - iterative context
401: . n - iteration number
402: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
403: - vf - The viewer context of type `PETSCVIEWERDRAW`
405: Options Database Key:
406: . -ksp_monitor_true_residual viewertype - Activates `KSPMonitorTrueResidualView()`
408: Level: intermediate
410: Note:
411: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
412: to be used during the `KSP` solve.
414: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorResidual()`,
415: `KSPMonitorTrueResidualDrawLG()`, `PetscViewerAndFormat`
416: @*/
417: PetscErrorCode KSPMonitorTrueResidualView(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
418: {
419: PetscViewer viewer = vf->viewer;
420: PetscViewerFormat format = vf->format;
421: Vec r;
423: PetscFunctionBegin;
425: PetscCall(PetscViewerPushFormat(viewer, format));
426: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
427: PetscCall(PetscObjectSetName((PetscObject)r, "True Residual"));
428: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", (PetscObject)ksp));
429: PetscCall(VecView(r, viewer));
430: PetscCall(PetscObjectCompose((PetscObject)r, "__Vec_bc_zero__", NULL));
431: PetscCall(VecDestroy(&r));
432: PetscCall(PetscViewerPopFormat(viewer));
433: PetscFunctionReturn(PETSC_SUCCESS);
434: }
436: /*@
437: KSPMonitorTrueResidualDrawLG - Plots the true residual norm at each iteration of an iterative solver.
439: Collective
441: Input Parameters:
442: + ksp - iterative context
443: . n - iteration number
444: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
445: - vf - The viewer context
447: Options Database Key:
448: . -ksp_monitor_true_residual draw::draw_lg - Activates `KSPMonitorTrueResidualDrawLG()`
450: Level: intermediate
452: Notes:
453: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
454: to be used during the `KSP` solve.
456: Call `KSPMonitorTrueResidualDrawLGCreate()` to create the context needed for this monitor
458: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorTrueResidualDraw()`, `KSPMonitorResidual`,
459: `KSPMonitorTrueResidualDrawLGCreate()`
460: @*/
461: PetscErrorCode KSPMonitorTrueResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
462: {
463: PetscViewer viewer = vf->viewer;
464: PetscViewerFormat format = vf->format;
465: Vec r;
466: KSPConvergedReason reason;
467: PetscReal truenorm, x[2], y[2];
468: PetscDrawLG lg;
470: PetscFunctionBegin;
472: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
473: PetscCall(VecNorm(r, NORM_2, &truenorm));
474: PetscCall(VecDestroy(&r));
475: PetscCall(PetscViewerPushFormat(viewer, format));
476: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
477: if (!n) PetscCall(PetscDrawLGReset(lg));
478: x[0] = (PetscReal)n;
479: if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
480: else y[0] = -15.0;
481: x[1] = (PetscReal)n;
482: if (truenorm > 0.0) y[1] = PetscLog10Real(truenorm);
483: else y[1] = -15.0;
484: PetscCall(PetscDrawLGAddPoint(lg, x, y));
485: PetscCall(KSPGetConvergedReason(ksp, &reason));
486: if (n <= 20 || !(n % 5) || reason) {
487: PetscCall(PetscDrawLGDraw(lg));
488: PetscCall(PetscDrawLGSave(lg));
489: }
490: PetscCall(PetscViewerPopFormat(viewer));
491: PetscFunctionReturn(PETSC_SUCCESS);
492: }
494: /*@
495: KSPMonitorTrueResidualDrawLGCreate - Creates the context for the true residual monitor `KSPMonitorTrueResidualDrawLG()`
497: Collective
499: Input Parameters:
500: + viewer - The `PetscViewer` of type `PETSCVIEWERDRAW`
501: . format - The viewer format
502: - ctx - An optional application context
504: Output Parameter:
505: . vf - The viewer context
507: Level: intermediate
509: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `PetscViewerAndFormat`
510: @*/
511: PetscErrorCode KSPMonitorTrueResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, PetscCtx ctx, PetscViewerAndFormat **vf)
512: {
513: const char *names[] = {"preconditioned", "true"};
515: PetscFunctionBegin;
516: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
517: (*vf)->data = ctx;
518: PetscCall(PetscViewerMonitorLGSetUp(viewer, NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300));
519: PetscFunctionReturn(PETSC_SUCCESS);
520: }
522: /*@
523: KSPMonitorTrueResidualMax - Prints the true residual max norm at each iteration of an iterative solver.
525: Collective
527: Input Parameters:
528: + ksp - iterative context
529: . n - iteration number
530: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
531: - vf - The viewer context
533: Options Database Key:
534: . -ksp_monitor_true_residual_max - Activates `KSPMonitorTrueResidualMax()`
536: Level: intermediate
538: Note:
539: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
540: to be used during the `KSP` solve.
542: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`
543: @*/
544: PetscErrorCode KSPMonitorTrueResidualMax(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
545: {
546: PetscViewer viewer = vf->viewer;
547: PetscViewerFormat format = vf->format;
548: Vec r;
549: PetscReal truenorm, bnorm;
550: char normtype[256];
551: PetscInt tablevel;
552: const char *prefix;
554: PetscFunctionBegin;
556: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
557: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
558: PetscCall(PetscStrncpy(normtype, KSPNormTypes[ksp->normtype], sizeof(normtype)));
559: PetscCall(PetscStrtolower(normtype));
560: PetscCall(KSPBuildResidual(ksp, NULL, NULL, &r));
561: PetscCall(VecNorm(r, NORM_INFINITY, &truenorm));
562: PetscCall(VecNorm(ksp->vec_rhs, NORM_INFINITY, &bnorm));
563: PetscCall(VecDestroy(&r));
565: PetscCall(PetscViewerPushFormat(viewer, format));
566: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
567: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
568: 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)));
569: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
570: PetscCall(PetscViewerPopFormat(viewer));
571: PetscFunctionReturn(PETSC_SUCCESS);
572: }
574: /*@
575: KSPMonitorError - Prints the error norm, as well as the (possibly preconditioned) residual norm, at each iteration of an iterative solver.
577: Collective
579: Input Parameters:
580: + ksp - iterative context
581: . n - iteration number
582: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
583: - vf - The viewer context
585: Options Database Key:
586: . -ksp_monitor_error - Activates `KSPMonitorError()`
588: Level: intermediate
590: Note:
591: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
592: to be used during the `KSP` solve.
594: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`
595: @*/
596: PetscErrorCode KSPMonitorError(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
597: {
598: PetscViewer viewer = vf->viewer;
599: PetscViewerFormat format = vf->format;
600: DM dm;
601: Vec sol;
602: PetscReal *errors;
603: PetscInt Nf, f;
604: PetscInt tablevel;
605: const char *prefix;
607: PetscFunctionBegin;
609: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
610: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
611: PetscCall(KSPGetDM(ksp, &dm));
612: PetscCall(DMGetNumFields(dm, &Nf));
613: PetscCall(DMGetGlobalVector(dm, &sol));
614: PetscCall(KSPBuildSolution(ksp, sol, NULL));
615: /* TODO: Make a different monitor that flips sign for SNES, Newton system is A dx = -b, so we need to negate the solution */
616: PetscCall(VecScale(sol, -1.0));
617: PetscCall(PetscCalloc1(Nf, &errors));
618: PetscCall(DMComputeError(dm, sol, errors, NULL));
620: PetscCall(PetscViewerPushFormat(viewer, format));
621: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
622: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Error norms for %s solve.\n", prefix));
623: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Error norm %s", n, Nf > 1 ? "[" : ""));
624: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
625: for (f = 0; f < Nf; ++f) {
626: if (f > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
627: PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)errors[f]));
628: }
629: PetscCall(PetscViewerASCIIPrintf(viewer, "%s resid norm %14.12e\n", Nf > 1 ? "]" : "", (double)rnorm));
630: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
631: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
632: PetscCall(PetscViewerPopFormat(viewer));
633: PetscCall(DMRestoreGlobalVector(dm, &sol));
634: PetscFunctionReturn(PETSC_SUCCESS);
635: }
637: /*@
638: KSPMonitorErrorDraw - Plots the error at each iteration of an iterative solver.
640: Collective
642: Input Parameters:
643: + ksp - iterative context
644: . n - iteration number
645: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
646: - vf - The viewer context
648: Options Database Key:
649: . -ksp_monitor_error draw - Activates `KSPMonitorErrorDraw()`
651: Level: intermediate
653: Note:
654: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
655: to be used during the `KSP` solve.
657: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDrawLG()`
658: @*/
659: PetscErrorCode KSPMonitorErrorDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
660: {
661: PetscViewer viewer = vf->viewer;
662: PetscViewerFormat format = vf->format;
663: DM dm;
664: Vec sol, e;
666: PetscFunctionBegin;
668: PetscCall(PetscViewerPushFormat(viewer, format));
669: PetscCall(KSPGetDM(ksp, &dm));
670: PetscCall(DMGetGlobalVector(dm, &sol));
671: PetscCall(KSPBuildSolution(ksp, sol, NULL));
672: PetscCall(DMComputeError(dm, sol, NULL, &e));
673: PetscCall(PetscObjectSetName((PetscObject)e, "Error"));
674: PetscCall(PetscObjectCompose((PetscObject)e, "__Vec_bc_zero__", (PetscObject)ksp));
675: PetscCall(VecView(e, viewer));
676: PetscCall(PetscObjectCompose((PetscObject)e, "__Vec_bc_zero__", NULL));
677: PetscCall(VecDestroy(&e));
678: PetscCall(DMRestoreGlobalVector(dm, &sol));
679: PetscCall(PetscViewerPopFormat(viewer));
680: PetscFunctionReturn(PETSC_SUCCESS);
681: }
683: /*@
684: KSPMonitorErrorDrawLG - Plots the error and residual norm at each iteration of an iterative solver.
686: Collective
688: Input Parameters:
689: + ksp - iterative context
690: . n - iteration number
691: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
692: - vf - The viewer context
694: Options Database Key:
695: . -ksp_monitor_error draw::draw_lg - Activates `KSPMonitorTrueResidualDrawLG()`
697: Level: intermediate
699: Notes:
700: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
701: to be used during the `KSP` solve.
703: Call `KSPMonitorErrorDrawLGCreate()` to create the context used with this monitor
705: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDraw()`
706: @*/
707: PetscErrorCode KSPMonitorErrorDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
708: {
709: PetscViewer viewer = vf->viewer;
710: PetscViewerFormat format = vf->format;
711: PetscDrawLG lg;
712: DM dm;
713: Vec sol;
714: KSPConvergedReason reason;
715: PetscReal *x, *errors;
716: PetscInt Nf;
718: PetscFunctionBegin;
720: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
721: PetscCall(KSPGetDM(ksp, &dm));
722: PetscCall(DMGetNumFields(dm, &Nf));
723: PetscCall(DMGetGlobalVector(dm, &sol));
724: PetscCall(KSPBuildSolution(ksp, sol, NULL));
725: /* TODO: Make a different monitor that flips sign for SNES, Newton system is A dx = -b, so we need to negate the solution */
726: PetscCall(VecScale(sol, -1.0));
727: PetscCall(PetscCalloc2(Nf + 1, &x, Nf + 1, &errors));
728: PetscCall(DMComputeError(dm, sol, errors, NULL));
730: PetscCall(PetscViewerPushFormat(viewer, format));
731: if (!n) PetscCall(PetscDrawLGReset(lg));
732: for (PetscInt f = 0; f < Nf; ++f) {
733: x[f] = (PetscReal)n;
734: errors[f] = errors[f] > 0.0 ? PetscLog10Real(errors[f]) : -15.;
735: }
736: x[Nf] = (PetscReal)n;
737: errors[Nf] = rnorm > 0.0 ? PetscLog10Real(rnorm) : -15.;
738: PetscCall(PetscDrawLGAddPoint(lg, x, errors));
739: PetscCall(KSPGetConvergedReason(ksp, &reason));
740: if (n <= 20 || !(n % 5) || reason) {
741: PetscCall(PetscDrawLGDraw(lg));
742: PetscCall(PetscDrawLGSave(lg));
743: }
744: PetscCall(PetscViewerPopFormat(viewer));
745: PetscFunctionReturn(PETSC_SUCCESS);
746: }
748: /*@
749: KSPMonitorErrorDrawLGCreate - Creates the context for the error and preconditioned residual plotter `KSPMonitorErrorDrawLG()`
751: Collective
753: Input Parameters:
754: + viewer - The `PetscViewer`
755: . format - The viewer format
756: - ctx - An optional application context
758: Output Parameter:
759: . vf - The viewer context
761: Level: intermediate
763: .seealso: [](ch_ksp), `PETSCVIEWERDRAW`, `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorErrorDrawLG()`
764: @*/
765: PetscErrorCode KSPMonitorErrorDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, PetscCtx ctx, PetscViewerAndFormat **vf)
766: {
767: KSP ksp = (KSP)ctx;
768: DM dm;
769: char **names;
770: PetscInt Nf;
772: PetscFunctionBegin;
773: PetscCall(KSPGetDM(ksp, &dm));
774: PetscCall(DMGetNumFields(dm, &Nf));
775: PetscCall(PetscMalloc1(Nf + 1, &names));
776: for (PetscInt f = 0; f < Nf; ++f) {
777: PetscObject disc;
778: const char *fname;
779: char lname[PETSC_MAX_PATH_LEN];
781: PetscCall(DMGetField(dm, f, NULL, &disc));
782: PetscCall(PetscObjectGetName(disc, &fname));
783: PetscCall(PetscStrncpy(lname, fname, PETSC_MAX_PATH_LEN));
784: PetscCall(PetscStrlcat(lname, " Error", PETSC_MAX_PATH_LEN));
785: PetscCall(PetscStrallocpy(lname, &names[f]));
786: }
787: PetscCall(PetscStrallocpy("residual", &names[Nf]));
788: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
789: (*vf)->data = ctx;
790: PetscCall(PetscViewerMonitorLGSetUp(viewer, NULL, NULL, "Log Error Norm", Nf + 1, (const char **)names, PETSC_DECIDE, PETSC_DECIDE, 400, 300));
791: for (PetscInt f = 0; f <= Nf; ++f) PetscCall(PetscFree(names[f]));
792: PetscCall(PetscFree(names));
793: PetscFunctionReturn(PETSC_SUCCESS);
794: }
796: /*@
797: KSPMonitorSolution - Print the solution norm at each iteration of an iterative solver.
799: Collective
801: Input Parameters:
802: + ksp - iterative context
803: . n - iteration number
804: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
805: - vf - The viewer context
807: Options Database Key:
808: . -ksp_monitor_solution - Activates `KSPMonitorSolution()`
810: Level: intermediate
812: Note:
813: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
814: to be used during the `KSP` solve.
816: .seealso: [](ch_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
817: @*/
818: PetscErrorCode KSPMonitorSolution(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
819: {
820: PetscViewer viewer = vf->viewer;
821: PetscViewerFormat format = vf->format;
822: Vec x;
823: PetscReal snorm;
824: PetscInt tablevel;
825: const char *prefix;
827: PetscFunctionBegin;
829: PetscCall(KSPBuildSolution(ksp, NULL, &x));
830: PetscCall(VecNorm(x, NORM_2, &snorm));
831: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
832: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
833: PetscCall(PetscViewerPushFormat(viewer, format));
834: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
835: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Solution norms for %s solve.\n", prefix));
836: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Solution norm %14.12e\n", n, (double)snorm));
837: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
838: PetscCall(PetscViewerPopFormat(viewer));
839: PetscFunctionReturn(PETSC_SUCCESS);
840: }
842: /*@
843: KSPMonitorSolutionDraw - Plots the solution at each iteration of an iterative solver.
845: Collective
847: Input Parameters:
848: + ksp - iterative context
849: . n - iteration number
850: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
851: - vf - The viewer context
853: Options Database Key:
854: . -ksp_monitor_solution draw - Activates `KSPMonitorSolutionDraw()`
856: Level: intermediate
858: Note:
859: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
860: to be used during the `KSP` solve.
862: .seealso: [](ch_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
863: @*/
864: PetscErrorCode KSPMonitorSolutionDraw(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
865: {
866: PetscViewer viewer = vf->viewer;
867: PetscViewerFormat format = vf->format;
868: Vec x;
870: PetscFunctionBegin;
872: PetscCall(KSPBuildSolution(ksp, NULL, &x));
873: PetscCall(PetscViewerPushFormat(viewer, format));
874: PetscCall(PetscObjectSetName((PetscObject)x, "Solution"));
875: PetscCall(PetscObjectCompose((PetscObject)x, "__Vec_bc_zero__", (PetscObject)ksp));
876: PetscCall(VecView(x, viewer));
877: PetscCall(PetscObjectCompose((PetscObject)x, "__Vec_bc_zero__", NULL));
878: PetscCall(PetscViewerPopFormat(viewer));
879: PetscFunctionReturn(PETSC_SUCCESS);
880: }
882: /*@
883: KSPMonitorSolutionDrawLG - Plots the solution norm at each iteration of an iterative solver.
885: Collective
887: Input Parameters:
888: + ksp - iterative context
889: . n - iteration number
890: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
891: - vf - The viewer context
893: Options Database Key:
894: . -ksp_monitor_solution draw::draw_lg - Activates `KSPMonitorSolutionDrawLG()`
896: Level: intermediate
898: Notes:
899: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
900: to be used during the `KSP` solve.
902: Call `KSPMonitorSolutionDrawLGCreate()` to create the context needed with this monitor
904: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `KSPMonitorSolutionDrawLGCreate()`
905: @*/
906: PetscErrorCode KSPMonitorSolutionDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
907: {
908: PetscViewer viewer = vf->viewer;
909: PetscViewerFormat format = vf->format;
910: PetscDrawLG lg;
911: Vec u;
912: KSPConvergedReason reason;
913: PetscReal snorm, x, y;
915: PetscFunctionBegin;
917: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
918: PetscCall(KSPBuildSolution(ksp, NULL, &u));
919: PetscCall(VecNorm(u, NORM_2, &snorm));
920: PetscCall(PetscViewerPushFormat(viewer, format));
921: if (!n) PetscCall(PetscDrawLGReset(lg));
922: x = (PetscReal)n;
923: if (snorm > 0.0) y = PetscLog10Real(snorm);
924: else y = -15.0;
925: PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
926: PetscCall(KSPGetConvergedReason(ksp, &reason));
927: if (n <= 20 || !(n % 5) || reason) {
928: PetscCall(PetscDrawLGDraw(lg));
929: PetscCall(PetscDrawLGSave(lg));
930: }
931: PetscCall(PetscViewerPopFormat(viewer));
932: PetscFunctionReturn(PETSC_SUCCESS);
933: }
935: /*@
936: KSPMonitorSolutionDrawLGCreate - Creates the context for the `KSP` monitor `KSPMonitorSolutionDrawLG()`
938: Collective
940: Input Parameters:
941: + viewer - The `PetscViewer`
942: . format - The viewer format
943: - ctx - An optional application context
945: Output Parameter:
946: . vf - The viewer context
948: Level: intermediate
950: Note:
951: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
952: to be used during the `KSP` solve.
954: .seealso: [](ch_ksp), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
955: @*/
956: PetscErrorCode KSPMonitorSolutionDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, PetscCtx ctx, PetscViewerAndFormat **vf)
957: {
958: PetscFunctionBegin;
959: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
960: (*vf)->data = ctx;
961: PetscCall(PetscViewerMonitorLGSetUp(viewer, NULL, NULL, "Log Solution Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300));
962: PetscFunctionReturn(PETSC_SUCCESS);
963: }
965: /*@
966: KSPMonitorSingularValue - Prints the two norm of the true residual and estimation of the extreme singular values of the preconditioned problem at each iteration.
968: Logically Collective
970: Input Parameters:
971: + ksp - the iterative context
972: . n - the iteration
973: . rnorm - the two norm of the residual
974: - vf - The viewer context
976: Options Database Key:
977: . -ksp_monitor_singular_value - Activates `KSPMonitorSingularValue()`
979: Level: intermediate
981: Notes:
982: The `KSPCG` solver uses the Lanczos technique for eigenvalue computation,
983: while `KSPGMRES` uses the Arnoldi technique; other iterative methods do
984: not currently compute singular values.
986: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
987: to be used during the `KSP` solve.
989: Call `KSPMonitorSingularValueCreate()` to create the context needed by this monitor
991: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPComputeExtremeSingularValues()`, `KSPMonitorSingularValueCreate()`
992: @*/
993: PetscErrorCode KSPMonitorSingularValue(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
994: {
995: PetscViewer viewer = vf->viewer;
996: PetscViewerFormat format = vf->format;
997: PetscReal emin, emax;
998: PetscInt tablevel;
999: const char *prefix;
1001: PetscFunctionBegin;
1004: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
1005: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
1006: PetscCall(PetscViewerPushFormat(viewer, format));
1007: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
1008: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
1009: if (!ksp->calc_sings) {
1010: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " KSP Residual norm %14.12e\n", n, (double)rnorm));
1011: } else {
1012: PetscCall(KSPComputeExtremeSingularValues(ksp, &emax, &emin));
1013: 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)));
1014: }
1015: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
1016: PetscCall(PetscViewerPopFormat(viewer));
1017: PetscFunctionReturn(PETSC_SUCCESS);
1018: }
1020: /*@
1021: KSPMonitorSingularValueCreate - Creates the singular value monitor context needed by `KSPMonitorSingularValue()`
1023: Collective
1025: Input Parameters:
1026: + viewer - The PetscViewer
1027: . format - The viewer format
1028: - ctx - An optional application context
1030: Output Parameter:
1031: . vf - The viewer context
1033: Level: intermediate
1035: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorSingularValue()`, `PetscViewer`
1036: @*/
1037: PetscErrorCode KSPMonitorSingularValueCreate(PetscViewer viewer, PetscViewerFormat format, PetscCtx ctx, PetscViewerAndFormat **vf)
1038: {
1039: KSP ksp = (KSP)ctx;
1041: PetscFunctionBegin;
1042: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
1043: (*vf)->data = ctx;
1044: PetscCall(KSPSetComputeSingularValues(ksp, PETSC_TRUE));
1045: PetscFunctionReturn(PETSC_SUCCESS);
1046: }
1048: /*@
1049: KSPMonitorDynamicToleranceCreate - Creates the context used by `KSPMonitorDynamicTolerance()`
1051: Logically Collective
1053: Output Parameter:
1054: . ctx - a void pointer
1056: Options Database Key:
1057: . -sub_ksp_dynamic_tolerance coef - coefficient of dynamic tolerance for inner solver, default is 1.0
1059: Level: advanced
1061: Note:
1062: Use before calling `KSPMonitorSet()` with `KSPMonitorDynamicTolerance()`
1064: The default coefficient for the tolerance can be changed with `KSPMonitorDynamicToleranceSetCoefficient()`
1066: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceSetCoefficient()`
1067: @*/
1068: PetscErrorCode KSPMonitorDynamicToleranceCreate(PetscCtx ctx)
1069: {
1070: KSPDynTolCtx *scale;
1072: PetscFunctionBegin;
1073: PetscCall(PetscMalloc1(1, &scale));
1074: scale->bnrm = -1.0;
1075: scale->coef = 1.0;
1076: *(void **)ctx = scale;
1077: PetscFunctionReturn(PETSC_SUCCESS);
1078: }
1080: /*@
1081: KSPMonitorDynamicToleranceSetCoefficient - Sets the coefficient in the context used by `KSPMonitorDynamicTolerance()`
1083: Logically Collective
1085: Output Parameters:
1086: + ctx - the context for `KSPMonitorDynamicTolerance()`
1087: - coeff - the coefficient, default is 1.0
1089: Options Database Key:
1090: . -sub_ksp_dynamic_tolerance coef - coefficient of dynamic tolerance for inner solver, default is 1.0
1092: Level: advanced
1094: Note:
1095: Use before calling `KSPMonitorSet()` and after `KSPMonitorDynamicToleranceCreate()`
1097: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceCreate()`
1098: @*/
1099: PetscErrorCode KSPMonitorDynamicToleranceSetCoefficient(PetscCtx ctx, PetscReal coeff)
1100: {
1101: KSPDynTolCtx *scale = (KSPDynTolCtx *)ctx;
1103: PetscFunctionBegin;
1104: scale->coef = coeff;
1105: PetscFunctionReturn(PETSC_SUCCESS);
1106: }
1108: /*@
1109: KSPMonitorDynamicTolerance - A monitor that changes the inner tolerance of nested preconditioners in every outer iteration in an adaptive way.
1111: Collective
1113: Input Parameters:
1114: + ksp - iterative context
1115: . its - iteration number (not used)
1116: . fnorm - the current residual norm
1117: - ctx - context used by monitor
1119: Options Database Key:
1120: . -sub_ksp_dynamic_tolerance coef - coefficient of dynamic tolerance for inner solver, default is 1.0
1122: Level: advanced
1124: Notes:
1125: Applies for `PCKSP`, `PCBJACOBI`, and `PCDEFLATION` preconditioners
1127: This may be useful for a flexible preconditioned Krylov method, such as `KSPFGMRES`, [](sec_flexibleksp) to
1128: control the accuracy of the inner solves needed to guarantee convergence of the outer iterations.
1130: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
1131: to be used during the `KSP` solve.
1133: Use `KSPMonitorDynamicToleranceCreate()` and `KSPMonitorDynamicToleranceSetCoefficient()` to create the context needed by this
1134: monitor function.
1136: Pass the context and `KSPMonitorDynamicToleranceDestroy()` to `KSPMonitorSet()`
1138: .seealso: [](sec_flexibleksp), `KSP`, `KSPMonitorDynamicToleranceCreate()`, `KSPMonitorDynamicToleranceDestroy()`, `KSPMonitorDynamicToleranceSetCoefficient()`
1139: @*/
1140: PetscErrorCode KSPMonitorDynamicTolerance(KSP ksp, PetscInt its, PetscReal fnorm, PetscCtx ctx)
1141: {
1142: PC pc;
1143: PetscReal outer_rtol, outer_abstol, outer_dtol, inner_rtol;
1144: PetscInt outer_maxits, nksp, first, i;
1145: KSPDynTolCtx *scale = (KSPDynTolCtx *)ctx;
1146: KSP *subksp = NULL;
1147: KSP kspinner;
1148: PetscBool flg;
1150: PetscFunctionBegin;
1151: PetscCall(KSPGetPC(ksp, &pc));
1153: /* compute inner_rtol */
1154: if (scale->bnrm < 0.0) {
1155: Vec b;
1156: PetscCall(KSPGetRhs(ksp, &b));
1157: PetscCall(VecNorm(b, NORM_2, &scale->bnrm));
1158: }
1159: PetscCall(KSPGetTolerances(ksp, &outer_rtol, &outer_abstol, &outer_dtol, &outer_maxits));
1160: inner_rtol = PetscMin(scale->coef * scale->bnrm * outer_rtol / fnorm, 0.999);
1162: /* if pc is ksp */
1163: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCKSP, &flg));
1164: if (flg) {
1165: PetscCall(PCKSPGetKSP(pc, &kspinner));
1166: PetscCall(KSPSetTolerances(kspinner, inner_rtol, outer_abstol, outer_dtol, outer_maxits));
1167: PetscFunctionReturn(PETSC_SUCCESS);
1168: }
1170: /* if pc is bjacobi */
1171: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCBJACOBI, &flg));
1172: if (flg) {
1173: PetscCall(PCBJacobiGetSubKSP(pc, &nksp, &first, &subksp));
1174: if (subksp) {
1175: for (i = 0; i < nksp; i++) PetscCall(KSPSetTolerances(subksp[i], inner_rtol, outer_abstol, outer_dtol, outer_maxits));
1176: PetscFunctionReturn(PETSC_SUCCESS);
1177: }
1178: }
1180: /* if pc is deflation*/
1181: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCDEFLATION, &flg));
1182: if (flg) {
1183: PetscCall(PCDeflationGetCoarseKSP(pc, &kspinner));
1184: PetscCall(KSPSetTolerances(kspinner, inner_rtol, outer_abstol, outer_dtol, PETSC_CURRENT));
1185: PetscFunctionReturn(PETSC_SUCCESS);
1186: }
1188: /* TODO: dynamic tolerance may apply to other types of pc */
1189: PetscFunctionReturn(PETSC_SUCCESS);
1190: }
1192: /*@
1193: KSPMonitorDynamicToleranceDestroy - Destroy the monitor context used in `KSPMonitorDynamicTolerance()`
1195: Input Parameter:
1196: . ctx - the monitor context
1198: Level: advanced
1200: Note:
1201: This is not called directly but is passed to `KSPMonitorSet()` along with `KSPMonitorDynamicTolerance()`
1203: .seealso: [](ch_ksp), `KSP`, `KSPMonitorDynamicTolerance()`, `KSPMonitorSet()`, `KSPMonitorDynamicToleranceCreate()`
1204: @*/
1205: PetscErrorCode KSPMonitorDynamicToleranceDestroy(PetscCtxRt ctx)
1206: {
1207: PetscFunctionBegin;
1208: PetscCall(PetscFree(*(void **)ctx));
1209: PetscFunctionReturn(PETSC_SUCCESS);
1210: }
1212: /*@
1213: KSPConvergedSkip - Convergence test that do not return as converged
1214: until the maximum number of iterations is reached.
1216: Collective
1218: Input Parameters:
1219: + ksp - iterative context
1220: . n - iteration number
1221: . rnorm - 2-norm residual value (may be estimated)
1222: - dtx - unused convergence context
1224: Output Parameter:
1225: . reason - `KSP_CONVERGED_ITERATING` or `KSP_CONVERGED_ITS`
1227: Options Database Key:
1228: . -ksp_convergence_test skip - skips the test
1230: Level: advanced
1232: Note:
1233: This should be used as the convergence test with the option
1234: `KSPSetNormType`(ksp,`KSP_NORM_NONE`), since norms of the residual are
1235: not computed. Convergence is then declared after the maximum number
1236: of iterations have been reached. Useful when one is using `KSPCG` or
1237: `KSPBCGS`. [](sec_flexibleksp)
1239: .seealso: [](ch_ksp), `KSP`, `KSPCG`, `KSPBCGS`, `KSPConvergenceTestFn`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPSetNormType()`, [](sec_flexibleksp),
1240: `KSPConvergedReason`
1241: @*/
1242: PetscErrorCode KSPConvergedSkip(KSP ksp, PetscInt n, PetscReal rnorm, KSPConvergedReason *reason, PetscCtx dtx)
1243: {
1244: PetscFunctionBegin;
1246: PetscAssertPointer(reason, 4);
1247: *reason = KSP_CONVERGED_ITERATING;
1248: if (n >= ksp->max_it) *reason = KSP_CONVERGED_ITS;
1249: PetscFunctionReturn(PETSC_SUCCESS);
1250: }
1252: /*@
1253: KSPSetConvergedNegativeCurvature - Allows to declare convergence and return `KSP_CONVERGED_NEG_CURVE` when negative curvature is detected
1255: Collective
1257: Input Parameters:
1258: + ksp - iterative context
1259: - flg - the Boolean value
1261: Options Database Key:
1262: . -ksp_converged_neg_curve (true|false) - Declare convergence if negative curvature is detected
1264: Level: advanced
1266: Note:
1267: This is currently used only by a subset of the Krylov solvers, namely `KSPCG`, `KSPSTCG`, `KSPQCG`, `KSPGLTR`, `KSPNASH`, and `KSPMINRES`.
1269: .seealso: [](ch_ksp), `KSP`, `KSPConvergedReason`, `KSPGetConvergedNegativeCurvature()`
1270: @*/
1271: PetscErrorCode KSPSetConvergedNegativeCurvature(KSP ksp, PetscBool flg)
1272: {
1273: PetscFunctionBegin;
1276: ksp->converged_neg_curve = flg;
1277: PetscFunctionReturn(PETSC_SUCCESS);
1278: }
1280: /*@
1281: KSPGetConvergedNegativeCurvature - Get the flag to declare convergence if negative curvature is detected
1283: Collective
1285: Input Parameter:
1286: . ksp - iterative context
1288: Output Parameter:
1289: . flg - the Boolean value
1291: Level: advanced
1293: .seealso: [](ch_ksp), `KSP`, `KSPConvergedReason`, `KSPSetConvergedNegativeCurvature()`
1294: @*/
1295: PetscErrorCode KSPGetConvergedNegativeCurvature(KSP ksp, PetscBool *flg)
1296: {
1297: PetscFunctionBegin;
1299: PetscAssertPointer(flg, 2);
1300: *flg = ksp->converged_neg_curve;
1301: PetscFunctionReturn(PETSC_SUCCESS);
1302: }
1304: /*@
1305: KSPConvergedDefaultCreate - Creates and initializes the context used by the `KSPConvergedDefault()` function
1307: Not Collective
1309: Output Parameter:
1310: . ctx - convergence context
1312: Level: intermediate
1314: .seealso: [](ch_ksp), `KSP`, `KSPConvergedDefault()`, `KSPConvergedDefaultDestroy()`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`,
1315: `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`,
1316: `KSPConvergedDefaultSetConvergedMaxits()`
1317: @*/
1318: PetscErrorCode KSPConvergedDefaultCreate(void **ctx) PeNS
1319: {
1320: KSPConvergedDefaultCtx *cctx;
1322: PetscFunctionBegin;
1323: PetscCall(PetscNew(&cctx));
1324: *ctx = cctx;
1325: PetscFunctionReturn(PETSC_SUCCESS);
1326: }
1328: /*@
1329: KSPConvergedDefaultSetUIRNorm - makes the default convergence test use $ || B*(b - A*(initial guess))||$
1330: instead of $ || B*b ||$. In the case of right preconditioner or if `KSPSetNormType`(ksp,`KSP_NORM_UNPRECONDITIONED`)
1331: is used there is no B in the above formula.
1333: Collective
1335: Input Parameters:
1336: . ksp - iterative context
1338: Options Database Key:
1339: . -ksp_converged_use_initial_residual_norm (true|false) - Use initial residual norm for computing relative convergence
1341: Level: intermediate
1343: Notes:
1344: UIRNorm is short for Use Initial Residual Norm.
1346: Use `KSPSetTolerances()` to alter the defaults for rtol, abstol, dtol.
1348: The precise values of reason are macros such as `KSP_CONVERGED_RTOL`, which
1349: are defined in petscksp.h.
1351: If the convergence test is not `KSPConvergedDefault()` then this is ignored.
1353: If right preconditioning is being used then B does not appear in the above formula.
1355: .seealso: [](ch_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`
1356: @*/
1357: PetscErrorCode KSPConvergedDefaultSetUIRNorm(KSP ksp)
1358: {
1359: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1361: PetscFunctionBegin;
1363: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1364: PetscCheck(!ctx->mininitialrtol, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "Cannot use KSPConvergedDefaultSetUIRNorm() and KSPConvergedDefaultSetUMIRNorm() together");
1365: ctx->initialrtol = PETSC_TRUE;
1366: PetscFunctionReturn(PETSC_SUCCESS);
1367: }
1369: /*@
1370: KSPConvergedDefaultSetUMIRNorm - makes the default convergence test use $\min(|| B*(b - A*(initial guess))||,|| B*b ||)$
1371: In the case of right preconditioner or if `KSPSetNormType`(ksp,`KSP_NORM_UNPRECONDITIONED`)
1372: is used there is no $B$ in the above formula.
1374: Collective
1376: Input Parameters:
1377: . ksp - iterative context
1379: Options Database Key:
1380: . -ksp_converged_use_min_initial_residual_norm (true|false) - Use minimum of initial residual norm and b for computing relative convergence
1382: Level: intermediate
1384: Notes:
1385: UMIRNorm is short for Use Minimum Initial Residual Norm.
1387: Use `KSPSetTolerances()` to alter the defaults for rtol, abstol, dtol.
1389: .seealso: [](ch_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`
1390: @*/
1391: PetscErrorCode KSPConvergedDefaultSetUMIRNorm(KSP ksp)
1392: {
1393: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1395: PetscFunctionBegin;
1397: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1398: PetscCheck(!ctx->initialrtol, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "Cannot use KSPConvergedDefaultSetUIRNorm() and KSPConvergedDefaultSetUMIRNorm() together");
1399: ctx->mininitialrtol = PETSC_TRUE;
1400: PetscFunctionReturn(PETSC_SUCCESS);
1401: }
1403: /*@
1404: KSPConvergedDefaultSetConvergedMaxits - allows the default convergence test to declare convergence and return `KSP_CONVERGED_ITS` if the maximum number of iterations is reached
1406: Collective
1408: Input Parameters:
1409: + ksp - iterative context
1410: - flg - boolean flag
1412: Options Database Key:
1413: . -ksp_converged_maxits (true|false) - Declare convergence if the maximum number of iterations is reached
1415: Level: intermediate
1417: .seealso: [](ch_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetUIRNorm()`
1418: @*/
1419: PetscErrorCode KSPConvergedDefaultSetConvergedMaxits(KSP ksp, PetscBool flg)
1420: {
1421: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx *)ksp->cnvP;
1423: PetscFunctionBegin;
1426: if (ksp->converged != KSPConvergedDefault) PetscFunctionReturn(PETSC_SUCCESS);
1427: ctx->convmaxits = flg;
1428: PetscFunctionReturn(PETSC_SUCCESS);
1429: }
1431: /*@
1432: KSPConvergedDefault - Default code to determine convergence of the linear iterative solvers
1434: Collective
1436: Input Parameters:
1437: + ksp - iterative context
1438: . n - iteration number
1439: . rnorm - residual norm (may be estimated, depending on the method may be the preconditioned residual norm)
1440: - ctx - convergence context which must be created by `KSPConvergedDefaultCreate()`
1442: Output Parameter:
1443: . reason - the convergence reason; it is positive if the iteration has converged,
1444: negative if the iteration has diverged, and `KSP_CONVERGED_ITERATING` otherwise
1446: Options Database Keys:
1447: + -ksp_max_it - maximum number of linear iterations
1448: . -ksp_min_it - minimum number of linear iterations, defaults to 0
1449: . -ksp_rtol rtol - relative tolerance used in default determination of convergence, i.e. if residual norm decreases by this factor than convergence is declared
1450: . -ksp_atol abstol - absolute tolerance used in default convergence test, i.e. if residual norm is less than this then convergence is declared
1451: . -ksp_divtol tol - if residual norm increases by this factor than divergence is declared
1452: . -ksp_converged_use_initial_residual_norm - see `KSPConvergedDefaultSetUIRNorm()`
1453: . -ksp_converged_use_min_initial_residual_norm - see `KSPConvergedDefaultSetUMIRNorm()`
1454: - -ksp_converged_maxits - see `KSPConvergedDefaultSetConvergedMaxits()`
1456: Level: advanced
1458: Notes:
1459: `KSPConvergedDefault()` reaches convergence when rnorm < MAX (rtol * rnorm_0, abstol);
1460: Divergence is detected if rnorm > dtol * rnorm_0, or when failures are detected throughout the iteration.
1461: By default, reaching the maximum number of iterations is considered divergence (i.e. `KSP_DIVERGED_ITS`).
1462: In order to have PETSc declaring convergence in such a case (i.e. `KSP_CONVERGED_ITS`), users can use `KSPConvergedDefaultSetConvergedMaxits()`
1464: where\:
1465: + `rtol` - relative tolerance,
1466: . `abstol` - absolute tolerance.
1467: . `dtol` - divergence tolerance,
1468: - `rnorm_0` - the two norm of the right-hand side (or the preconditioned norm, depending on what was set with
1469: `KSPSetNormType()`). When initial guess is non-zero you
1470: can call `KSPConvergedDefaultSetUIRNorm()` to use the norm of (b - A*(initial guess))
1471: as the starting point for relative norm convergence testing, that is as `rnorm_0`.
1472: Call `KSPConvergedDefaultSetUMIRNorm()` to use the minimum of the norm of (b - A*(initial guess)) and the norm of b as the starting point.
1473: During `KSPMatSolve()`, when the iteration is performed on a whole batch of right-hand sides at once, a batch being the whole block unless `KSPSetMatSolveBatchSize()` is used,
1474: `rnorm_0` is by default the Frobenius norm of that batch of (preconditioned) right-hand sides.
1476: Use `KSPSetTolerances()` to alter the defaults for `rtol`, `abstol`, `dtol`.
1478: Use `KSPSetNormType()` (or `-ksp_norm_type <none,preconditioned,unpreconditioned,natural>`) to change the norm used for computing rnorm
1480: The precise values of reason are available in `KSPConvergedReason`
1482: This routine is used by `KSP` by default so the user generally never needs call it directly.
1484: Use `KSPSetConvergenceTest()` to provide your own test instead of using this one.
1486: Call `KSPSetConvergenceTest()` with the `ctx`, as created above and the destruction function `KSPConvergedDefaultDestroy()`
1488: .seealso: [](ch_ksp), `KSP`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`, `KSPConvergedReason`, `KSPGetConvergedReason()`,
1489: `KSPSetMinimumIterations()`, `KSPConvergenceTestFn`,
1490: `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`, `KSPConvergedDefaultSetConvergedMaxits()`, `KSPConvergedDefaultCreate()`, `KSPConvergedDefaultDestroy()`
1491: @*/
1492: PetscErrorCode KSPConvergedDefault(KSP ksp, PetscInt n, PetscReal rnorm, KSPConvergedReason *reason, PetscCtx ctx)
1493: {
1494: KSPConvergedDefaultCtx *cctx = (KSPConvergedDefaultCtx *)ctx;
1495: KSPNormType normtype;
1497: PetscFunctionBegin;
1500: PetscAssertPointer(reason, 4);
1501: PetscCheck(cctx, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_NULL, "Convergence context must have been created with KSPConvergedDefaultCreate()");
1502: *reason = KSP_CONVERGED_ITERATING;
1504: if (cctx->convmaxits && n >= ksp->max_it) {
1505: *reason = KSP_CONVERGED_ITS;
1506: PetscCall(PetscInfo(ksp, "Linear solver has converged. Maximum number of iterations reached %" PetscInt_FMT "\n", n));
1507: PetscFunctionReturn(PETSC_SUCCESS);
1508: }
1509: PetscCall(KSPGetNormType(ksp, &normtype));
1510: if (normtype == KSP_NORM_NONE) PetscFunctionReturn(PETSC_SUCCESS);
1512: if (!n) {
1513: /* if user gives initial guess need to compute norm of b */
1514: if (!ksp->guess_zero && !cctx->initialrtol) {
1515: PetscReal snorm = 0.0;
1516: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->pc_side == PC_RIGHT) {
1517: if (ksp->mat_rhs) {
1518: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing Frobenius norm of the batch of RHS\n"));
1519: PetscCall(MatNorm(ksp->mat_rhs, NORM_FROBENIUS, &snorm)); /* <- trace(B'*B) */
1520: } else {
1521: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing 2-norm of RHS\n"));
1522: PetscCall(VecNorm(ksp->vec_rhs, NORM_2, &snorm)); /* <- b'*b */
1523: }
1524: } else if (ksp->mat_rhs) {
1525: Mat Z;
1527: PetscCheck(ksp->normtype != KSP_NORM_NATURAL, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "KSPConvergedDefault() does not support KSP_NORM_NATURAL with a batch of right-hand sides and a nonzero initial guess, use KSPConvergedDefaultSetUIRNorm()");
1528: /* As with the Vec below, Z cannot be stashed in cctx because the number of right-hand sides may change between solves */
1529: PetscCall(MatDuplicate(ksp->mat_rhs, MAT_DO_NOT_COPY_VALUES, &Z));
1530: PetscCall(KSP_PCMatApply(ksp, ksp->mat_rhs, Z));
1531: /* KSP_PCApply() below removes the null space of Amat, so the batch of preconditioned right-hand sides must be projected as well */
1532: PetscCall(KSP_RemoveNullSpaceMat(ksp, Z));
1533: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing Frobenius norm of the preconditioned batch of RHS\n"));
1534: PetscCall(MatNorm(Z, NORM_FROBENIUS, &snorm)); /* dp <- trace(B'*P'*P*B) */
1535: PetscCall(MatDestroy(&Z));
1536: } else {
1537: Vec z;
1538: /* Should avoid allocating the z vector each time but cannot stash it in cctx because if KSPReset() is called the vector size might change */
1539: PetscCall(VecDuplicate(ksp->vec_rhs, &z));
1540: PetscCall(KSP_PCApply(ksp, ksp->vec_rhs, z));
1541: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
1542: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing 2-norm of preconditioned RHS\n"));
1543: PetscCall(VecNorm(z, NORM_2, &snorm)); /* dp <- b'*B'*B*b */
1544: } else if (ksp->normtype == KSP_NORM_NATURAL) {
1545: PetscScalar norm;
1546: PetscCall(PetscInfo(ksp, "user has provided nonzero initial guess, computing natural norm of RHS\n"));
1547: PetscCall(VecDot(ksp->vec_rhs, z, &norm));
1548: snorm = PetscSqrtReal(PetscAbsScalar(norm)); /* dp <- b'*B*b */
1549: }
1550: PetscCall(VecDestroy(&z));
1551: }
1552: /* handle special case of zero RHS and nonzero guess */
1553: if (!snorm) {
1554: PetscCall(PetscInfo(ksp, "Special case, user has provided nonzero initial guess and zero RHS\n"));
1555: snorm = rnorm;
1556: }
1557: if (cctx->mininitialrtol) ksp->rnorm0 = PetscMin(snorm, rnorm);
1558: else ksp->rnorm0 = snorm;
1559: } else {
1560: ksp->rnorm0 = rnorm;
1561: }
1562: ksp->ttol = PetscMax(ksp->rtol * ksp->rnorm0, ksp->abstol);
1563: }
1565: if (n <= ksp->chknorm) PetscFunctionReturn(PETSC_SUCCESS);
1567: if (PetscIsInfOrNanReal(rnorm)) {
1568: PCFailedReason pcreason;
1569: PetscCall(PCReduceFailedReason(ksp->pc));
1570: PetscCall(PCGetFailedReason(ksp->pc, &pcreason));
1571: if (pcreason) {
1572: *reason = KSP_DIVERGED_PC_FAILED;
1573: PetscCall(PetscInfo(ksp, "Linear solver pcsetup fails, declaring divergence \n"));
1574: } else {
1575: *reason = KSP_DIVERGED_NANORINF;
1576: PetscCall(PetscInfo(ksp, "Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n"));
1577: }
1578: PetscFunctionReturn(PETSC_SUCCESS);
1579: }
1581: if (n < ksp->min_it) PetscFunctionReturn(PETSC_SUCCESS);
1583: if (rnorm <= ksp->ttol) {
1584: if (rnorm < ksp->abstol) {
1585: 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));
1586: *reason = KSP_CONVERGED_ATOL;
1587: } else {
1588: if (cctx->initialrtol) {
1589: 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));
1590: } else {
1591: 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));
1592: }
1593: *reason = KSP_CONVERGED_RTOL;
1594: }
1595: } else if (rnorm >= ksp->divtol * ksp->rnorm0) {
1596: 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));
1597: *reason = KSP_DIVERGED_DTOL;
1598: }
1599: PetscFunctionReturn(PETSC_SUCCESS);
1600: }
1602: /*@
1603: KSPConvergedDefaultDestroy - Frees the space used by the `KSPConvergedDefault()` function context
1605: Not Collective
1607: Input Parameter:
1608: . ctx - convergence context
1610: Level: intermediate
1612: Note:
1613: Pass this function name into `KSPSetConvergenceTest()` along with the context obtained with `KSPConvergedDefaultCreate()` and `KSPConvergedDefault()`
1615: .seealso: [](ch_ksp), `KSP`, `KSPConvergedDefault()`, `KSPConvergedDefaultCreate()`, `KSPSetConvergenceTest()`, `KSPSetTolerances()`, `KSPConvergedSkip()`,
1616: `KSPConvergedReason`, `KSPGetConvergedReason()`, `KSPConvergedDefaultSetUIRNorm()`, `KSPConvergedDefaultSetUMIRNorm()`
1617: @*/
1618: PetscErrorCode KSPConvergedDefaultDestroy(PetscCtxRt ctx)
1619: {
1620: KSPConvergedDefaultCtx *cctx = *(KSPConvergedDefaultCtx **)ctx;
1622: PetscFunctionBegin;
1623: PetscCall(VecDestroy(&cctx->work));
1624: PetscCall(PetscFree(cctx));
1625: PetscFunctionReturn(PETSC_SUCCESS);
1626: }
1628: /*@
1629: KSPBuildSolutionDefault - Default code to build/move the solution.
1631: Collective
1633: Input Parameters:
1634: + ksp - iterative context
1635: - v - pointer to the user's vector
1637: Output Parameter:
1638: . V - pointer to a vector containing the solution
1640: Level: advanced
1642: Note:
1643: Some `KSP` methods such as `KSPGMRES` do not compute the explicit solution at each iteration, this routine takes the information
1644: they have computed during the previous iterations and uses it to compute the explicit solution
1646: Developer Note:
1647: This is `PETSC_EXTERN` because it may be used by user written plugin `KSPType` implementations
1649: .seealso: [](ch_ksp), `KSP`, `KSPGetSolution()`, `KSPBuildResidualDefault()`
1650: @*/
1651: PetscErrorCode KSPBuildSolutionDefault(KSP ksp, Vec v, Vec *V)
1652: {
1653: PetscFunctionBegin;
1654: if (ksp->pc_side == PC_RIGHT) {
1655: if (ksp->pc) {
1656: PetscCheck(v, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with right preconditioner");
1657: PetscCall(KSP_PCApply(ksp, ksp->vec_sol, v));
1658: *V = v;
1659: } else {
1660: if (v) {
1661: PetscCall(VecCopy(ksp->vec_sol, v));
1662: *V = v;
1663: } else *V = ksp->vec_sol;
1664: }
1665: } else if (ksp->pc_side == PC_SYMMETRIC) {
1666: if (ksp->pc) {
1667: PetscCheck(!ksp->transpose_solve, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with symmetric preconditioner and transpose solve");
1668: PetscCheck(v, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "Not working with symmetric preconditioner");
1669: PetscCall(PCApplySymmetricRight(ksp->pc, ksp->vec_sol, v));
1670: *V = v;
1671: } else {
1672: if (v) {
1673: PetscCall(VecCopy(ksp->vec_sol, v));
1674: *V = v;
1675: } else *V = ksp->vec_sol;
1676: }
1677: } else {
1678: if (v) {
1679: PetscCall(VecCopy(ksp->vec_sol, v));
1680: *V = v;
1681: } else *V = ksp->vec_sol;
1682: }
1683: PetscFunctionReturn(PETSC_SUCCESS);
1684: }
1686: /*@
1687: KSPBuildResidualDefault - Default code to compute the residual.
1689: Collecive on ksp
1691: Input Parameters:
1692: + ksp - iterative context
1693: . t - pointer to temporary vector
1694: - v - pointer to user vector
1696: Output Parameter:
1697: . V - pointer to a vector containing the residual
1699: Level: advanced
1701: Note:
1702: Some `KSP` methods such as `KSPGMRES` do not compute the explicit residual at each iteration, this routine takes the information
1703: they have computed during the previous iterations and uses it to compute the explicit residual via the formula r = b - A*x.
1705: Developer Note:
1706: This is `PETSC_EXTERN` because it may be used by user written plugin `KSPType` implementations
1708: .seealso: [](ch_ksp), `KSP`, `KSPBuildSolutionDefault()`
1709: @*/
1710: PetscErrorCode KSPBuildResidualDefault(KSP ksp, Vec t, Vec v, Vec *V)
1711: {
1712: Mat Amat, Pmat;
1714: PetscFunctionBegin;
1715: if (!ksp->pc) PetscCall(KSPGetPC(ksp, &ksp->pc));
1716: PetscCall(PCGetOperators(ksp->pc, &Amat, &Pmat));
1717: PetscCall(KSPBuildSolution(ksp, t, NULL));
1718: PetscCall(KSP_MatMult(ksp, Amat, t, v));
1719: PetscCall(VecAYPX(v, -1.0, ksp->vec_rhs));
1720: *V = v;
1721: PetscFunctionReturn(PETSC_SUCCESS);
1722: }
1724: /*@
1725: KSPCreateVecs - Gets a number of work vectors suitably sized for the operator in the `KSP`
1727: Collective
1729: Input Parameters:
1730: + ksp - iterative context
1731: . rightn - number of right work vectors to allocate
1732: - leftn - number of left work vectors to allocate
1734: Output Parameters:
1735: + right - the array of vectors created
1736: - left - the array of left vectors
1738: Level: advanced
1740: Notes:
1741: The right vector has as many elements as the matrix has columns. The left
1742: vector has as many elements as the matrix has rows, see `MatSetSizes()` for details on the layout of the vectors.
1744: The vectors are new vectors that are not owned by the `KSP`, they should be destroyed with calls to `VecDestroyVecs()` when no longer needed.
1746: PETSc `Vec` always have all zero entries when created with `KSPCreateVecs()` until routines such as `VecSet()` or `VecSetValues()`
1747: are used to change the values. There is no reason to call `VecZeroEntries()` after creation.
1749: Developer Note:
1750: First tries to duplicate the rhs and solution vectors of the `KSP`, if they do not exist tries to get them from the matrix with `MatCreateVecs()`, if
1751: that does not exist tries to get them from the `DM` (if it is provided) with `DMCreateGlobalVectors()`.
1753: .seealso: [](ch_ksp), `MatCreateVecs()`, `VecDestroyVecs()`, `KSPSetWorkVecs()`
1754: @*/
1755: PetscErrorCode KSPCreateVecs(KSP ksp, PetscInt rightn, Vec *right[], PetscInt leftn, Vec *left[])
1756: {
1757: Vec vecr = NULL, vecl = NULL;
1758: PetscBool matset, pmatset, isshell, preferdm = PETSC_FALSE;
1759: Mat mat = NULL;
1761: PetscFunctionBegin;
1762: if (ksp->dm) {
1763: PetscCall(PetscObjectTypeCompare((PetscObject)ksp->dm, DMSHELL, &isshell));
1764: preferdm = isshell ? PETSC_FALSE : PETSC_TRUE;
1765: }
1766: if (rightn) {
1767: PetscCheck(right, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_INCOMP, "You asked for right vectors but did not pass a pointer to hold them");
1768: if (ksp->vec_sol) vecr = ksp->vec_sol;
1769: else {
1770: if (preferdm) {
1771: PetscCall(DMGetGlobalVector(ksp->dm, &vecr));
1772: } else if (ksp->pc) {
1773: PetscCall(PCGetOperatorsSet(ksp->pc, &matset, &pmatset));
1774: /* check for mat before pmat because for KSPLSQR pmat may be a different size than mat since pmat maybe mat'*mat */
1775: if (matset) {
1776: PetscCall(PCGetOperators(ksp->pc, &mat, NULL));
1777: PetscCall(MatCreateVecs(mat, &vecr, NULL));
1778: } else if (pmatset) {
1779: PetscCall(PCGetOperators(ksp->pc, NULL, &mat));
1780: PetscCall(MatCreateVecs(mat, &vecr, NULL));
1781: }
1782: }
1783: if (!vecr && ksp->dm) PetscCall(DMGetGlobalVector(ksp->dm, &vecr));
1784: PetscCheck(vecr, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "You requested a vector from a KSP that cannot provide one");
1785: }
1786: PetscCall(VecDuplicateVecs(vecr, rightn, right));
1787: if (!ksp->vec_sol) {
1788: if (preferdm) {
1789: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecr));
1790: } else if (mat) {
1791: PetscCall(VecDestroy(&vecr));
1792: } else if (ksp->dm) {
1793: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecr));
1794: }
1795: }
1796: }
1797: if (leftn) {
1798: PetscCheck(left, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_INCOMP, "You asked for left vectors but did not pass a pointer to hold them");
1799: if (ksp->vec_rhs) vecl = ksp->vec_rhs;
1800: else {
1801: if (preferdm) {
1802: PetscCall(DMGetGlobalVector(ksp->dm, &vecl));
1803: } else if (ksp->pc) {
1804: PetscCall(PCGetOperatorsSet(ksp->pc, &matset, &pmatset));
1805: /* check for mat before pmat because for KSPLSQR pmat may be a different size than mat since pmat maybe mat'*mat */
1806: if (matset) {
1807: PetscCall(PCGetOperators(ksp->pc, &mat, NULL));
1808: PetscCall(MatCreateVecs(mat, NULL, &vecl));
1809: } else if (pmatset) {
1810: PetscCall(PCGetOperators(ksp->pc, NULL, &mat));
1811: PetscCall(MatCreateVecs(mat, NULL, &vecl));
1812: }
1813: }
1814: if (!vecl && ksp->dm) PetscCall(DMGetGlobalVector(ksp->dm, &vecl));
1815: PetscCheck(vecl, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_WRONGSTATE, "You requested a vector from a KSP that cannot provide one");
1816: }
1817: PetscCall(VecDuplicateVecs(vecl, leftn, left));
1818: if (!ksp->vec_rhs) {
1819: if (preferdm) {
1820: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecl));
1821: } else if (mat) {
1822: PetscCall(VecDestroy(&vecl));
1823: } else if (ksp->dm) {
1824: PetscCall(DMRestoreGlobalVector(ksp->dm, &vecl));
1825: }
1826: }
1827: }
1828: PetscFunctionReturn(PETSC_SUCCESS);
1829: }
1831: /*@
1832: KSPSetWorkVecs - Sets a number of work vectors into a `KSP` object
1834: Collective
1836: Input Parameters:
1837: + ksp - iterative context
1838: - nw - number of work vectors to allocate
1840: Level: developer
1842: Developer Note:
1843: This is `PETSC_EXTERN` because it may be used by user written plugin `KSPType` implementations
1845: .seealso: [](ch_ksp), `KSP`, `KSPCreateVecs()`
1846: @*/
1847: PetscErrorCode KSPSetWorkVecs(KSP ksp, PetscInt nw)
1848: {
1849: PetscFunctionBegin;
1850: PetscCall(VecDestroyVecs(ksp->nwork, &ksp->work));
1851: ksp->nwork = nw;
1852: PetscCall(KSPCreateVecs(ksp, nw, &ksp->work, 0, NULL));
1853: PetscFunctionReturn(PETSC_SUCCESS);
1854: }
1856: /*@
1857: KSPDestroyDefault - Destroys an iterative context variable for methods with no separate context. Preferred calling sequence `KSPDestroy()`.
1859: Collective
1861: Input Parameter:
1862: . ksp - the iterative context
1864: Level: advanced
1866: Developer Note:
1867: This is `PETSC_EXTERN` because it may be used by user written plugin `KSPType` implementations
1869: .seealso: [](ch_ksp), `KSP`, `KSPDestroy()`
1870: @*/
1871: PetscErrorCode KSPDestroyDefault(KSP ksp)
1872: {
1873: PetscFunctionBegin;
1875: PetscCall(PetscFree(ksp->data));
1876: PetscFunctionReturn(PETSC_SUCCESS);
1877: }
1879: /*@
1880: KSPGetConvergedReason - Gets the reason the `KSP` iteration was stopped.
1882: Not Collective
1884: Input Parameter:
1885: . ksp - the `KSP` context
1887: Output Parameter:
1888: . reason - negative value indicates diverged, positive value converged, see `KSPConvergedReason` for the possible values
1890: Options Database Key:
1891: . -ksp_converged_reason - prints the reason to standard out when the solve ends
1893: Level: intermediate
1895: Note:
1896: If this routine is called before or doing the `KSPSolve()` the value of `KSP_CONVERGED_ITERATING` is returned
1898: .seealso: [](ch_ksp), `KSPConvergedReason`, `KSP`, `KSPSetConvergenceTest()`, `KSPConvergedDefault()`, `KSPSetTolerances()`,
1899: `KSPConvergedReasonView()`, `KSPGetConvergedReasonString()`
1900: @*/
1901: PetscErrorCode KSPGetConvergedReason(KSP ksp, KSPConvergedReason *reason)
1902: {
1903: PetscFunctionBegin;
1905: PetscAssertPointer(reason, 2);
1906: *reason = ksp->reason;
1907: PetscFunctionReturn(PETSC_SUCCESS);
1908: }
1910: /*@
1911: KSPGetConvergedReasonString - Return a human readable string for a `KSPConvergedReason`
1913: Not Collective
1915: Input Parameter:
1916: . ksp - the `KSP` context
1918: Output Parameter:
1919: . strreason - a human readable string that describes ksp converged reason
1921: Level: beginner
1923: .seealso: [](ch_ksp), `KSP`, `KSPGetConvergedReason()`
1924: @*/
1925: PetscErrorCode KSPGetConvergedReasonString(KSP ksp, const char *strreason[])
1926: {
1927: PetscFunctionBegin;
1929: PetscAssertPointer(strreason, 2);
1930: *strreason = KSPConvergedReasons[ksp->reason];
1931: PetscFunctionReturn(PETSC_SUCCESS);
1932: }
1934: #include <petsc/private/dmimpl.h>
1935: /*@
1936: KSPSetDM - Sets the `DM` that may be used by some preconditioners and that may be used to construct the linear system
1938: Logically Collective
1940: Input Parameters:
1941: + ksp - the `KSP`
1942: - dm - the `DM`, cannot be `NULL` to remove a previously set `DM`
1944: Level: intermediate
1946: Notes:
1947: If this is used then the `KSP` will attempt to use the `DM` to create the matrix and use the routine set with
1948: `DMKSPSetComputeOperators()`. Use `KSPSetDMActive`(ksp, `KSP_DMACTIVE_OPERATOR`, `PETSC_FALSE`) to instead use the matrix you've provided with
1949: `KSPSetOperators()`.
1951: A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
1952: even when not using interfaces like `DMKSPSetComputeOperators()`. Use `DMClone()` to get a distinct `DM` when solving
1953: different problems using the same function space.
1955: .seealso: [](ch_ksp), `KSP`, `DM`, `KSPGetDM()`, `KSPSetDMActive()`, `KSPSetComputeOperators()`, `KSPSetComputeRHS()`, `KSPSetComputeInitialGuess()`, `DMKSPSetComputeOperators()`, `DMKSPSetComputeRHS()`, `DMKSPSetComputeInitialGuess()`
1956: @*/
1957: PetscErrorCode KSPSetDM(KSP ksp, DM dm)
1958: {
1959: PetscFunctionBegin;
1962: PetscCall(PetscObjectReference((PetscObject)dm));
1963: if (ksp->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
1964: if (ksp->dm->dmksp && !dm->dmksp) {
1965: DMKSP kdm;
1966: PetscCall(DMCopyDMKSP(ksp->dm, dm));
1967: PetscCall(DMGetDMKSP(ksp->dm, &kdm));
1968: if (kdm->originaldm == ksp->dm) kdm->originaldm = dm; /* Grant write privileges to the replacement DM */
1969: }
1970: PetscCall(DMDestroy(&ksp->dm));
1971: }
1972: ksp->dm = dm;
1973: ksp->dmAuto = PETSC_FALSE;
1974: ksp->dmActive = KSP_DMACTIVE_ALL;
1975: if (ksp->pc) PetscCall(PCSetDM(ksp->pc, dm));
1976: PetscFunctionReturn(PETSC_SUCCESS);
1977: }
1979: /*@
1980: KSPSetDMActive - Indicates the `DM` should be used to generate the linear system matrix, the right-hand side vector, and the initial guess
1982: Logically Collective
1984: Input Parameters:
1985: + ksp - the `KSP`
1986: . active - one of `KSP_DMACTIVE_OPERATOR`, `KSP_DMACTIVE_RHS`, or `KSP_DMACTIVE_INITIAL_GUESS`
1987: - flg - use the `DM`
1989: Level: intermediate
1991: Note:
1992: By default `KSPSetDM()` sets the `DM` as active.
1994: .seealso: [](ch_ksp), `KSP`, `DM`, `KSPGetDM()`, `KSPSetDM()`, `SNESSetDM()`, `KSPSetComputeOperators()`, `KSPSetComputeRHS()`, `KSPSetComputeInitialGuess()`
1995: @*/
1996: PetscErrorCode KSPSetDMActive(KSP ksp, KSPDMActive active, PetscBool flg)
1997: {
1998: PetscFunctionBegin;
2001: if (flg) ksp->dmActive = (KSPDMActive)(ksp->dmActive | active);
2002: else ksp->dmActive = (KSPDMActive)(ksp->dmActive & ~active);
2003: PetscFunctionReturn(PETSC_SUCCESS);
2004: }
2006: /*@
2007: KSPGetDM - Gets the `DM` that may be used by some preconditioners and that may be used to construct the linear system
2009: Not Collective
2011: Input Parameter:
2012: . ksp - the `KSP`
2014: Output Parameter:
2015: . dm - the `DM`
2017: Level: intermediate
2019: .seealso: [](ch_ksp), `KSP`, `DM`, `KSPSetDM()`, `KSPSetDMActive()`
2020: @*/
2021: PetscErrorCode KSPGetDM(KSP ksp, DM *dm)
2022: {
2023: PetscFunctionBegin;
2025: if (!ksp->dm) {
2026: PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ksp), &ksp->dm));
2027: ksp->dmAuto = PETSC_TRUE;
2028: }
2029: *dm = ksp->dm;
2030: PetscFunctionReturn(PETSC_SUCCESS);
2031: }
2033: /*@
2034: KSPSetApplicationContext - Sets the optional user-defined context for the linear solver.
2036: Logically Collective
2038: Input Parameters:
2039: + ksp - the `KSP` context
2040: - ctx - application context
2042: Level: intermediate
2044: Notes:
2045: The application context is a way for users to attach any information to the `KSP` that they may need later when interacting with the `KSP`
2047: Use `KSPGetApplicationContext()` to get access to the context at a later time.
2049: Fortran Note:
2050: This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
2051: function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `KSPGetApplicationContext()` for
2052: an example.
2054: .seealso: [](ch_ksp), `KSP`, `KSPGetApplicationContext()`
2055: @*/
2056: PetscErrorCode KSPSetApplicationContext(KSP ksp, PetscCtx ctx)
2057: {
2058: PC pc;
2060: PetscFunctionBegin;
2062: ksp->ctx = ctx;
2063: PetscCall(KSPGetPC(ksp, &pc));
2064: PetscCall(PCSetApplicationContext(pc, ctx));
2065: PetscFunctionReturn(PETSC_SUCCESS);
2066: }
2068: /*@
2069: KSPGetApplicationContext - Gets the user-defined context for the linear solver set with `KSPSetApplicationContext()`
2071: Not Collective
2073: Input Parameter:
2074: . ksp - `KSP` context
2076: Output Parameter:
2077: . ctx - a pointer to the application context
2079: Level: intermediate
2081: Fortran Notes:
2082: This only works when the context is a Fortran derived type or a `PetscObject`. Define `ctx` with
2083: .vb
2084: type(tUsertype), pointer :: ctx
2085: .ve
2087: .seealso: [](ch_ksp), `KSP`, `KSPSetApplicationContext()`
2088: @*/
2089: PetscErrorCode KSPGetApplicationContext(KSP ksp, PetscCtxRt ctx)
2090: {
2091: PetscFunctionBegin;
2093: *(void **)ctx = ksp->ctx;
2094: PetscFunctionReturn(PETSC_SUCCESS);
2095: }
2097: #include <petsc/private/pcimpl.h>
2099: static PetscErrorCode KSPCheckSolve_Private(KSP ksp, PC pc, Vec vec, Mat mat)
2100: {
2101: PCFailedReason pcreason;
2102: PC subpc;
2103: PetscBool failed;
2105: PetscFunctionBegin;
2106: PetscCall(KSPGetPC(ksp, &subpc));
2107: PetscCall(PCGetFailedReason(subpc, &pcreason));
2108: failed = (PetscBool)(pcreason || (ksp->reason < 0 && ksp->reason != KSP_DIVERGED_ITS));
2109: PetscCall(VecFlag(vec, failed));
2110: PetscCall(MatFlag(mat, failed));
2111: if (failed) {
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: }
2116: PetscFunctionReturn(PETSC_SUCCESS);
2117: }
2119: /*@
2120: KSPCheckSolve - Checks if the `PCSetUp()` or `KSPSolve()` failed and set the error flag for the outer `PC`. A `KSP_DIVERGED_ITS` is
2121: not considered a failure in this context
2123: Logically Collective
2125: Input Parameters:
2126: + ksp - the linear solver `KSP` context.
2127: . pc - the preconditioner context
2128: - vec - a vector that will be initialized with infinity to indicate lack of convergence
2130: Level: developer
2132: Note:
2133: This is called within `PCApply()` implementations to check if an error has been detected on any particular MPI processes. By initializing the vector
2134: with infinity the next call to `KSPCheckNorm()` or `KSPCheckDot()` will provide the same information to all the MPI processes that an error occurred on
2135: at least one of the processes.
2137: If `vec` is `NULL`, it must be `NULL` on all calling processes.
2139: This may be called by a subset of the processes in the `PC`.
2141: Developer Note:
2142: This is used to manage returning with appropriate information from preconditioners whose inner `KSP` solvers have failed in some way
2144: .seealso: [](ch_ksp), `KSP`, `KSPCreate()`, `KSPSetType()`, `KSPCheckNorm()`, `KSPCheckDot()`, `KSPCheckMatSolve()`
2145: @*/
2146: PetscErrorCode KSPCheckSolve(KSP ksp, PC pc, Vec vec)
2147: {
2148: PetscFunctionBegin;
2149: PetscCall(KSPCheckSolve_Private(ksp, pc, vec, NULL));
2150: PetscFunctionReturn(PETSC_SUCCESS);
2151: }
2153: /*@
2154: KSPCheckMatSolve - Checks whether an inner matrix solve failed and flags its solution and the outer preconditioner
2156: Logically Collective
2158: Input Parameters:
2159: + ksp - the inner linear solver context
2160: . pc - the outer preconditioner context
2161: - mat - the `MATDENSE` solution matrix to flag
2163: Level: developer
2165: Notes:
2166: This is the matrix counterpart of `KSPCheckSolve()`, for use after `KSPMatSolve()` or `KSPMatSolveTranspose()`
2167: within a `PCMatApply()` or `PCMatApplyTranspose()` implementation.
2169: If the inner preconditioner reports a failure, or `ksp` has a negative convergence reason other than `KSP_DIVERGED_ITS`,
2170: the local portion of `mat` is set to infinity with `MatFlag()` and the outer `pc` is marked with `PC_SUBPC_ERROR`.
2171: If the outer `pc` is configured to raise an error on failure, this routine raises the error after flagging `mat`.
2173: Without a failure, the entries of `mat` are unchanged. Its object state is increased in either case.
2175: If `mat` is `NULL`, it must be `NULL` on all calling processes.
2177: This may be called by a subset of the processes in the `PC`.
2179: Example Usage:
2180: .vb
2181: PetscCall(KSPMatSolve(ksp, B, X));
2182: PetscCall(KSPCheckMatSolve(ksp, pc, X));
2183: .ve
2185: .seealso: [](ch_ksp), `KSP`, `PC`, `KSPCheckSolve()`, `KSPMatSolve()`, `KSPMatSolveTranspose()`, `MatFlag()`, `PCGetFailedReason()`, `PCSetErrorIfFailure()`
2186: @*/
2187: PetscErrorCode KSPCheckMatSolve(KSP ksp, PC pc, Mat mat)
2188: {
2189: PetscFunctionBegin;
2190: PetscCall(KSPCheckSolve_Private(ksp, pc, NULL, mat));
2191: PetscFunctionReturn(PETSC_SUCCESS);
2192: }