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