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