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