xref: /petsc/src/snes/interface/snesut.c (revision fff3f5fae336d1caaec33911beb15ba4efbb662b)
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 -  dummy -  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: [](chapter_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 -  dummy -  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: [](chapter_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 -  dummy - 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: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`, `SNESMonitor()`, `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: [](chapter_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: [](chapter_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: [](chapter_snes), `KSP`, `SNES`, `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: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorFunction()`, `SNESMonitorSolution()`, `SNESMonitorResidual()`,
296           `SNESMonitorSolutionUpdate()`, `SNESMonitorDefault()`, `SNESMonitorScaling()`, `SNESMonitorRange()`, `SNESMonitorRatio()`,
297           `SNESMonitorDefaultField()`
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: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `SNESMonitorJacUpdateSpectrum()`
375 @*/
376 PetscErrorCode SNESMonitorScaling(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
377 {
378   PetscViewer viewer = vf->viewer;
379   KSP         ksp;
380   Mat         J;
381   Vec         v;
382 
383   PetscFunctionBegin;
384   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4);
385   PetscCall(SNESGetKSP(snes, &ksp));
386   PetscCall(KSPGetOperators(ksp, &J, NULL));
387   PetscCall(MatCreateVecs(J, &v, NULL));
388   PetscCall(MatGetRowMaxAbs(J, v, NULL));
389   PetscCall(PetscViewerPushFormat(viewer, vf->format));
390   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
391   PetscCall(PetscViewerASCIIPrintf(viewer, "SNES Jacobian maximum row entries\n"));
392   PetscCall(VecView(v, viewer));
393   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
394   PetscCall(PetscViewerPopFormat(viewer));
395   PetscCall(VecDestroy(&v));
396   PetscFunctionReturn(PETSC_SUCCESS);
397 }
398 
399 /*@C
400    SNESMonitorJacUpdateSpectrum - Monitors the spectrun of the change in the Jacobian from the last Jacobian evaluation
401 
402    Collective
403 
404    Input Parameters:
405 +  snes - the `SNES` context
406 .  its - iteration number
407 .  fgnorm - 2-norm of residual
408 -  vf - viewer and format structure
409 
410    Option Database Key:
411 .  -snes_monitor_jacupdate_spectrum - activates this monitor
412 
413    Level: intermediate
414 
415    Notes:
416    This routine prints the eigenvalues of the difference in the Jacobians
417 
418    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
419    to be used during the `SNES` solve.
420 
421 .seealso: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`
422 @*/
423 PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes, PetscInt it, PetscReal fnorm, PetscViewerAndFormat *vf)
424 {
425   Vec X;
426   Mat J, dJ, dJdense;
427   PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
428   PetscInt     n;
429   PetscBLASInt nb = 0, lwork;
430   PetscReal   *eigr, *eigi;
431   PetscScalar *work;
432   PetscScalar *a;
433 
434   PetscFunctionBegin;
435   if (it == 0) PetscFunctionReturn(PETSC_SUCCESS);
436   /* create the difference between the current update and the current Jacobian */
437   PetscCall(SNESGetSolution(snes, &X));
438   PetscCall(SNESGetJacobian(snes, NULL, &J, &func, NULL));
439   PetscCall(MatDuplicate(J, MAT_COPY_VALUES, &dJ));
440   PetscCall(SNESComputeJacobian(snes, X, dJ, dJ));
441   PetscCall(MatAXPY(dJ, -1.0, J, SAME_NONZERO_PATTERN));
442 
443   /* compute the spectrum directly */
444   PetscCall(MatConvert(dJ, MATSEQDENSE, MAT_INITIAL_MATRIX, &dJdense));
445   PetscCall(MatGetSize(dJ, &n, NULL));
446   PetscCall(PetscBLASIntCast(n, &nb));
447   lwork = 3 * nb;
448   PetscCall(PetscMalloc1(n, &eigr));
449   PetscCall(PetscMalloc1(n, &eigi));
450   PetscCall(PetscMalloc1(lwork, &work));
451   PetscCall(MatDenseGetArray(dJdense, &a));
452 #if !defined(PETSC_USE_COMPLEX)
453   {
454     PetscBLASInt lierr;
455     PetscInt     i;
456     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
457     PetscCallBLAS("LAPACKgeev", LAPACKgeev_("N", "N", &nb, a, &nb, eigr, eigi, NULL, &nb, NULL, &nb, work, &lwork, &lierr));
458     PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "geev() error %" PetscBLASInt_FMT, lierr);
459     PetscCall(PetscFPTrapPop());
460     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n", it, it - 1));
461     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]));
462   }
463   PetscCall(MatDenseRestoreArray(dJdense, &a));
464   PetscCall(MatDestroy(&dJ));
465   PetscCall(MatDestroy(&dJdense));
466   PetscCall(PetscFree(eigr));
467   PetscCall(PetscFree(eigi));
468   PetscCall(PetscFree(work));
469   PetscFunctionReturn(PETSC_SUCCESS);
470 #else
471   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded for complex");
472 #endif
473 }
474 
475 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
476 
477 PetscErrorCode SNESMonitorRange_Private(SNES snes, PetscInt it, PetscReal *per)
478 {
479   Vec          resid;
480   PetscReal    rmax, pwork;
481   PetscInt     i, n, N;
482   PetscScalar *r;
483 
484   PetscFunctionBegin;
485   PetscCall(SNESGetFunction(snes, &resid, NULL, NULL));
486   PetscCall(VecNorm(resid, NORM_INFINITY, &rmax));
487   PetscCall(VecGetLocalSize(resid, &n));
488   PetscCall(VecGetSize(resid, &N));
489   PetscCall(VecGetArray(resid, &r));
490   pwork = 0.0;
491   for (i = 0; i < n; i++) pwork += (PetscAbsScalar(r[i]) > .20 * rmax);
492   PetscCall(MPIU_Allreduce(&pwork, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)snes)));
493   PetscCall(VecRestoreArray(resid, &r));
494   *per = *per / N;
495   PetscFunctionReturn(PETSC_SUCCESS);
496 }
497 
498 /*@C
499    SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum entry in the residual
500 
501    Collective
502 
503    Input Parameters:
504 +  snes   - iterative context
505 .  it    - iteration number
506 .  rnorm - 2-norm (preconditioned) residual value (may be estimated).
507 -  dummy - unused monitor context
508 
509    Options Database Key:
510 .  -snes_monitor_range - Activates `SNESMonitorRange()`
511 
512    Level: intermediate
513 
514    Note:
515    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
516    to be used during the `SNES` solve.
517 
518 .seealso: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()`, `SNESMonitorScaling()`
519 @*/
520 PetscErrorCode SNESMonitorRange(SNES snes, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf)
521 {
522   PetscReal   perc, rel;
523   PetscViewer viewer = vf->viewer;
524   /* should be in a MonitorRangeContext */
525   static PetscReal prev;
526 
527   PetscFunctionBegin;
528   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4);
529   if (!it) prev = rnorm;
530   PetscCall(SNESMonitorRange_Private(snes, it, &perc));
531 
532   rel  = (prev - rnorm) / prev;
533   prev = rnorm;
534   PetscCall(PetscViewerPushFormat(viewer, vf->format));
535   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
536   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)));
537   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
538   PetscCall(PetscViewerPopFormat(viewer));
539   PetscFunctionReturn(PETSC_SUCCESS);
540 }
541 
542 /*@C
543    SNESMonitorRatio - Monitors progress of the `SNES` solvers by printing the ratio
544    of residual norm at each iteration to the previous.
545 
546    Collective
547 
548    Input Parameters:
549 +  snes - the `SNES` context
550 .  its - iteration number
551 .  fgnorm - 2-norm of residual (or gradient)
552 -  dummy -  context of monitor
553 
554    Option Database Key:
555 .  -snes_monitor_ratio - activate this monitor
556 
557    Level: intermediate
558 
559    Notes:
560    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
561    to be used during the `SNES` solve.
562 
563    Be sure to call `SNESMonitorRationSetUp()` before using this monitor.
564 
565 .seealso: [](chapter_snes), `SNESMonitorRationSetUp()`, `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`
566 @*/
567 PetscErrorCode SNESMonitorRatio(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
568 {
569   PetscInt    len;
570   PetscReal  *history;
571   PetscViewer viewer = vf->viewer;
572 
573   PetscFunctionBegin;
574   PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, &len));
575   PetscCall(PetscViewerPushFormat(viewer, vf->format));
576   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
577   if (!its || !history || its > len) {
578     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm));
579   } else {
580     PetscReal ratio = fgnorm / history[its - 1];
581     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e \n", its, (double)fgnorm, (double)ratio));
582   }
583   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
584   PetscCall(PetscViewerPopFormat(viewer));
585   PetscFunctionReturn(PETSC_SUCCESS);
586 }
587 
588 /*@C
589    SNESMonitorRatioSetUp - Insures the `SNES` object is saving its history since this monitor needs access to it
590 
591    Collective
592 
593    Input Parameters:
594 +   snes - the `SNES` context
595 -   viewer - the `PetscViewer` object (ignored)
596 
597    Level: intermediate
598 
599 .seealso: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()`
600 @*/
601 PetscErrorCode SNESMonitorRatioSetUp(SNES snes, PetscViewerAndFormat *vf)
602 {
603   PetscReal *history;
604 
605   PetscFunctionBegin;
606   PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, NULL));
607   if (!history) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, 100, PETSC_TRUE));
608   PetscFunctionReturn(PETSC_SUCCESS);
609 }
610 
611 /*
612      Default (short) SNES Monitor, same as SNESMonitorDefault() except
613   it prints fewer digits of the residual as the residual gets smaller.
614   This is because the later digits are meaningless and are often
615   different on different machines; by using this routine different
616   machines will usually generate the same output.
617 
618   Deprecated: Intentionally has no manual page
619 */
620 PetscErrorCode SNESMonitorDefaultShort(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
621 {
622   PetscViewer viewer = vf->viewer;
623 
624   PetscFunctionBegin;
625   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4);
626   PetscCall(PetscViewerPushFormat(viewer, vf->format));
627   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
628   if (fgnorm > 1.e-9) {
629     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %g \n", its, (double)fgnorm));
630   } else if (fgnorm > 1.e-11) {
631     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %5.3e \n", its, (double)fgnorm));
632   } else {
633     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm < 1.e-11\n", its));
634   }
635   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
636   PetscCall(PetscViewerPopFormat(viewer));
637   PetscFunctionReturn(PETSC_SUCCESS);
638 }
639 
640 /*@C
641   SNESMonitorDefaultField - Monitors progress of the `SNES` solvers, separated into fields.
642 
643   Collective
644 
645   Input Parameters:
646 + snes   - the `SNES` context
647 . its    - iteration number
648 . fgnorm - 2-norm of residual
649 - ctx    - the PetscViewer
650 
651    Option Database Key:
652 .  -snes_monitor_field - activate this monitor
653 
654   Level: intermediate
655 
656   Notes:
657   This routine uses the `DM` attached to the residual vector to define the fields.
658 
659   This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
660   to be used during the `SNES` solve.
661 
662 .seealso: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`
663 @*/
664 PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
665 {
666   PetscViewer viewer = vf->viewer;
667   Vec         r;
668   DM          dm;
669   PetscReal   res[256];
670   PetscInt    tablevel;
671 
672   PetscFunctionBegin;
673   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4);
674   PetscCall(SNESGetFunction(snes, &r, NULL, NULL));
675   PetscCall(VecGetDM(r, &dm));
676   if (!dm) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf));
677   else {
678     PetscSection s, gs;
679     PetscInt     Nf, f;
680 
681     PetscCall(DMGetLocalSection(dm, &s));
682     PetscCall(DMGetGlobalSection(dm, &gs));
683     if (!s || !gs) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf));
684     PetscCall(PetscSectionGetNumFields(s, &Nf));
685     PetscCheck(Nf <= 256, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Do not support %" PetscInt_FMT " fields > 256", Nf);
686     PetscCall(PetscSectionVecNorm(s, gs, r, NORM_2, res));
687     PetscCall(PetscObjectGetTabLevel((PetscObject)snes, &tablevel));
688     PetscCall(PetscViewerPushFormat(viewer, vf->format));
689     PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
690     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double)fgnorm));
691     for (f = 0; f < Nf; ++f) {
692       if (f) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
693       PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f]));
694     }
695     PetscCall(PetscViewerASCIIPrintf(viewer, "] \n"));
696     PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
697     PetscCall(PetscViewerPopFormat(viewer));
698   }
699   PetscFunctionReturn(PETSC_SUCCESS);
700 }
701 
702 /*@C
703    SNESConvergedDefault - Default onvergence test of the solvers for
704    systems of nonlinear equations.
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  - one of
718 .vb
719    SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
720    SNES_CONVERGED_SNORM_RELATIVE  - (snorm < stol*xnorm),
721    SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
722    SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
723    SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
724    SNES_CONVERGED_ITERATING       - (otherwise),
725    SNES_DIVERGED_DTOL             - (fnorm > divtol*snes->fnorm0)
726 .ve
727 
728    where
729 +    maxf - maximum number of function evaluations,  set with `SNESSetTolerances()`
730 .    nfct - number of function evaluations,
731 .    abstol - absolute function norm tolerance, set with `SNESSetTolerances()`
732 .    rtol - relative function norm tolerance, set with `SNESSetTolerances()`
733 .    divtol - divergence tolerance, set with `SNESSetDivergenceTolerance()`
734 -    fnorm0 - 2-norm of the function at the initial solution (initial guess; zeroth iteration)
735 
736   Options Database Keys:
737 +  -snes_convergence_test default - see `SNESSetFromOptions()`
738 .  -snes_stol - convergence tolerance in terms of the norm  of the change in the solution between steps
739 .  -snes_atol <abstol> - absolute tolerance of residual norm
740 .  -snes_rtol <rtol> - relative decrease in tolerance norm from the initial 2-norm of the solution
741 .  -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
742 .  -snes_max_funcs <max_funcs> - maximum number of function evaluations
743 .  -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
744 -  -snes_max_linear_solve_fail - number of linear solver failures before `SNESSolve()` stops
745 
746    Level: intermediate
747 
748 .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()`
749 @*/
750 PetscErrorCode SNESConvergedDefault(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy)
751 {
752   PetscFunctionBegin;
753   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
754   PetscValidPointer(reason, 6);
755 
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_FNORM_NAN;
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   }
772 
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 > 0 && (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 }
787 
788 /*@C
789    SNESConvergedSkip - Convergence test for `SNES` that NEVER returns as
790    converged, UNLESS the maximum number of iteration have been reached.
791 
792    Logically Collective
793 
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 -  dummy - unused context
801 
802    Output Parameter:
803 .   reason  - `SNES_CONVERGED_ITERATING`, `SNES_CONVERGED_ITS`, or `SNES_DIVERGED_FNORM_NAN`
804 
805    Options Database Key:
806 .  -snes_convergence_test skip - see `SNESSetFromOptions()`
807 
808    Level: advanced
809 
810 .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESConvergedDefault()`, `SNESSetConvergenceTest()`
811 @*/
812 PetscErrorCode SNESConvergedSkip(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy)
813 {
814   PetscFunctionBegin;
815   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
816   PetscValidPointer(reason, 6);
817 
818   *reason = SNES_CONVERGED_ITERATING;
819 
820   if (fnorm != fnorm) {
821     PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n"));
822     *reason = SNES_DIVERGED_FNORM_NAN;
823   } else if (it == snes->max_its) {
824     *reason = SNES_CONVERGED_ITS;
825   }
826   PetscFunctionReturn(PETSC_SUCCESS);
827 }
828 
829 /*@C
830   SNESSetWorkVecs - Gets a number of work vectors to be used internally by `SNES` solvers
831 
832   Input Parameters:
833 + snes  - the `SNES` context
834 - nw - number of work vectors to allocate
835 
836   Level: developer
837 
838 .seealso: [](chapter_snes), `SNES`
839 @*/
840 PetscErrorCode SNESSetWorkVecs(SNES snes, PetscInt nw)
841 {
842   DM  dm;
843   Vec v;
844 
845   PetscFunctionBegin;
846   if (snes->work) PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
847   snes->nwork = nw;
848 
849   PetscCall(SNESGetDM(snes, &dm));
850   PetscCall(DMGetGlobalVector(dm, &v));
851   PetscCall(VecDuplicateVecs(v, snes->nwork, &snes->work));
852   PetscCall(DMRestoreGlobalVector(dm, &v));
853   PetscFunctionReturn(PETSC_SUCCESS);
854 }
855