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