xref: /petsc/src/snes/interface/snesut.c (revision f3fe499b4cc4d64bf04aa4f5e4963dcc4eb56541)
1 #define PETSCSNES_DLL
2 
3 #include "private/snesimpl.h"       /*I   "petscsnes.h"   I*/
4 
5 #undef __FUNCT__
6 #define __FUNCT__ "SNESMonitorSolution"
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 - either a viewer or PETSC_NULL
18 
19    Level: intermediate
20 
21 .keywords: SNES, nonlinear, vector, monitor, view
22 
23 .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
24 @*/
25 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSolution(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
26 {
27   PetscErrorCode ierr;
28   Vec            x;
29   PetscViewer    viewer = (PetscViewer) dummy;
30 
31   PetscFunctionBegin;
32   ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr);
33   if (!viewer) {
34     MPI_Comm comm;
35     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
36     viewer = PETSC_VIEWER_DRAW_(comm);
37   }
38   ierr = VecView(x,viewer);CHKERRQ(ierr);
39 
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 PETSC_NULL
56 
57    Level: intermediate
58 
59 .keywords: SNES, nonlinear, vector, monitor, view
60 
61 .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
62 @*/
63 PetscErrorCode PETSCSNES_DLLEXPORT 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 
78   PetscFunctionReturn(0);
79 }
80 
81 #undef __FUNCT__
82 #define __FUNCT__ "SNESMonitorSolutionUpdate"
83 /*@C
84    SNESMonitorSolutionUpdate - Monitors progress of the SNES solvers by calling
85    VecView() for the UPDATE to the solution at each iteration.
86 
87    Collective on SNES
88 
89    Input Parameters:
90 +  snes - the SNES context
91 .  its - iteration number
92 .  fgnorm - 2-norm of residual
93 -  dummy - either a viewer or PETSC_NULL
94 
95    Level: intermediate
96 
97 .keywords: SNES, nonlinear, vector, monitor, view
98 
99 .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
100 @*/
101 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSolutionUpdate(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
102 {
103   PetscErrorCode ierr;
104   Vec            x;
105   PetscViewer    viewer = (PetscViewer) dummy;
106 
107   PetscFunctionBegin;
108   ierr = SNESGetSolutionUpdate(snes,&x);CHKERRQ(ierr);
109   if (!viewer) {
110     MPI_Comm comm;
111     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
112     viewer = PETSC_VIEWER_DRAW_(comm);
113   }
114   ierr = VecView(x,viewer);CHKERRQ(ierr);
115 
116   PetscFunctionReturn(0);
117 }
118 
119 #undef __FUNCT__
120 #define __FUNCT__ "SNESMonitorDefault"
121 /*@C
122    SNESMonitorDefault - Monitors progress of the SNES solvers (default).
123 
124    Collective on SNES
125 
126    Input Parameters:
127 +  snes - the SNES context
128 .  its - iteration number
129 .  fgnorm - 2-norm of residual
130 -  dummy - unused context
131 
132    Notes:
133    This routine prints the residual norm at each iteration.
134 
135    Level: intermediate
136 
137 .keywords: SNES, nonlinear, default, monitor, norm
138 
139 .seealso: SNESMonitorSet(), SNESMonitorSolution()
140 @*/
141 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
142 {
143   PetscErrorCode          ierr;
144   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
145 
146   PetscFunctionBegin;
147   if (!dummy) {
148     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
149   }
150   ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr);
151   if (!dummy) {
152     ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr);
153   }
154   PetscFunctionReturn(0);
155 }
156 
157 #undef __FUNCT__
158 #define __FUNCT__ "SNESMonitorRange_Private"
159 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per)
160 {
161   PetscErrorCode          ierr;
162   Vec                     resid;
163   PetscReal               rmax,pwork;
164   PetscInt                i,n,N;
165   PetscScalar             *r;
166 
167   PetscFunctionBegin;
168   ierr = SNESGetFunction(snes,&resid,0,0);CHKERRQ(ierr);
169   ierr = VecNorm(resid,NORM_INFINITY,&rmax);CHKERRQ(ierr);
170   ierr = VecGetLocalSize(resid,&n);CHKERRQ(ierr);
171   ierr = VecGetSize(resid,&N);CHKERRQ(ierr);
172   ierr = VecGetArray(resid,&r);CHKERRQ(ierr);
173   pwork = 0.0;
174   for (i=0; i<n; i++) {
175     pwork += (PetscAbsScalar(r[i]) > .20*rmax);
176   }
177   ierr = MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
178   ierr = VecRestoreArray(resid,&r);CHKERRQ(ierr);
179   *per  = *per/N;
180   PetscFunctionReturn(0);
181 }
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "SNESMonitorRange"
185 /*@C
186    SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value.
187 
188    Collective on SNES
189 
190    Input Parameters:
191 +  snes   - iterative context
192 .  it    - iteration number
193 .  rnorm - 2-norm (preconditioned) residual value (may be estimated).
194 -  dummy - unused monitor context
195 
196    Options Database Key:
197 .  -snes_monitor_range - Activates SNESMonitorRange()
198 
199    Level: intermediate
200 
201 .keywords: SNES, default, monitor, residual
202 
203 .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate()
204 @*/
205 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy)
206 {
207   PetscErrorCode          ierr;
208   PetscReal               perc,rel;
209   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
210   /* should be in a MonitorRangeContext */
211   static PetscReal        prev;
212 
213   PetscFunctionBegin;
214   if (!it) prev = rnorm;
215   if (!dummy) {ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);}
216   ierr = SNESMonitorRange_Private(snes,it,&perc);CHKERRQ(ierr);
217 
218   rel  = (prev - rnorm)/prev;
219   prev = rnorm;
220   ierr = PetscViewerASCIIMonitorPrintf(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,rnorm,100.0*perc,rel,rel/perc);CHKERRQ(ierr);
221   if (!dummy) {ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr);}
222   PetscFunctionReturn(0);
223 }
224 
225 typedef struct {
226   PetscViewerASCIIMonitor viewer;
227   PetscReal               *history;
228 } SNESMonitorRatioContext;
229 
230 #undef __FUNCT__
231 #define __FUNCT__ "SNESMonitorRatio"
232 /*@C
233    SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio
234    of residual norm at each iteration to the previous.
235 
236    Collective on SNES
237 
238    Input Parameters:
239 +  snes - the SNES context
240 .  its - iteration number
241 .  fgnorm - 2-norm of residual (or gradient)
242 -  dummy -  context of monitor
243 
244    Level: intermediate
245 
246 .keywords: SNES, nonlinear, monitor, norm
247 
248 .seealso: SNESMonitorSet(), SNESMonitorSolution()
249 @*/
250 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
251 {
252   PetscErrorCode          ierr;
253   PetscInt                len;
254   PetscReal               *history;
255   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy;
256 
257   PetscFunctionBegin;
258   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr);
259   if (!its || !history || its > len) {
260     ierr = PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr);
261   } else {
262     PetscReal ratio = fgnorm/history[its-1];
263     ierr = PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %G \n",its,fgnorm,ratio);CHKERRQ(ierr);
264   }
265   PetscFunctionReturn(0);
266 }
267 
268 /*
269    If the we set the history monitor space then we must destroy it
270 */
271 #undef __FUNCT__
272 #define __FUNCT__ "SNESMonitorRatioDestroy"
273 PetscErrorCode SNESMonitorRatioDestroy(void *ct)
274 {
275   PetscErrorCode          ierr;
276   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)ct;
277 
278   PetscFunctionBegin;
279   ierr = PetscFree(ctx->history);CHKERRQ(ierr);
280   ierr = PetscViewerASCIIMonitorDestroy(ctx->viewer);CHKERRQ(ierr);
281   ierr = PetscFree(ctx);CHKERRQ(ierr);
282   PetscFunctionReturn(0);
283 }
284 
285 #undef __FUNCT__
286 #define __FUNCT__ "SNESMonitorSetRatio"
287 /*@C
288    SNESMonitorSetRatio - Sets SNES to use a monitor that prints the
289    ratio of the function norm at each iteration.
290 
291    Collective on SNES
292 
293    Input Parameters:
294 +   snes - the SNES context
295 -   viewer - ASCII viewer to print output
296 
297    Level: intermediate
298 
299 .keywords: SNES, nonlinear, monitor, norm
300 
301 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
302 @*/
303 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSetRatio(SNES snes,PetscViewerASCIIMonitor viewer)
304 {
305   PetscErrorCode          ierr;
306   SNESMonitorRatioContext *ctx;
307   PetscReal               *history;
308 
309   PetscFunctionBegin;
310   if (!viewer) {
311     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
312     ierr = PetscObjectReference((PetscObject)viewer);CHKERRQ(ierr);
313   }
314   ierr = PetscNewLog(snes,SNESMonitorRatioContext,&ctx);
315   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
316   if (!history) {
317     ierr = PetscMalloc(100*sizeof(PetscReal),&ctx->history);CHKERRQ(ierr);
318     ierr = SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);CHKERRQ(ierr);
319   }
320   ctx->viewer = viewer;
321   ierr = SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);CHKERRQ(ierr);
322   PetscFunctionReturn(0);
323 }
324 
325 /* ---------------------------------------------------------------- */
326 #undef __FUNCT__
327 #define __FUNCT__ "SNESMonitorDefaultShort"
328 /*
329      Default (short) SNES Monitor, same as SNESMonitorDefault() except
330   it prints fewer digits of the residual as the residual gets smaller.
331   This is because the later digits are meaningless and are often
332   different on different machines; by using this routine different
333   machines will usually generate the same output.
334 */
335 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
336 {
337   PetscErrorCode          ierr;
338   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
339 
340   PetscFunctionBegin;
341   if (!dummy) {
342     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
343   }
344   if (fgnorm > 1.e-9) {
345     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);CHKERRQ(ierr);
346   } else if (fgnorm > 1.e-11){
347     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr);
348   } else {
349     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr);
350   }
351   if (!dummy) {
352     ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr);
353   }
354   PetscFunctionReturn(0);
355 }
356 /* ---------------------------------------------------------------- */
357 #undef __FUNCT__
358 #define __FUNCT__ "SNESDefaultConverged"
359 /*@C
360    SNESDefaultConverged - Convergence test of the solvers for
361    systems of nonlinear equations (default).
362 
363    Collective on SNES
364 
365    Input Parameters:
366 +  snes - the SNES context
367 .  it - the iteration (0 indicates before any Newton steps)
368 .  xnorm - 2-norm of current iterate
369 .  pnorm - 2-norm of current step
370 .  fnorm - 2-norm of function at current iterate
371 -  dummy - unused context
372 
373    Output Parameter:
374 .   reason  - one of
375 $  SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
376 $  SNES_CONVERGED_PNORM_RELATIVE  - (pnorm < xtol*xnorm),
377 $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
378 $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
379 $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
380 $  SNES_CONVERGED_ITERATING       - (otherwise),
381 
382    where
383 +    maxf - maximum number of function evaluations,
384             set with SNESSetTolerances()
385 .    nfct - number of function evaluations,
386 .    abstol - absolute function norm tolerance,
387             set with SNESSetTolerances()
388 -    rtol - relative function norm tolerance, set with SNESSetTolerances()
389 
390    Level: intermediate
391 
392 .keywords: SNES, nonlinear, default, converged, convergence
393 
394 .seealso: SNESSetConvergenceTest()
395 @*/
396 PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
397 {
398   PetscErrorCode ierr;
399 
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
402   PetscValidPointer(reason,6);
403 
404   *reason = SNES_CONVERGED_ITERATING;
405 
406   if (!it) {
407     /* set parameter for default relative tolerance convergence test */
408     snes->ttol = fnorm*snes->rtol;
409   }
410   if (fnorm != fnorm) {
411     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
412     *reason = SNES_DIVERGED_FNORM_NAN;
413   } else if (fnorm < snes->abstol) {
414     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
415     *reason = SNES_CONVERGED_FNORM_ABS;
416   } else if (snes->nfuncs >= snes->max_funcs) {
417     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
418     *reason = SNES_DIVERGED_FUNCTION_COUNT;
419   }
420 
421   if (it && !*reason) {
422     if (fnorm <= snes->ttol) {
423       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
424       *reason = SNES_CONVERGED_FNORM_RELATIVE;
425     } else if (pnorm < snes->xtol*xnorm) {
426       ierr = PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes->xtol,xnorm);CHKERRQ(ierr);
427       *reason = SNES_CONVERGED_PNORM_RELATIVE;
428     }
429   }
430   PetscFunctionReturn(0);
431 }
432 
433 #undef __FUNCT__
434 #define __FUNCT__ "SNESSkipConverged"
435 /*@C
436    SNESSkipConverged - Convergence test for SNES that NEVER returns as
437    converged, UNLESS the maximum number of iteration have been reached.
438 
439    Logically Collective on SNES
440 
441    Input Parameters:
442 +  snes - the SNES context
443 .  it - the iteration (0 indicates before any Newton steps)
444 .  xnorm - 2-norm of current iterate
445 .  pnorm - 2-norm of current step
446 .  fnorm - 2-norm of function at current iterate
447 -  dummy - unused context
448 
449    Output Parameter:
450 .   reason  - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN
451 
452    Notes:
453    Convergence is then declared after a fixed number of iterations have been used.
454 
455    Level: advanced
456 
457 .keywords: SNES, nonlinear, skip, converged, convergence
458 
459 .seealso: SNESSetConvergenceTest()
460 @*/
461 PetscErrorCode PETSCSNES_DLLEXPORT SNESSkipConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
462 {
463   PetscErrorCode ierr;
464 
465   PetscFunctionBegin;
466   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
467   PetscValidPointer(reason,6);
468 
469   *reason = SNES_CONVERGED_ITERATING;
470 
471   if (fnorm != fnorm) {
472     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
473     *reason = SNES_DIVERGED_FNORM_NAN;
474   } else if(it == snes->max_its) {
475     *reason = SNES_CONVERGED_ITS;
476   }
477   PetscFunctionReturn(0);
478 }
479 
480