Actual source code: snesut.c
2: #include <petsc/private/snesimpl.h>
3: #include <petscdm.h>
4: #include <petscsection.h>
5: #include <petscblaslapack.h>
7: /*@C
8: SNESMonitorSolution - Monitors progress of the `SNES` solvers by calling
9: `VecView()` for the approximate solution at each iteration.
11: Collective
13: Input Parameters:
14: + snes - the `SNES` context
15: . its - iteration number
16: . fgnorm - 2-norm of residual
17: - dummy - a viewer
19: Options Database Key:
20: . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
22: Note:
23: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
24: to be used during the `SNESSolve()`
26: Level: intermediate
28: .seealso: `SNES`, `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`
29: @*/
30: PetscErrorCode SNESMonitorSolution(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
31: {
32: Vec x;
33: PetscViewer viewer = vf->viewer;
36: SNESGetSolution(snes, &x);
37: PetscViewerPushFormat(viewer, vf->format);
38: VecView(x, viewer);
39: PetscViewerPopFormat(viewer);
40: return 0;
41: }
43: /*@C
44: SNESMonitorResidual - Monitors progress of the `SNES` solvers 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: - dummy - 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: Note:
59: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
60: to be used during the SNES solve.
62: Level: intermediate
64: .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`, `SNESMonitor()`
65: @*/
66: PetscErrorCode SNESMonitorResidual(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
67: {
68: Vec x;
71: SNESGetFunction(snes, &x, NULL, NULL);
72: PetscViewerPushFormat(vf->viewer, vf->format);
73: VecView(x, vf->viewer);
74: PetscViewerPopFormat(vf->viewer);
75: return 0;
76: }
78: /*@C
79: SNESMonitorSolutionUpdate - Monitors progress of the `SNES` solvers by calling
80: `VecView()` for the UPDATE to the solution at each iteration.
82: Collective
84: Input Parameters:
85: + snes - the `SNES` context
86: . its - iteration number
87: . fgnorm - 2-norm of residual
88: - dummy - a viewer
90: Options Database Key:
91: . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
93: Note:
94: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
95: to be used during the SNES solve.
97: Level: intermediate
99: .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`, `SNESMonitor()`, `SNESMonitor()`
100: @*/
101: PetscErrorCode SNESMonitorSolutionUpdate(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
102: {
103: Vec x;
104: PetscViewer viewer = vf->viewer;
107: SNESGetSolutionUpdate(snes, &x);
108: PetscViewerPushFormat(viewer, vf->format);
109: VecView(x, viewer);
110: PetscViewerPopFormat(viewer);
111: return 0;
112: }
114: #include <petscdraw.h>
116: /*@C
117: KSPMonitorSNESResidual - Prints the `SNES` residual norm, as well as the `KSP` residual norm, at each iteration of an iterative solver.
119: Collective
121: Input Parameters:
122: + ksp - iterative context
123: . n - iteration number
124: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
125: - vf - The viewer context
127: Options Database Key:
128: . -snes_monitor_ksp - Activates `KSPMonitorSNESResidual()`
130: Note:
131: This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
132: to be used during the KSP solve.
134: Level: intermediate
136: .seealso: `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`, `KSPMonitor()`, `SNESMonitor()`
137: @*/
138: PetscErrorCode KSPMonitorSNESResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
139: {
140: PetscViewer viewer = vf->viewer;
141: PetscViewerFormat format = vf->format;
142: SNES snes = (SNES)vf->data;
143: Vec snes_solution, work1, work2;
144: PetscReal snorm;
145: PetscInt tablevel;
146: const char *prefix;
149: SNESGetSolution(snes, &snes_solution);
150: VecDuplicate(snes_solution, &work1);
151: VecDuplicate(snes_solution, &work2);
152: KSPBuildSolution(ksp, work1, NULL);
153: VecAYPX(work1, -1.0, snes_solution);
154: SNESComputeFunction(snes, work1, work2);
155: VecNorm(work2, NORM_2, &snorm);
156: VecDestroy(&work1);
157: VecDestroy(&work2);
159: PetscObjectGetTabLevel((PetscObject)ksp, &tablevel);
160: PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix);
161: PetscViewerPushFormat(viewer, format);
162: PetscViewerASCIIAddTab(viewer, tablevel);
163: if (n == 0 && prefix) PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix);
164: PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Residual norm %5.3e KSP Residual norm %5.3e \n", n, (double)snorm, (double)rnorm);
165: PetscViewerASCIISubtractTab(viewer, tablevel);
166: PetscViewerPopFormat(viewer);
167: return 0;
168: }
170: /*@C
171: KSPMonitorSNESResidualDrawLG - Plots the linear `KSP` residual norm and the `SNES` residual norm at each iteration of an iterative solver.
173: Collective
175: Input Parameters:
176: + ksp - iterative context
177: . n - iteration number
178: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
179: - vf - The viewer context, created with `KSPMonitorSNESResidualDrawLGCreate()`
181: Options Database Key:
182: . -snes_monitor_ksp draw::draw_lg - Activates `KSPMonitorSNESResidualDrawLG()`
184: Note:
185: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
186: to be used during the `SNESSolve()`
188: Level: intermediate
190: .seealso: `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `SNESMonitor()`, `KSPMonitor()`, `KSPMonitorSNESResidualDrawLGCreate()`
191: @*/
192: PetscErrorCode KSPMonitorSNESResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
193: {
194: PetscViewer viewer = vf->viewer;
195: PetscViewerFormat format = vf->format;
196: PetscDrawLG lg = vf->lg;
197: SNES snes = (SNES)vf->data;
198: Vec snes_solution, work1, work2;
199: PetscReal snorm;
200: KSPConvergedReason reason;
201: PetscReal x[2], y[2];
205: SNESGetSolution(snes, &snes_solution);
206: VecDuplicate(snes_solution, &work1);
207: VecDuplicate(snes_solution, &work2);
208: KSPBuildSolution(ksp, work1, NULL);
209: VecAYPX(work1, -1.0, snes_solution);
210: SNESComputeFunction(snes, work1, work2);
211: VecNorm(work2, NORM_2, &snorm);
212: VecDestroy(&work1);
213: VecDestroy(&work2);
215: PetscViewerPushFormat(viewer, format);
216: if (!n) PetscDrawLGReset(lg);
217: x[0] = (PetscReal)n;
218: if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
219: else y[0] = -15.0;
220: x[1] = (PetscReal)n;
221: if (snorm > 0.0) y[1] = PetscLog10Real(snorm);
222: else y[1] = -15.0;
223: PetscDrawLGAddPoint(lg, x, y);
224: KSPGetConvergedReason(ksp, &reason);
225: if (n <= 20 || !(n % 5) || reason) {
226: PetscDrawLGDraw(lg);
227: PetscDrawLGSave(lg);
228: }
229: PetscViewerPopFormat(viewer);
230: return 0;
231: }
233: /*@C
234: KSPMonitorSNESResidualDrawLGCreate - Creates the `PetscViewer` used by `KSPMonitorSNESResidualDrawLG()`
236: Collective
238: Input Parameters:
239: + viewer - The PetscViewer
240: . format - The viewer format
241: - ctx - An optional user context
243: Output Parameter:
244: . vf - The viewer context
246: Level: intermediate
248: .seealso: `KSP`, `SNES`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
249: @*/
250: PetscErrorCode KSPMonitorSNESResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
251: {
252: const char *names[] = {"linear", "nonlinear"};
254: PetscViewerAndFormatCreate(viewer, format, vf);
255: (*vf)->data = ctx;
256: KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg);
257: return 0;
258: }
260: PetscErrorCode SNESMonitorDefaultSetUp(SNES snes, PetscViewerAndFormat *vf)
261: {
262: if (vf->format == PETSC_VIEWER_DRAW_LG) KSPMonitorLGCreate(PetscObjectComm((PetscObject)vf->viewer), NULL, NULL, "Log Residual Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &vf->lg);
263: return 0;
264: }
266: /*@C
267: SNESMonitorDefault - Monitors progress of the `SNES` solvers (default).
269: Collective
271: Input Parameters:
272: + snes - the `SNES` context
273: . its - iteration number
274: . fgnorm - 2-norm of residual
275: - vf - viewer and format structure
277: Options Database Key:
278: . -snes_monitor - use this function to monitor the convergence of the nonlinear solver
280: Notes:
281: This routine prints the residual norm at each iteration.
283: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
284: to be used during the `SNES` solve.
286: Level: intermediate
288: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorFunction()`, `SNESMonitorSolution()`, `SNESMonitorResidual()`,
289: `SNESMonitorSolutionUpdate()`, `SNESMonitorDefault()`, `SNESMonitorScaling()`, `SNESMonitorRange()`, `SNESMonitorRatio()`,
290: `SNESMonitorDefaultField()`
291: @*/
292: PetscErrorCode SNESMonitorDefault(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
293: {
294: PetscViewer viewer = vf->viewer;
295: PetscViewerFormat format = vf->format;
296: PetscBool isascii, isdraw;
299: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
300: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw);
301: PetscViewerPushFormat(viewer, format);
302: if (isascii) {
303: PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
304: PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm);
305: PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
306: } else if (isdraw) {
307: if (format == PETSC_VIEWER_DRAW_LG) {
308: PetscDrawLG lg = (PetscDrawLG)vf->lg;
309: PetscReal x, y;
312: if (!its) PetscDrawLGReset(lg);
313: x = (PetscReal)its;
314: if (fgnorm > 0.0) y = PetscLog10Real(fgnorm);
315: else y = -15.0;
316: PetscDrawLGAddPoint(lg, &x, &y);
317: if (its <= 20 || !(its % 5) || snes->reason) {
318: PetscDrawLGDraw(lg);
319: PetscDrawLGSave(lg);
320: }
321: }
322: }
323: PetscViewerPopFormat(viewer);
324: return 0;
325: }
327: /*@C
328: SNESMonitorScaling - Monitors the largest value in each row of the Jacobian.
330: Collective
332: Input Parameters:
333: + snes - the `SNES` context
334: . its - iteration number
335: . fgnorm - 2-norm of residual
336: - vf - viewer and format structure
338: Notes:
339: This routine prints the largest value in each row of the Jacobian
341: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
342: to be used during the `SNES` solve.
344: Level: intermediate
346: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `SNESMonitorJacUpdateSpectrum()`
347: @*/
348: PetscErrorCode SNESMonitorScaling(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
349: {
350: PetscViewer viewer = vf->viewer;
351: KSP ksp;
352: Mat J;
353: Vec v;
356: SNESGetKSP(snes, &ksp);
357: KSPGetOperators(ksp, &J, NULL);
358: MatCreateVecs(J, &v, NULL);
359: MatGetRowMaxAbs(J, v, NULL);
360: PetscViewerPushFormat(viewer, vf->format);
361: PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
362: PetscViewerASCIIPrintf(viewer, "SNES Jacobian maximum row entries\n");
363: VecView(v, viewer);
364: PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
365: PetscViewerPopFormat(viewer);
366: VecDestroy(&v);
367: return 0;
368: }
370: /*@C
371: SNESMonitorJacUpdateSpectrum - Monitors the spectrun of the change in the Jacobian from the last Jacobian evaluation
373: Collective
375: Input Parameters:
376: + snes - the `SNES` context
377: . its - iteration number
378: . fgnorm - 2-norm of residual
379: - vf - viewer and format structure
381: Option Database Key:
382: . -snes_monitor_jacupdate_spectrum - activates this monitor
384: Notes:
385: This routine prints the eigenvalues of the difference in the Jacobians
387: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
388: to be used during the `SNES` solve.
390: Level: intermediate
392: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`
393: @*/
394: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes, PetscInt it, PetscReal fnorm, PetscViewerAndFormat *vf)
395: {
396: Vec X;
397: Mat J, dJ, dJdense;
398: PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
399: PetscInt n;
400: PetscBLASInt nb = 0, lwork;
401: PetscReal *eigr, *eigi;
402: PetscScalar *work;
403: PetscScalar *a;
405: if (it == 0) return 0;
406: /* create the difference between the current update and the current Jacobian */
407: SNESGetSolution(snes, &X);
408: SNESGetJacobian(snes, NULL, &J, &func, NULL);
409: MatDuplicate(J, MAT_COPY_VALUES, &dJ);
410: SNESComputeJacobian(snes, X, dJ, dJ);
411: MatAXPY(dJ, -1.0, J, SAME_NONZERO_PATTERN);
413: /* compute the spectrum directly */
414: MatConvert(dJ, MATSEQDENSE, MAT_INITIAL_MATRIX, &dJdense);
415: MatGetSize(dJ, &n, NULL);
416: PetscBLASIntCast(n, &nb);
417: lwork = 3 * nb;
418: PetscMalloc1(n, &eigr);
419: PetscMalloc1(n, &eigi);
420: PetscMalloc1(lwork, &work);
421: MatDenseGetArray(dJdense, &a);
422: #if !defined(PETSC_USE_COMPLEX)
423: {
424: PetscBLASInt lierr;
425: PetscInt i;
426: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
427: PetscCallBLAS("LAPACKgeev", LAPACKgeev_("N", "N", &nb, a, &nb, eigr, eigi, NULL, &nb, NULL, &nb, work, &lwork, &lierr));
429: PetscFPTrapPop();
430: PetscPrintf(PetscObjectComm((PetscObject)snes), "Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n", it, it - 1);
431: for (i = 0; i < n; i++) PetscPrintf(PetscObjectComm((PetscObject)snes), "%5" PetscInt_FMT ": %20.5g + %20.5gi\n", i, (double)eigr[i], (double)eigi[i]);
432: }
433: MatDenseRestoreArray(dJdense, &a);
434: MatDestroy(&dJ);
435: MatDestroy(&dJdense);
436: PetscFree(eigr);
437: PetscFree(eigi);
438: PetscFree(work);
439: return 0;
440: #else
441: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded for complex");
442: #endif
443: }
445: PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
447: PetscErrorCode SNESMonitorRange_Private(SNES snes, PetscInt it, PetscReal *per)
448: {
449: Vec resid;
450: PetscReal rmax, pwork;
451: PetscInt i, n, N;
452: PetscScalar *r;
454: SNESGetFunction(snes, &resid, NULL, NULL);
455: VecNorm(resid, NORM_INFINITY, &rmax);
456: VecGetLocalSize(resid, &n);
457: VecGetSize(resid, &N);
458: VecGetArray(resid, &r);
459: pwork = 0.0;
460: for (i = 0; i < n; i++) pwork += (PetscAbsScalar(r[i]) > .20 * rmax);
461: MPIU_Allreduce(&pwork, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)snes));
462: VecRestoreArray(resid, &r);
463: *per = *per / N;
464: return 0;
465: }
467: /*@C
468: SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum entry in the residual
470: Collective
472: Input Parameters:
473: + snes - iterative context
474: . it - iteration number
475: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
476: - dummy - unused monitor context
478: Options Database Key:
479: . -snes_monitor_range - Activates `SNESMonitorRange()`
481: Note:
482: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
483: to be used during the `SNES` solve.
485: Level: intermediate
487: .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()`, `SNESMonitorScaling()`
488: @*/
489: PetscErrorCode SNESMonitorRange(SNES snes, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf)
490: {
491: PetscReal perc, rel;
492: PetscViewer viewer = vf->viewer;
493: /* should be in a MonitorRangeContext */
494: static PetscReal prev;
497: if (!it) prev = rnorm;
498: SNESMonitorRange_Private(snes, it, &perc);
500: rel = (prev - rnorm) / prev;
501: prev = rnorm;
502: PetscViewerPushFormat(viewer, vf->format);
503: PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
504: 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.0 * perc), (double)rel, (double)(rel / perc));
505: PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
506: PetscViewerPopFormat(viewer);
507: return 0;
508: }
510: /*@C
511: SNESMonitorRatio - Monitors progress of the `SNES` solvers by printing the ratio
512: of residual norm at each iteration to the previous.
514: Collective
516: Input Parameters:
517: + snes - the `SNES` context
518: . its - iteration number
519: . fgnorm - 2-norm of residual (or gradient)
520: - dummy - context of monitor
522: Option Database Key:
523: . -snes_monitor_ratio - activate this monitor
525: Level: intermediate
527: Notes:
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: Be sure to call `SNESMonitorRationSetUp()` before using this monitor.
533: .seealso: `SNESMonitorRationSetUp()`, `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`
534: @*/
535: PetscErrorCode SNESMonitorRatio(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
536: {
537: PetscInt len;
538: PetscReal *history;
539: PetscViewer viewer = vf->viewer;
541: SNESGetConvergenceHistory(snes, &history, NULL, &len);
542: PetscViewerPushFormat(viewer, vf->format);
543: PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
544: if (!its || !history || its > len) {
545: PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm);
546: } else {
547: PetscReal ratio = fgnorm / history[its - 1];
548: PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e \n", its, (double)fgnorm, (double)ratio);
549: }
550: PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
551: PetscViewerPopFormat(viewer);
552: return 0;
553: }
555: /*@C
556: SNESMonitorRatioSetUp - Insures the `SNES` object is saving its history since this monitor needs access to it
558: Collective
560: Input Parameters:
561: + snes - the `SNES` context
562: - viewer - the `PetscViewer` object (ignored)
564: Level: intermediate
566: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()`
567: @*/
568: PetscErrorCode SNESMonitorRatioSetUp(SNES snes, PetscViewerAndFormat *vf)
569: {
570: PetscReal *history;
572: SNESGetConvergenceHistory(snes, &history, NULL, NULL);
573: if (!history) SNESSetConvergenceHistory(snes, NULL, NULL, 100, PETSC_TRUE);
574: return 0;
575: }
577: /*
578: Default (short) SNES Monitor, same as SNESMonitorDefault() except
579: it prints fewer digits of the residual as the residual gets smaller.
580: This is because the later digits are meaningless and are often
581: different on different machines; by using this routine different
582: machines will usually generate the same output.
584: Deprecated: Intentionally has no manual page
585: */
586: PetscErrorCode SNESMonitorDefaultShort(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
587: {
588: PetscViewer viewer = vf->viewer;
591: PetscViewerPushFormat(viewer, vf->format);
592: PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
593: if (fgnorm > 1.e-9) {
594: PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %g \n", its, (double)fgnorm);
595: } else if (fgnorm > 1.e-11) {
596: PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %5.3e \n", its, (double)fgnorm);
597: } else {
598: PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm < 1.e-11\n", its);
599: }
600: PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
601: PetscViewerPopFormat(viewer);
602: return 0;
603: }
605: /*@C
606: SNESMonitorDefaultField - Monitors progress of the `SNES` solvers, separated into fields.
608: Collective
610: Input Parameters:
611: + snes - the `SNES` context
612: . its - iteration number
613: . fgnorm - 2-norm of residual
614: - ctx - the PetscViewer
616: Option Database Key:
617: . -snes_monitor_field - activate this monitor
619: Notes:
620: This routine uses the `DM` attached to the residual vector to define the fields.
622: This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
623: to be used during the `SNES` solve.
625: Level: intermediate
627: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`
628: @*/
629: PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
630: {
631: PetscViewer viewer = vf->viewer;
632: Vec r;
633: DM dm;
634: PetscReal res[256];
635: PetscInt tablevel;
638: SNESGetFunction(snes, &r, NULL, NULL);
639: VecGetDM(r, &dm);
640: if (!dm) SNESMonitorDefault(snes, its, fgnorm, vf);
641: else {
642: PetscSection s, gs;
643: PetscInt Nf, f;
645: DMGetLocalSection(dm, &s);
646: DMGetGlobalSection(dm, &gs);
647: if (!s || !gs) SNESMonitorDefault(snes, its, fgnorm, vf);
648: PetscSectionGetNumFields(s, &Nf);
650: PetscSectionVecNorm(s, gs, r, NORM_2, res);
651: PetscObjectGetTabLevel((PetscObject)snes, &tablevel);
652: PetscViewerPushFormat(viewer, vf->format);
653: PetscViewerASCIIAddTab(viewer, tablevel);
654: PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double)fgnorm);
655: for (f = 0; f < Nf; ++f) {
656: if (f) PetscViewerASCIIPrintf(viewer, ", ");
657: PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f]);
658: }
659: PetscViewerASCIIPrintf(viewer, "] \n");
660: PetscViewerASCIISubtractTab(viewer, tablevel);
661: PetscViewerPopFormat(viewer);
662: }
663: return 0;
664: }
666: /*@C
667: SNESConvergedDefault - Default onvergence test of the solvers for
668: systems of nonlinear equations.
670: Collective
672: Input Parameters:
673: + snes - the `SNES` context
674: . it - the iteration (0 indicates before any Newton steps)
675: . xnorm - 2-norm of current iterate
676: . snorm - 2-norm of current step
677: . fnorm - 2-norm of function at current iterate
678: - dummy - unused context
680: Output Parameter:
681: . reason - one of
682: .vb
683: SNES_CONVERGED_FNORM_ABS - (fnorm < abstol),
684: SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm),
685: SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0),
686: SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf),
687: SNES_DIVERGED_FNORM_NAN - (fnorm == NaN),
688: SNES_CONVERGED_ITERATING - (otherwise),
689: SNES_DIVERGED_DTOL - (fnorm > divtol*snes->fnorm0)
690: .ve
692: where
693: + maxf - maximum number of function evaluations, set with `SNESSetTolerances()`
694: . nfct - number of function evaluations,
695: . abstol - absolute function norm tolerance, set with `SNESSetTolerances()`
696: . rtol - relative function norm tolerance, set with `SNESSetTolerances()`
697: . divtol - divergence tolerance, set with `SNESSetDivergenceTolerance()`
698: - fnorm0 - 2-norm of the function at the initial solution (initial guess; zeroth iteration)
700: Options Database Keys:
701: + -snes_convergence_test default - see `SNESSetFromOptions()`
702: . -snes_stol - convergence tolerance in terms of the norm of the change in the solution between steps
703: . -snes_atol <abstol> - absolute tolerance of residual norm
704: . -snes_rtol <rtol> - relative decrease in tolerance norm from the initial 2-norm of the solution
705: . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
706: . -snes_max_funcs <max_funcs> - maximum number of function evaluations
707: . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
708: - -snes_max_linear_solve_fail - number of linear solver failures before `SNESSolve()` stops
710: Level: intermediate
712: .seealso: `SNES`, `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()`
713: @*/
714: PetscErrorCode SNESConvergedDefault(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy)
715: {
719: *reason = SNES_CONVERGED_ITERATING;
720: if (!it) {
721: /* set parameter for default relative tolerance convergence test */
722: snes->ttol = fnorm * snes->rtol;
723: snes->rnorm0 = fnorm;
724: }
725: if (PetscIsInfOrNanReal(fnorm)) {
726: PetscInfo(snes, "Failed to converged, function norm is NaN\n");
727: *reason = SNES_DIVERGED_FNORM_NAN;
728: } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) {
729: PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e\n", (double)fnorm, (double)snes->abstol);
730: *reason = SNES_CONVERGED_FNORM_ABS;
731: } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) {
732: PetscInfo(snes, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", snes->nfuncs, snes->max_funcs);
733: *reason = SNES_DIVERGED_FUNCTION_COUNT;
734: }
736: if (it && !*reason) {
737: if (fnorm <= snes->ttol) {
738: PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e (relative tolerance)\n", (double)fnorm, (double)snes->ttol);
739: *reason = SNES_CONVERGED_FNORM_RELATIVE;
740: } else if (snorm < snes->stol * xnorm) {
741: PetscInfo(snes, "Converged due to small update length: %14.12e < %14.12e * %14.12e\n", (double)snorm, (double)snes->stol, (double)xnorm);
742: *reason = SNES_CONVERGED_SNORM_RELATIVE;
743: } else if (snes->divtol > 0 && (fnorm > snes->divtol * snes->rnorm0)) {
744: PetscInfo(snes, "Diverged due to increase in function norm: %14.12e > %14.12e * %14.12e\n", (double)fnorm, (double)snes->divtol, (double)snes->rnorm0);
745: *reason = SNES_DIVERGED_DTOL;
746: }
747: }
748: return 0;
749: }
751: /*@C
752: SNESConvergedSkip - Convergence test for `SNES` that NEVER returns as
753: converged, UNLESS the maximum number of iteration have been reached.
755: Logically Collective
757: Input Parameters:
758: + snes - the `SNES` context
759: . it - the iteration (0 indicates before any Newton steps)
760: . xnorm - 2-norm of current iterate
761: . snorm - 2-norm of current step
762: . fnorm - 2-norm of function at current iterate
763: - dummy - unused context
765: Output Parameter:
766: . reason - `SNES_CONVERGED_ITERATING`, `SNES_CONVERGED_ITS`, or `SNES_DIVERGED_FNORM_NAN`
768: Options Database Key:
769: . -snes_convergence_test skip - see `SNESSetFromOptions()`
771: Level: advanced
773: .seealso: `SNES`, `SNESSolve()`, `SNESConvergedDefault()`, `SNESSetConvergenceTest()`
774: @*/
775: PetscErrorCode SNESConvergedSkip(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy)
776: {
780: *reason = SNES_CONVERGED_ITERATING;
782: if (fnorm != fnorm) {
783: PetscInfo(snes, "Failed to converged, function norm is NaN\n");
784: *reason = SNES_DIVERGED_FNORM_NAN;
785: } else if (it == snes->max_its) {
786: *reason = SNES_CONVERGED_ITS;
787: }
788: return 0;
789: }
791: /*@C
792: SNESSetWorkVecs - Gets a number of work vectors to be used internally by `SNES` solvers
794: Input Parameters:
795: + snes - the `SNES` context
796: - nw - number of work vectors to allocate
798: Level: developer
800: @*/
801: PetscErrorCode SNESSetWorkVecs(SNES snes, PetscInt nw)
802: {
803: DM dm;
804: Vec v;
806: if (snes->work) VecDestroyVecs(snes->nwork, &snes->work);
807: snes->nwork = nw;
809: SNESGetDM(snes, &dm);
810: DMGetGlobalVector(dm, &v);
811: VecDuplicateVecs(v, snes->nwork, &snes->work);
812: DMRestoreGlobalVector(dm, &v);
813: return 0;
814: }