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