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