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