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