xref: /petsc/src/snes/interface/snesut.c (revision 7c4f633dc6bb6149cca88d301ead35a99e103cbb) !
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,PetscSum_Op,((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 
200    Notes:
201    When using either ICC or ILU preconditioners in BlockSolve95
202    (via MATMPIROWBS matrix format), then use this monitor will
203    print both the residual norm associated with the original
204    (unscaled) matrix.
205 
206    Level: intermediate
207 
208 .keywords: SNES, default, monitor, residual
209 
210 .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate()
211 @*/
212 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy)
213 {
214   PetscErrorCode          ierr;
215   PetscReal               perc,rel;
216   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
217   /* should be in a MonitorRangeContext */
218   static PetscReal        prev;
219 
220   PetscFunctionBegin;
221   if (!it) prev = rnorm;
222   if (!dummy) {ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);}
223   ierr = SNESMonitorRange_Private(snes,it,&perc);CHKERRQ(ierr);
224 
225   rel  = (prev - rnorm)/prev;
226   prev = rnorm;
227   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);
228   if (!dummy) {ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr);}
229   PetscFunctionReturn(0);
230 }
231 
232 typedef struct {
233   PetscViewerASCIIMonitor viewer;
234   PetscReal               *history;
235 } SNESMonitorRatioContext;
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "SNESMonitorRatio"
239 /*@C
240    SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio
241    of residual norm at each iteration to the previous.
242 
243    Collective on SNES
244 
245    Input Parameters:
246 +  snes - the SNES context
247 .  its - iteration number
248 .  fgnorm - 2-norm of residual (or gradient)
249 -  dummy -  context of monitor
250 
251    Level: intermediate
252 
253 .keywords: SNES, nonlinear, monitor, norm
254 
255 .seealso: SNESMonitorSet(), SNESMonitorSolution()
256 @*/
257 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
258 {
259   PetscErrorCode          ierr;
260   PetscInt                len;
261   PetscReal               *history;
262   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy;
263 
264   PetscFunctionBegin;
265   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr);
266   if (!its || !history || its > len) {
267     ierr = PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr);
268   } else {
269     PetscReal ratio = fgnorm/history[its-1];
270     ierr = PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %G \n",its,fgnorm,ratio);CHKERRQ(ierr);
271   }
272   PetscFunctionReturn(0);
273 }
274 
275 /*
276    If the we set the history monitor space then we must destroy it
277 */
278 #undef __FUNCT__
279 #define __FUNCT__ "SNESMonitorRatioDestroy"
280 PetscErrorCode SNESMonitorRatioDestroy(void *ct)
281 {
282   PetscErrorCode          ierr;
283   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)ct;
284 
285   PetscFunctionBegin;
286   ierr = PetscFree(ctx->history);CHKERRQ(ierr);
287   ierr = PetscViewerASCIIMonitorDestroy(ctx->viewer);CHKERRQ(ierr);
288   ierr = PetscFree(ctx);CHKERRQ(ierr);
289   PetscFunctionReturn(0);
290 }
291 
292 #undef __FUNCT__
293 #define __FUNCT__ "SNESMonitorSetRatio"
294 /*@C
295    SNESMonitorSetRatio - Sets SNES to use a monitor that prints the
296    ratio of the function norm at each iteration.
297 
298    Collective on SNES
299 
300    Input Parameters:
301 +   snes - the SNES context
302 -   viewer - ASCII viewer to print output
303 
304    Level: intermediate
305 
306 .keywords: SNES, nonlinear, monitor, norm
307 
308 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
309 @*/
310 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSetRatio(SNES snes,PetscViewerASCIIMonitor viewer)
311 {
312   PetscErrorCode          ierr;
313   SNESMonitorRatioContext *ctx;
314   PetscReal               *history;
315 
316   PetscFunctionBegin;
317   if (!viewer) {
318     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
319     ierr = PetscObjectReference((PetscObject)viewer);CHKERRQ(ierr);
320   }
321   ierr = PetscNewLog(snes,SNESMonitorRatioContext,&ctx);
322   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
323   if (!history) {
324     ierr = PetscMalloc(100*sizeof(PetscReal),&ctx->history);CHKERRQ(ierr);
325     ierr = SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);CHKERRQ(ierr);
326   }
327   ctx->viewer = viewer;
328   ierr = SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);CHKERRQ(ierr);
329   PetscFunctionReturn(0);
330 }
331 
332 /* ---------------------------------------------------------------- */
333 #undef __FUNCT__
334 #define __FUNCT__ "SNESMonitorDefaultShort"
335 /*
336      Default (short) SNES Monitor, same as SNESMonitorDefault() except
337   it prints fewer digits of the residual as the residual gets smaller.
338   This is because the later digits are meaningless and are often
339   different on different machines; by using this routine different
340   machines will usually generate the same output.
341 */
342 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
343 {
344   PetscErrorCode          ierr;
345   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
346 
347   PetscFunctionBegin;
348   if (!dummy) {
349     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
350   }
351   if (fgnorm > 1.e-9) {
352     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);CHKERRQ(ierr);
353   } else if (fgnorm > 1.e-11){
354     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr);
355   } else {
356     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr);
357   }
358   if (!dummy) {
359     ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr);
360   }
361   PetscFunctionReturn(0);
362 }
363 /* ---------------------------------------------------------------- */
364 #undef __FUNCT__
365 #define __FUNCT__ "SNESDefaultConverged"
366 /*@C
367    SNESDefaultConverged - Convergence test of the solvers for
368    systems of nonlinear equations (default).
369 
370    Collective on SNES
371 
372    Input Parameters:
373 +  snes - the SNES context
374 .  it - the iteration (0 indicates before any Newton steps)
375 .  xnorm - 2-norm of current iterate
376 .  pnorm - 2-norm of current step
377 .  fnorm - 2-norm of function at current iterate
378 -  dummy - unused context
379 
380    Output Parameter:
381 .   reason  - one of
382 $  SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
383 $  SNES_CONVERGED_PNORM_RELATIVE  - (pnorm < xtol*xnorm),
384 $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
385 $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
386 $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
387 $  SNES_CONVERGED_ITERATING       - (otherwise),
388 
389    where
390 +    maxf - maximum number of function evaluations,
391             set with SNESSetTolerances()
392 .    nfct - number of function evaluations,
393 .    abstol - absolute function norm tolerance,
394             set with SNESSetTolerances()
395 -    rtol - relative function norm tolerance, set with SNESSetTolerances()
396 
397    Level: intermediate
398 
399 .keywords: SNES, nonlinear, default, converged, convergence
400 
401 .seealso: SNESSetConvergenceTest()
402 @*/
403 PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
404 {
405   PetscErrorCode ierr;
406 
407   PetscFunctionBegin;
408   PetscValidHeaderSpecific(snes,SNES_COOKIE,1);
409   PetscValidPointer(reason,6);
410 
411   *reason = SNES_CONVERGED_ITERATING;
412 
413   if (!it) {
414     /* set parameter for default relative tolerance convergence test */
415     snes->ttol = fnorm*snes->rtol;
416   }
417   if (fnorm != fnorm) {
418     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
419     *reason = SNES_DIVERGED_FNORM_NAN;
420   } else if (fnorm < snes->abstol) {
421     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
422     *reason = SNES_CONVERGED_FNORM_ABS;
423   } else if (snes->nfuncs >= snes->max_funcs) {
424     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
425     *reason = SNES_DIVERGED_FUNCTION_COUNT;
426   }
427 
428   if (it && !*reason) {
429     if (fnorm <= snes->ttol) {
430       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
431       *reason = SNES_CONVERGED_FNORM_RELATIVE;
432     } else if (pnorm < snes->xtol*xnorm) {
433       ierr = PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes->xtol,xnorm);CHKERRQ(ierr);
434       *reason = SNES_CONVERGED_PNORM_RELATIVE;
435     }
436   }
437   PetscFunctionReturn(0);
438 }
439 
440 #undef __FUNCT__
441 #define __FUNCT__ "SNESSkipConverged"
442 /*@C
443    SNESSkipConverged - Convergence test for SNES that NEVER returns as
444    converged, UNLESS the maximum number of iteration have been reached.
445 
446    Collective on SNES
447 
448    Input Parameters:
449 +  snes - the SNES context
450 .  it - the iteration (0 indicates before any Newton steps)
451 .  xnorm - 2-norm of current iterate
452 .  pnorm - 2-norm of current step
453 .  fnorm - 2-norm of function at current iterate
454 -  dummy - unused context
455 
456    Output Parameter:
457 .   reason  - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN
458 
459    Notes:
460    Convergence is then declared after a fixed number of iterations have been used.
461 
462    Level: advanced
463 
464 .keywords: SNES, nonlinear, skip, converged, convergence
465 
466 .seealso: SNESSetConvergenceTest()
467 @*/
468 PetscErrorCode PETSCSNES_DLLEXPORT SNESSkipConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
469 {
470   PetscErrorCode ierr;
471 
472   PetscFunctionBegin;
473   PetscValidHeaderSpecific(snes,SNES_COOKIE,1);
474   PetscValidPointer(reason,6);
475 
476   *reason = SNES_CONVERGED_ITERATING;
477 
478   if (fnorm != fnorm) {
479     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
480     *reason = SNES_DIVERGED_FNORM_NAN;
481   } else if(it == snes->max_its) {
482     *reason = SNES_CONVERGED_ITS;
483   }
484   PetscFunctionReturn(0);
485 }
486 
487