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