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