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