Actual source code: snesut.c
1: #include <petsc/private/snesimpl.h>
2: #include <petscdm.h>
3: #include <petscsection.h>
4: #include <petscblaslapack.h>
6: /*@C
7: SNESMonitorSolution - Monitors progress of a `SNES` `SNESSolve()` by calling
8: `VecView()` for the approximate solution at each iteration.
10: Collective
12: Input Parameters:
13: + snes - the `SNES` context
14: . its - iteration number
15: . fgnorm - 2-norm of residual
16: - vf - a viewer
18: Options Database Key:
19: . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
21: Level: intermediate
23: Note:
24: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
25: to be used during the `SNESSolve()`
27: .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`
28: @*/
29: PetscErrorCode SNESMonitorSolution(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
30: {
31: Vec x;
32: PetscViewer viewer = vf->viewer;
34: PetscFunctionBegin;
36: PetscCall(SNESGetSolution(snes, &x));
37: PetscCall(PetscViewerPushFormat(viewer, vf->format));
38: PetscCall(VecView(x, viewer));
39: PetscCall(PetscViewerPopFormat(viewer));
40: PetscFunctionReturn(PETSC_SUCCESS);
41: }
43: /*@C
44: SNESMonitorResidual - Monitors progress of a `SNESSolve()` by calling
45: `VecView()` for the residual at each iteration.
47: Collective
49: Input Parameters:
50: + snes - the `SNES` context
51: . its - iteration number
52: . fgnorm - 2-norm of residual
53: - vf - a viewer
55: Options Database Key:
56: . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration
58: Level: intermediate
60: Note:
61: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
62: to be used during the `SNES` solve.
64: .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`, `SNESMonitor()`
65: @*/
66: PetscErrorCode SNESMonitorResidual(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
67: {
68: Vec x;
70: PetscFunctionBegin;
72: PetscCall(SNESGetFunction(snes, &x, NULL, NULL));
73: PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
74: PetscCall(VecView(x, vf->viewer));
75: PetscCall(PetscViewerPopFormat(vf->viewer));
76: PetscFunctionReturn(PETSC_SUCCESS);
77: }
79: /*@C
80: SNESMonitorSolutionUpdate - Monitors progress of a `SNESSolve()` by calling
81: `VecView()` for the UPDATE to the solution at each iteration.
83: Collective
85: Input Parameters:
86: + snes - the `SNES` context
87: . its - iteration number
88: . fgnorm - 2-norm of residual
89: - vf - a viewer
91: Options Database Key:
92: . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
94: Level: intermediate
96: Note:
97: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
98: to be used during the `SNES` solve.
100: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`, `SNESMonitor()`
101: @*/
102: PetscErrorCode SNESMonitorSolutionUpdate(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
103: {
104: Vec x;
105: PetscViewer viewer = vf->viewer;
107: PetscFunctionBegin;
109: PetscCall(SNESGetSolutionUpdate(snes, &x));
110: PetscCall(PetscViewerPushFormat(viewer, vf->format));
111: PetscCall(VecView(x, viewer));
112: PetscCall(PetscViewerPopFormat(viewer));
113: PetscFunctionReturn(PETSC_SUCCESS);
114: }
116: #include <petscdraw.h>
118: /*@C
119: KSPMonitorSNESResidual - Prints the `SNES` residual norm, as well as the `KSP` residual norm, at each iteration of a `KSPSolve()` called within a `SNESSolve()`.
121: Collective
123: Input Parameters:
124: + ksp - iterative context
125: . n - iteration number
126: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
127: - vf - The viewer context
129: Options Database Key:
130: . -snes_monitor_ksp - Activates `KSPMonitorSNESResidual()`
132: Level: intermediate
134: Note:
135: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
136: to be used during the `KSP` solve.
138: .seealso: [](ch_snes), `SNES`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`, `KSPMonitor()`, `SNESMonitor()`, `PetscViewerAndFormat()`
139: @*/
140: PetscErrorCode KSPMonitorSNESResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
141: {
142: PetscViewer viewer = vf->viewer;
143: PetscViewerFormat format = vf->format;
144: SNES snes = (SNES)vf->data;
145: Vec snes_solution, work1, work2;
146: PetscReal snorm;
147: PetscInt tablevel;
148: const char *prefix;
150: PetscFunctionBegin;
152: PetscCall(SNESGetSolution(snes, &snes_solution));
153: PetscCall(VecDuplicate(snes_solution, &work1));
154: PetscCall(VecDuplicate(snes_solution, &work2));
155: PetscCall(KSPBuildSolution(ksp, work1, NULL));
156: PetscCall(VecAYPX(work1, -1.0, snes_solution));
157: PetscCall(SNESComputeFunction(snes, work1, work2));
158: PetscCall(VecNorm(work2, NORM_2, &snorm));
159: PetscCall(VecDestroy(&work1));
160: PetscCall(VecDestroy(&work2));
162: PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
163: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
164: PetscCall(PetscViewerPushFormat(viewer, format));
165: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
166: if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix));
167: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Residual norm %5.3e KSP Residual norm %5.3e\n", n, (double)snorm, (double)rnorm));
168: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
169: PetscCall(PetscViewerPopFormat(viewer));
170: PetscFunctionReturn(PETSC_SUCCESS);
171: }
173: /*@C
174: KSPMonitorSNESResidualDrawLG - Plots the linear `KSP` residual norm and the `SNES` residual norm of a `KSPSolve()` called within a `SNESSolve()`.
176: Collective
178: Input Parameters:
179: + ksp - iterative context
180: . n - iteration number
181: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
182: - vf - The viewer context, created with `KSPMonitorSNESResidualDrawLGCreate()`
184: Options Database Key:
185: . -snes_monitor_ksp draw::draw_lg - Activates `KSPMonitorSNESResidualDrawLG()`
187: Level: intermediate
189: Note:
190: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
191: to be used during the `SNESSolve()`
193: .seealso: [](ch_snes), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `SNESMonitor()`, `KSPMonitor()`, `KSPMonitorSNESResidualDrawLGCreate()`
194: @*/
195: PetscErrorCode KSPMonitorSNESResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
196: {
197: PetscViewer viewer = vf->viewer;
198: PetscViewerFormat format = vf->format;
199: PetscDrawLG lg;
200: SNES snes = (SNES)vf->data;
201: Vec snes_solution, work1, work2;
202: PetscReal snorm;
203: KSPConvergedReason reason;
204: PetscReal x[2], y[2];
206: PetscFunctionBegin;
208: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
209: PetscCall(SNESGetSolution(snes, &snes_solution));
210: PetscCall(VecDuplicate(snes_solution, &work1));
211: PetscCall(VecDuplicate(snes_solution, &work2));
212: PetscCall(KSPBuildSolution(ksp, work1, NULL));
213: PetscCall(VecAYPX(work1, -1.0, snes_solution));
214: PetscCall(SNESComputeFunction(snes, work1, work2));
215: PetscCall(VecNorm(work2, NORM_2, &snorm));
216: PetscCall(VecDestroy(&work1));
217: PetscCall(VecDestroy(&work2));
219: PetscCall(PetscViewerPushFormat(viewer, format));
220: if (!n) PetscCall(PetscDrawLGReset(lg));
221: x[0] = (PetscReal)n;
222: if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
223: else y[0] = -15.0;
224: x[1] = (PetscReal)n;
225: if (snorm > 0.0) y[1] = PetscLog10Real(snorm);
226: else y[1] = -15.0;
227: PetscCall(PetscDrawLGAddPoint(lg, x, y));
228: PetscCall(KSPGetConvergedReason(ksp, &reason));
229: if (n <= 20 || !(n % 5) || reason) {
230: PetscCall(PetscDrawLGDraw(lg));
231: PetscCall(PetscDrawLGSave(lg));
232: }
233: PetscCall(PetscViewerPopFormat(viewer));
234: PetscFunctionReturn(PETSC_SUCCESS);
235: }
237: /*@C
238: KSPMonitorSNESResidualDrawLGCreate - Creates the `PetscViewer` used by `KSPMonitorSNESResidualDrawLG()`
240: Collective
242: Input Parameters:
243: + viewer - The `PetscViewer`
244: . format - The viewer format
245: - ctx - An optional application context
247: Output Parameter:
248: . vf - The viewer context
250: Level: intermediate
252: .seealso: [](ch_snes), `KSP`, `SNES`, `PetscViewerFormat`, `PetscViewerAndFormat`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
253: @*/
254: PetscErrorCode KSPMonitorSNESResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, PetscCtx ctx, PetscViewerAndFormat **vf)
255: {
256: const char *names[] = {"linear", "nonlinear"};
258: PetscFunctionBegin;
259: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
260: (*vf)->data = ctx;
261: PetscCall(PetscViewerMonitorLGSetUp(viewer, NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300));
262: PetscFunctionReturn(PETSC_SUCCESS);
263: }
265: /*@C
266: SNESMonitorDefaultSetUp - Prepare the `PetscViewerAndFormat` associated with `SNESMonitorDefault()`, in particular by initializing the underlying `PetscDrawLG` when the viewer format is `PETSC_VIEWER_DRAW_LG`
268: Collective
270: Input Parameters:
271: + snes - the `SNES` context
272: - vf - the viewer/format pair passed to `SNESMonitorSet()` along with `SNESMonitorDefault()`
274: Level: developer
276: .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`, `SNESMonitorDefault()`, `PetscViewerAndFormat`, `PetscViewerMonitorLGSetUp()`
277: @*/
278: PetscErrorCode SNESMonitorDefaultSetUp(SNES snes, PetscViewerAndFormat *vf)
279: {
280: PetscFunctionBegin;
281: if (vf->format == PETSC_VIEWER_DRAW_LG) PetscCall(PetscViewerMonitorLGSetUp(vf->viewer, NULL, NULL, "Log Residual Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300));
282: PetscFunctionReturn(PETSC_SUCCESS);
283: }
285: /*@C
286: SNESMonitorDefault - Monitors progress of a `SNESSolve()` (default).
288: Collective
290: Input Parameters:
291: + snes - the `SNES` context
292: . its - iteration number
293: . fgnorm - 2-norm of residual
294: - vf - viewer and format structure
296: Options Database Key:
297: . -snes_monitor - use this function to monitor the convergence of the nonlinear solver
299: Level: intermediate
301: Notes:
302: Prints the residual norm at each iteration.
304: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
305: to be used during the `SNES` solve.
307: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorFunction()`, `SNESMonitorResidual()`,
308: `SNESMonitorSolutionUpdate()`, `SNESMonitorScaling()`, `SNESMonitorRange()`, `SNESMonitorRatio()`,
309: `SNESMonitorDefaultField()`, `PetscViewerFormat`, `PetscViewerAndFormat`
310: @*/
311: PetscErrorCode SNESMonitorDefault(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
312: {
313: PetscViewer viewer = vf->viewer;
314: PetscViewerFormat format = vf->format;
315: PetscBool isascii, isdraw;
317: PetscFunctionBegin;
319: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
320: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
321: PetscCall(PetscViewerPushFormat(viewer, format));
322: if (isascii) {
323: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
324: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
325: Vec dx;
326: PetscReal upnorm;
327: SNESObjectiveFn *objective;
329: PetscCall(SNESGetSolutionUpdate(snes, &dx));
330: PetscCall(VecNorm(dx, NORM_2, &upnorm));
331: PetscCall(SNESGetObjective(snes, &objective, NULL));
332: if (objective) {
333: Vec x;
334: PetscReal obj;
336: PetscCall(SNESGetSolution(snes, &x));
337: PetscCall(SNESComputeObjective(snes, x, &obj));
338: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e, Update norm %14.12e, Objective %14.12e\n", its, (double)fgnorm, (double)upnorm, (double)obj));
339: } else {
340: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e, Update norm %14.12e\n", its, (double)fgnorm, (double)upnorm));
341: }
342: } else {
343: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e\n", its, (double)fgnorm));
344: }
345: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
346: } else if (isdraw) {
347: if (format == PETSC_VIEWER_DRAW_LG) {
348: PetscDrawLG lg;
349: PetscReal x, y;
351: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
352: if (!its) PetscCall(PetscDrawLGReset(lg));
353: x = (PetscReal)its;
354: if (fgnorm > 0.0) y = PetscLog10Real(fgnorm);
355: else y = -15.0;
356: PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
357: if (its <= 20 || !(its % 5) || snes->reason) {
358: PetscCall(PetscDrawLGDraw(lg));
359: PetscCall(PetscDrawLGSave(lg));
360: }
361: }
362: }
363: PetscCall(PetscViewerPopFormat(viewer));
364: PetscFunctionReturn(PETSC_SUCCESS);
365: }
367: /*@C
368: SNESMonitorScaling - Monitors the largest value in each row of the Jacobian of a `SNESSolve()`
370: Collective
372: Input Parameters:
373: + snes - the `SNES` context
374: . its - iteration number
375: . fgnorm - 2-norm of residual
376: - vf - viewer and format structure
378: Level: intermediate
380: Notes:
381: This routine prints the largest value in each row of the Jacobian
383: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
384: to be used during the `SNES` solve.
386: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `SNESMonitorJacUpdateSpectrum()`,
387: `PetscViewerFormat`, `PetscViewerAndFormat`
388: @*/
389: PetscErrorCode SNESMonitorScaling(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
390: {
391: PetscViewer viewer = vf->viewer;
392: KSP ksp;
393: Mat J;
394: Vec v;
396: PetscFunctionBegin;
398: PetscCall(SNESGetKSP(snes, &ksp));
399: PetscCall(KSPGetOperators(ksp, &J, NULL));
400: PetscCall(MatCreateVecs(J, &v, NULL));
401: PetscCall(MatGetRowMaxAbs(J, v, NULL));
402: PetscCall(PetscViewerPushFormat(viewer, vf->format));
403: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
404: PetscCall(PetscViewerASCIIPrintf(viewer, "SNES Jacobian maximum row entries\n"));
405: PetscCall(VecView(v, viewer));
406: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
407: PetscCall(PetscViewerPopFormat(viewer));
408: PetscCall(VecDestroy(&v));
409: PetscFunctionReturn(PETSC_SUCCESS);
410: }
412: /*@C
413: SNESMonitorJacUpdateSpectrum - Monitors the spectrun of the change in the Jacobian from the last Jacobian evaluation of a `SNESSolve()`
415: Collective
417: Input Parameters:
418: + snes - the `SNES` context
419: . it - iteration number
420: . fnorm - 2-norm of residual
421: - vf - viewer and format structure
423: Options Database Key:
424: . -snes_monitor_jacupdate_spectrum - activates this monitor
426: Level: intermediate
428: Notes:
429: This routine prints the eigenvalues of the difference in the Jacobians
431: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
432: to be used during the `SNES` solve.
434: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `PetscViewerFormat`, `PetscViewerAndFormat`
435: @*/
436: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes, PetscInt it, PetscReal fnorm, PetscViewerAndFormat *vf)
437: {
438: Vec X;
439: Mat J, dJ, dJdense;
440: PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
441: PetscInt n;
442: PetscBLASInt nb = 0, lwork;
443: PetscReal *eigr, *eigi;
444: PetscScalar *work;
445: PetscScalar *a;
447: PetscFunctionBegin;
448: if (it == 0) PetscFunctionReturn(PETSC_SUCCESS);
449: /* create the difference between the current update and the current Jacobian */
450: PetscCall(SNESGetSolution(snes, &X));
451: PetscCall(SNESGetJacobian(snes, NULL, &J, &func, NULL));
452: PetscCall(MatDuplicate(J, MAT_COPY_VALUES, &dJ));
453: PetscCall(SNESComputeJacobian(snes, X, dJ, dJ));
454: PetscCall(MatAXPY(dJ, -1.0, J, SAME_NONZERO_PATTERN));
456: /* compute the spectrum directly */
457: PetscCall(MatConvert(dJ, MATSEQDENSE, MAT_INITIAL_MATRIX, &dJdense));
458: PetscCall(MatGetSize(dJ, &n, NULL));
459: PetscCall(PetscBLASIntCast(n, &nb));
460: lwork = 3 * nb;
461: PetscCall(PetscMalloc1(n, &eigr));
462: PetscCall(PetscMalloc1(n, &eigi));
463: PetscCall(PetscMalloc1(lwork, &work));
464: PetscCall(MatDenseGetArray(dJdense, &a));
465: #if !defined(PETSC_USE_COMPLEX)
466: {
467: PetscBLASInt lierr;
468: PetscInt i;
469: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
470: PetscCallBLAS("LAPACKgeev", LAPACKgeev_("N", "N", &nb, a, &nb, eigr, eigi, NULL, &nb, NULL, &nb, work, &lwork, &lierr));
471: PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "geev() error %" PetscBLASInt_FMT, lierr);
472: PetscCall(PetscFPTrapPop());
473: PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n", it, it - 1));
474: for (i = 0; i < n; i++) PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "%5" PetscInt_FMT ": %20.5g + %20.5gi\n", i, (double)eigr[i], (double)eigi[i]));
475: }
476: PetscCall(MatDenseRestoreArray(dJdense, &a));
477: PetscCall(MatDestroy(&dJ));
478: PetscCall(MatDestroy(&dJdense));
479: PetscCall(PetscFree(eigr));
480: PetscCall(PetscFree(eigi));
481: PetscCall(PetscFree(work));
482: PetscFunctionReturn(PETSC_SUCCESS);
483: #else
484: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded for complex");
485: #endif
486: }
488: PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
490: PetscErrorCode SNESMonitorRange_Private(SNES snes, PetscInt it, PetscReal *per)
491: {
492: Vec resid;
493: PetscReal rmax, pwork;
494: PetscInt i, n, N;
495: PetscScalar *r;
497: PetscFunctionBegin;
498: PetscCall(SNESGetFunction(snes, &resid, NULL, NULL));
499: PetscCall(VecNorm(resid, NORM_INFINITY, &rmax));
500: PetscCall(VecGetLocalSize(resid, &n));
501: PetscCall(VecGetSize(resid, &N));
502: PetscCall(VecGetArray(resid, &r));
503: pwork = 0.0;
504: for (i = 0; i < n; i++) pwork += (PetscAbsScalar(r[i]) > .20 * rmax);
505: PetscCallMPI(MPIU_Allreduce(&pwork, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)snes)));
506: PetscCall(VecRestoreArray(resid, &r));
507: *per = *per / N;
508: PetscFunctionReturn(PETSC_SUCCESS);
509: }
511: /*@C
512: SNESMonitorRange - Prints the percentage of residual elements that are more than 10 percent of the maximum entry in the residual in each iteration of a `SNESSolve()`
514: Collective
516: Input Parameters:
517: + snes - `SNES` iterative context
518: . it - iteration number
519: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
520: - vf - unused monitor context
522: Options Database Key:
523: . -snes_monitor_range - Activates `SNESMonitorRange()`
525: Level: intermediate
527: Note:
528: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
529: to be used during the `SNES` solve.
531: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()`, `SNESMonitorScaling()`, `PetscViewerFormat`, `PetscViewerAndFormat`
532: @*/
533: PetscErrorCode SNESMonitorRange(SNES snes, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf)
534: {
535: PetscReal perc, rel;
536: PetscViewer viewer = vf->viewer;
537: /* should be in a MonitorRangeContext */
538: static PetscReal prev;
540: PetscFunctionBegin;
542: if (!it) prev = rnorm;
543: PetscCall(SNESMonitorRange_Private(snes, it, &perc));
545: rel = (prev - rnorm) / prev;
546: prev = rnorm;
547: PetscCall(PetscViewerPushFormat(viewer, vf->format));
548: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
549: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES preconditioned resid norm %14.12e Percent values above 20 percent of maximum %5.2g relative decrease %5.2e ratio %5.2e\n", it, (double)rnorm, (double)(100 * perc), (double)rel, (double)(rel / perc)));
550: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
551: PetscCall(PetscViewerPopFormat(viewer));
552: PetscFunctionReturn(PETSC_SUCCESS);
553: }
555: /*@C
556: SNESMonitorRatio - Monitors progress of a `SNESSolve()` by printing the ratio of residual norm at each iteration to the previous.
558: Collective
560: Input Parameters:
561: + snes - the `SNES` context
562: . its - iteration number
563: . fgnorm - 2-norm of residual (or gradient)
564: - vf - context of monitor
566: Options Database Key:
567: . -snes_monitor_ratio - activate this monitor
569: Level: intermediate
571: Notes:
572: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
573: to be used during the `SNES` solve.
575: Be sure to call `SNESMonitorRationSetUp()` before using this monitor.
577: .seealso: [](ch_snes), `SNESMonitorRationSetUp()`, `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `PetscViewerFormat`, `PetscViewerAndFormat`
578: @*/
579: PetscErrorCode SNESMonitorRatio(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
580: {
581: PetscInt len;
582: PetscReal *history;
583: PetscViewer viewer = vf->viewer;
585: PetscFunctionBegin;
586: PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, &len));
587: PetscCall(PetscViewerPushFormat(viewer, vf->format));
588: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
589: if (!its || !history || its > len) {
590: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e\n", its, (double)fgnorm));
591: } else {
592: PetscReal ratio = fgnorm / history[its - 1];
593: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e\n", its, (double)fgnorm, (double)ratio));
594: }
595: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
596: PetscCall(PetscViewerPopFormat(viewer));
597: PetscFunctionReturn(PETSC_SUCCESS);
598: }
600: /*@C
601: SNESMonitorRatioSetUp - Insures the `SNES` object is saving its history since this monitor needs access to it
603: Collective
605: Input Parameters:
606: + snes - the `SNES` context
607: - vf - `PetscViewerAndFormat` (ignored)
609: Level: intermediate
611: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()`, `PetscViewerFormat`, `PetscViewerAndFormat`
612: @*/
613: PetscErrorCode SNESMonitorRatioSetUp(SNES snes, PetscViewerAndFormat *vf)
614: {
615: PetscReal *history;
617: PetscFunctionBegin;
618: PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, NULL));
619: if (!history) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, 100, PETSC_TRUE));
620: PetscFunctionReturn(PETSC_SUCCESS);
621: }
623: /*
624: Default (short) SNES Monitor, same as SNESMonitorDefault() except
625: it prints fewer digits of the residual as the residual gets smaller.
626: This is because the later digits are meaningless and are often
627: different on different machines; by using this routine different
628: machines will usually generate the same output.
630: Deprecated: Intentionally has no manual page
631: */
632: PetscErrorCode SNESMonitorDefaultShort(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
633: {
634: PetscViewer viewer = vf->viewer;
636: PetscFunctionBegin;
638: PetscCall(PetscViewerPushFormat(viewer, vf->format));
639: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
640: if (fgnorm > 1.e-9) {
641: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %g\n", its, (double)fgnorm));
642: } else if (fgnorm > 1.e-11) {
643: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %5.3e\n", its, (double)fgnorm));
644: } else {
645: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm < 1.e-11\n", its));
646: }
647: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
648: PetscCall(PetscViewerPopFormat(viewer));
649: PetscFunctionReturn(PETSC_SUCCESS);
650: }
652: /*@C
653: SNESMonitorDefaultField - Monitors progress of a `SNESSolve()`, separated into fields.
655: Collective
657: Input Parameters:
658: + snes - the `SNES` context
659: . its - iteration number
660: . fgnorm - 2-norm of residual
661: - vf - the PetscViewer
663: Options Database Key:
664: . -snes_monitor_field - activate this monitor
666: Level: intermediate
668: Notes:
669: This routine uses the `DM` attached to the residual vector to define the fields.
671: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
672: to be used during the `SNES` solve.
674: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `PetscViewerFormat`, `PetscViewerAndFormat`
675: @*/
676: PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
677: {
678: PetscViewer viewer = vf->viewer;
679: Vec r;
680: DM dm;
681: PetscReal res[256];
682: PetscInt tablevel;
684: PetscFunctionBegin;
686: PetscCall(SNESGetFunction(snes, &r, NULL, NULL));
687: PetscCall(VecGetDM(r, &dm));
688: if (!dm) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf));
689: else {
690: PetscSection s, gs;
691: PetscInt Nf, f;
693: PetscCall(DMGetLocalSection(dm, &s));
694: PetscCall(DMGetGlobalSection(dm, &gs));
695: if (!s || !gs) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf));
696: PetscCall(PetscSectionGetNumFields(s, &Nf));
697: PetscCheck(Nf <= 256, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Do not support %" PetscInt_FMT " fields > 256", Nf);
698: PetscCall(PetscSectionVecNorm(s, gs, r, NORM_2, res));
699: PetscCall(PetscObjectGetTabLevel((PetscObject)snes, &tablevel));
700: PetscCall(PetscViewerPushFormat(viewer, vf->format));
701: PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
702: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double)fgnorm));
703: for (f = 0; f < Nf; ++f) {
704: if (f) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
705: PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f]));
706: }
707: PetscCall(PetscViewerASCIIPrintf(viewer, "] \n"));
708: PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
709: PetscCall(PetscViewerPopFormat(viewer));
710: }
711: PetscFunctionReturn(PETSC_SUCCESS);
712: }
714: /*@C
715: SNESConvergedDefault - Default convergence test for `SNESSolve()`.
717: Collective
719: Input Parameters:
720: + snes - the `SNES` context
721: . it - the iteration (0 indicates before any Newton steps)
722: . xnorm - 2-norm of current iterate
723: . snorm - 2-norm of current step
724: . fnorm - 2-norm of function at current iterate
725: - ctx - unused context
727: Output Parameter:
728: . reason - converged reason, see `SNESConvergedReason`
730: Options Database Keys:
731: + -snes_convergence_test default - see `SNESSetFromOptions()`
732: . -snes_stol - convergence tolerance in terms of the norm of the change in the solution between steps
733: . -snes_atol abstol - absolute tolerance of residual norm
734: . -snes_rtol rtol - relative decrease in tolerance norm from the initial 2-norm of the solution
735: . -snes_divergence_tolerance divtol - if the residual goes above divtol*rnorm0, exit with divergence
736: . -snes_max_funcs max_funcs - maximum number of function evaluations, use `unlimited` for no maximum
737: . -snes_max_fail max_fail - maximum number of line search failures allowed before stopping, default is none
738: - -snes_max_linear_solve_fail - number of linear solver failures before `SNESSolve()` stops
740: Level: developer
742: Notes:
743: This routine is not generally called directly. It is set with `SNESSetConvergenceTest()` automatically before the `SNESSolve()`.
745: It can be called within a custom convergence test that should also apply the standard convergence tests
747: .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()`,
748: `SNESConvergedReason`
749: @*/
750: PetscErrorCode SNESConvergedDefault(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, PetscCtx ctx)
751: {
752: PetscFunctionBegin;
754: PetscAssertPointer(reason, 6);
756: *reason = SNES_CONVERGED_ITERATING;
757: if (!it) {
758: /* set parameter for default relative tolerance convergence test */
759: snes->ttol = fnorm * snes->rtol;
760: snes->rnorm0 = fnorm;
761: }
762: if (PetscIsInfOrNanReal(fnorm)) {
763: PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n"));
764: *reason = SNES_DIVERGED_FUNCTION_NANORINF;
765: } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) {
766: PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e\n", (double)fnorm, (double)snes->abstol));
767: *reason = SNES_CONVERGED_FNORM_ABS;
768: } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) {
769: PetscCall(PetscInfo(snes, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", snes->nfuncs, snes->max_funcs));
770: *reason = SNES_DIVERGED_FUNCTION_COUNT;
771: }
773: if (it && !*reason) {
774: if (fnorm <= snes->ttol) {
775: PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e (relative tolerance)\n", (double)fnorm, (double)snes->ttol));
776: *reason = SNES_CONVERGED_FNORM_RELATIVE;
777: } else if (snorm < snes->stol * xnorm) {
778: PetscCall(PetscInfo(snes, "Converged due to small update length: %14.12e < %14.12e * %14.12e\n", (double)snorm, (double)snes->stol, (double)xnorm));
779: *reason = SNES_CONVERGED_SNORM_RELATIVE;
780: } else if (snes->divtol != PETSC_UNLIMITED && (fnorm > snes->divtol * snes->rnorm0)) {
781: PetscCall(PetscInfo(snes, "Diverged due to increase in function norm: %14.12e > %14.12e * %14.12e\n", (double)fnorm, (double)snes->divtol, (double)snes->rnorm0));
782: *reason = SNES_DIVERGED_DTOL;
783: }
784: }
785: PetscFunctionReturn(PETSC_SUCCESS);
786: }
788: /*@C
789: SNESConvergedSkip - Convergence test for `SNES` that NEVER returns as
790: converged, UNLESS the maximum number of iteration have been reached.
792: Logically Collective
794: Input Parameters:
795: + snes - the `SNES` context
796: . it - the iteration (0 indicates before any Newton steps)
797: . xnorm - 2-norm of current iterate
798: . snorm - 2-norm of current step
799: . fnorm - 2-norm of function at current iterate
800: - ctx - unused context
802: Output Parameter:
803: . reason - `SNES_CONVERGED_ITERATING`, `SNES_CONVERGED_ITS`, or `SNES_DIVERGED_FUNCTION_NANORINF`
805: Options Database Key:
806: . -snes_convergence_test skip - see `SNESSetFromOptions()`
808: Level: advanced
810: Note:
811: This is often used if `snes` is being used as a nonlinear smoother in `SNESFAS` or possibly other `SNESType`
813: .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedDefault()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
814: @*/
815: PetscErrorCode SNESConvergedSkip(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, PetscCtx ctx)
816: {
817: PetscFunctionBegin;
819: PetscAssertPointer(reason, 6);
821: *reason = SNES_CONVERGED_ITERATING;
823: if (fnorm != fnorm) {
824: PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n"));
825: *reason = SNES_DIVERGED_FUNCTION_NANORINF;
826: } else if (it == snes->max_its) {
827: *reason = SNES_CONVERGED_ITS;
828: }
829: PetscFunctionReturn(PETSC_SUCCESS);
830: }
832: /*@
833: SNESSetWorkVecs - Allocates a number of work vectors to be used internally by the `SNES` solver
835: Input Parameters:
836: + snes - the `SNES` context
837: - nw - number of work vectors to allocate
839: Level: developer
841: Note:
842: Each `SNESType` calls this with the number of work vectors that particular type needs.
844: .seealso: [](ch_snes), `SNES`
845: @*/
846: PetscErrorCode SNESSetWorkVecs(SNES snes, PetscInt nw)
847: {
848: DM dm;
849: Vec v;
851: PetscFunctionBegin;
852: if (snes->work) PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
853: snes->nwork = nw;
855: PetscCall(SNESGetDM(snes, &dm));
856: PetscCall(DMGetGlobalVector(dm, &v));
857: PetscCall(VecDuplicateVecs(v, snes->nwork, &snes->work));
858: PetscCall(DMRestoreGlobalVector(dm, &v));
859: PetscFunctionReturn(PETSC_SUCCESS);
860: }