xref: /petsc/src/snes/interface/snesut.c (revision a58c3bc3391eee32bc3fd94ac7edeea38fe57aae)
1 #define PETSCSNES_DLL
2 
3 #include "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(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 typedef struct {
158   PetscViewerASCIIMonitor viewer;
159   PetscReal               *history;
160 } SNESMonitorRatioContext;
161 
162 #undef __FUNCT__
163 #define __FUNCT__ "SNESMonitorRatio"
164 /*@C
165    SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio
166    of residual norm at each iteration to the previous.
167 
168    Collective on SNES
169 
170    Input Parameters:
171 +  snes - the SNES context
172 .  its - iteration number
173 .  fgnorm - 2-norm of residual (or gradient)
174 -  dummy -  context of monitor
175 
176    Level: intermediate
177 
178 .keywords: SNES, nonlinear, monitor, norm
179 
180 .seealso: SNESMonitorSet(), SNESMonitorSolution()
181 @*/
182 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
183 {
184   PetscErrorCode          ierr;
185   PetscInt                len;
186   PetscReal               *history;
187   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy;
188 
189   PetscFunctionBegin;
190   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr);
191   if (!its || !history || its > len) {
192     ierr = PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr);
193   } else {
194     PetscReal ratio = fgnorm/history[its-1];
195     ierr = PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %G \n",its,fgnorm,ratio);CHKERRQ(ierr);
196   }
197   PetscFunctionReturn(0);
198 }
199 
200 /*
201    If the we set the history monitor space then we must destroy it
202 */
203 #undef __FUNCT__
204 #define __FUNCT__ "SNESMonitorRatioDestroy"
205 PetscErrorCode SNESMonitorRatioDestroy(void *ct)
206 {
207   PetscErrorCode          ierr;
208   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)ct;
209 
210   PetscFunctionBegin;
211   ierr = PetscFree(ctx->history);CHKERRQ(ierr);
212   ierr = PetscViewerASCIIMonitorDestroy(ctx->viewer);CHKERRQ(ierr);
213   ierr = PetscFree(ctx);CHKERRQ(ierr);
214   PetscFunctionReturn(0);
215 }
216 
217 #undef __FUNCT__
218 #define __FUNCT__ "SNESMonitorSetRatio"
219 /*@C
220    SNESMonitorSetRatio - Sets SNES to use a monitor that prints the
221    ratio of the function norm at each iteration.
222 
223    Collective on SNES
224 
225    Input Parameters:
226 +   snes - the SNES context
227 -   viewer - ASCII viewer to print output
228 
229    Level: intermediate
230 
231 .keywords: SNES, nonlinear, monitor, norm
232 
233 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
234 @*/
235 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSetRatio(SNES snes,PetscViewerASCIIMonitor viewer)
236 {
237   PetscErrorCode          ierr;
238   SNESMonitorRatioContext *ctx;
239   PetscReal               *history;
240 
241   PetscFunctionBegin;
242   if (!viewer) {
243     ierr = PetscViewerASCIIMonitorCreate(snes->comm,"stdout",0,&viewer);CHKERRQ(ierr);
244     ierr = PetscObjectReference((PetscObject)viewer);CHKERRQ(ierr);
245   }
246   ierr = PetscNew(SNESMonitorRatioContext,&ctx);
247   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
248   if (!history) {
249     ierr = PetscMalloc(100*sizeof(PetscReal),&ctx->history);CHKERRQ(ierr);
250     ierr = SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);CHKERRQ(ierr);
251   }
252   ctx->viewer = viewer;
253   ierr = SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);CHKERRQ(ierr);
254   PetscFunctionReturn(0);
255 }
256 
257 /* ---------------------------------------------------------------- */
258 #undef __FUNCT__
259 #define __FUNCT__ "SNESMonitorDefaultShort"
260 /*
261      Default (short) SNES Monitor, same as SNESMonitorDefault() except
262   it prints fewer digits of the residual as the residual gets smaller.
263   This is because the later digits are meaningless and are often
264   different on different machines; by using this routine different
265   machines will usually generate the same output.
266 */
267 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
268 {
269   PetscErrorCode          ierr;
270   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
271 
272   PetscFunctionBegin;
273   if (!dummy) {
274     ierr = PetscViewerASCIIMonitorCreate(snes->comm,"stdout",0,&viewer);CHKERRQ(ierr);
275   }
276   if (fgnorm > 1.e-9) {
277     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);CHKERRQ(ierr);
278   } else if (fgnorm > 1.e-11){
279     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr);
280   } else {
281     ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr);
282   }
283   if (!dummy) {
284     ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr);
285   }
286   PetscFunctionReturn(0);
287 }
288 /* ---------------------------------------------------------------- */
289 #undef __FUNCT__
290 #define __FUNCT__ "SNESDefaultConverged"
291 /*@C
292    SNESDefaultConverged - Convergence test of the solvers for
293    systems of nonlinear equations (default).
294 
295    Collective on SNES
296 
297    Input Parameters:
298 +  snes - the SNES context
299 .  it - the iteration (0 indicates before any Newton steps)
300 .  xnorm - 2-norm of current iterate
301 .  pnorm - 2-norm of current step
302 .  fnorm - 2-norm of function at current iterate
303 -  dummy - unused context
304 
305    Output Parameter:
306 .   reason  - one of
307 $  SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
308 $  SNES_CONVERGED_PNORM_RELATIVE  - (pnorm < xtol*xnorm),
309 $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
310 $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
311 $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
312 $  SNES_CONVERGED_ITERATING       - (otherwise),
313 
314    where
315 +    maxf - maximum number of function evaluations,
316             set with SNESSetTolerances()
317 .    nfct - number of function evaluations,
318 .    abstol - absolute function norm tolerance,
319             set with SNESSetTolerances()
320 -    rtol - relative function norm tolerance, set with SNESSetTolerances()
321 
322    Level: intermediate
323 
324 .keywords: SNES, nonlinear, default, converged, convergence
325 
326 .seealso: SNESSetConvergenceTest()
327 @*/
328 PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
329 {
330   PetscErrorCode ierr;
331 
332   PetscFunctionBegin;
333   PetscValidHeaderSpecific(snes,SNES_COOKIE,1);
334   PetscValidPointer(reason,6);
335 
336   *reason = SNES_CONVERGED_ITERATING;
337 
338   if (!it) {
339     /* set parameter for default relative tolerance convergence test */
340     snes->ttol = fnorm*snes->rtol;
341   }
342   if (fnorm != fnorm) {
343     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
344     *reason = SNES_DIVERGED_FNORM_NAN;
345   } else if (fnorm < snes->abstol) {
346     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
347     *reason = SNES_CONVERGED_FNORM_ABS;
348   } else if (snes->nfuncs >= snes->max_funcs) {
349     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
350     *reason = SNES_DIVERGED_FUNCTION_COUNT;
351   }
352 
353   if (it && !*reason) {
354     if (fnorm <= snes->ttol) {
355       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
356       *reason = SNES_CONVERGED_FNORM_RELATIVE;
357     } else if (pnorm < snes->xtol*xnorm) {
358       ierr = PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes->xtol,xnorm);CHKERRQ(ierr);
359       *reason = SNES_CONVERGED_PNORM_RELATIVE;
360     }
361   }
362   PetscFunctionReturn(0);
363 }
364 
365 #undef __FUNCT__
366 #define __FUNCT__ "SNESSkipConverged"
367 /*@C
368    SNESSkipConverged - Convergence test for SNES that NEVER returns as
369    converged, UNLESS the maximum number of iteration have been reached.
370 
371    Collective on SNES
372 
373    Input Parameters:
374 +  snes - the SNES context
375 .  it - the iteration (0 indicates before any Newton steps)
376 .  xnorm - 2-norm of current iterate
377 .  pnorm - 2-norm of current step
378 .  fnorm - 2-norm of function at current iterate
379 -  dummy - unused context
380 
381    Output Parameter:
382 .   reason  - SNES_CONVERGED_ITERATING or SNES_DIVERGED_FNORM_NAN
383 
384    Notes:
385    Convergence is then declared after a fixed number of iterations have been used.
386 
387    Level: advanced
388 
389 .keywords: SNES, nonlinear, skip, converged, convergence
390 
391 .seealso: SNESSetConvergenceTest()
392 @*/
393 PetscErrorCode PETSCSNES_DLLEXPORT SNESSkipConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
394 {
395   PetscErrorCode ierr;
396 
397   PetscFunctionBegin;
398   PetscValidHeaderSpecific(snes,SNES_COOKIE,1);
399   PetscValidPointer(reason,6);
400 
401   *reason = SNES_CONVERGED_ITERATING;
402 
403   if (fnorm != fnorm) {
404     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
405     *reason = SNES_DIVERGED_FNORM_NAN;
406   } else if(it == snes->max_its) {
407     *reason = SNES_CONVERGED_ITS;
408   }
409   PetscFunctionReturn(0);
410 }
411 
412