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