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