Actual source code: snesut.c
1: #define PETSCSNES_DLL
3: #include private/snesimpl.h
7: /*@C
8: SNESMonitorSolution - Monitors progress of the SNES solvers by calling
9: VecView() for the approximate solution at each iteration.
11: Collective on SNES
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
19: Level: intermediate
21: .keywords: SNES, nonlinear, vector, monitor, view
23: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
24: @*/
25: PetscErrorCode SNESMonitorSolution(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
26: {
28: Vec x;
29: PetscViewer viewer = (PetscViewer) dummy;
32: SNESGetSolution(snes,&x);
33: if (!viewer) {
34: MPI_Comm comm;
35: PetscObjectGetComm((PetscObject)snes,&comm);
36: viewer = PETSC_VIEWER_DRAW_(comm);
37: }
38: VecView(x,viewer);
40: return(0);
41: }
45: /*@C
46: SNESMonitorResidual - Monitors progress of the SNES solvers by calling
47: VecView() for the residual at each iteration.
49: Collective on SNES
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
57: Level: intermediate
59: .keywords: SNES, nonlinear, vector, monitor, view
61: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
62: @*/
63: PetscErrorCode SNESMonitorResidual(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
64: {
66: Vec x;
67: PetscViewer viewer = (PetscViewer) dummy;
70: SNESGetFunction(snes,&x,0,0);
71: if (!viewer) {
72: MPI_Comm comm;
73: PetscObjectGetComm((PetscObject)snes,&comm);
74: viewer = PETSC_VIEWER_DRAW_(comm);
75: }
76: VecView(x,viewer);
78: return(0);
79: }
83: /*@C
84: SNESMonitorSolutionUpdate - Monitors progress of the SNES solvers by calling
85: VecView() for the UPDATE to the solution at each iteration.
87: Collective on SNES
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
95: Level: intermediate
97: .keywords: SNES, nonlinear, vector, monitor, view
99: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
100: @*/
101: PetscErrorCode SNESMonitorSolutionUpdate(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
102: {
104: Vec x;
105: PetscViewer viewer = (PetscViewer) dummy;
108: SNESGetSolutionUpdate(snes,&x);
109: if (!viewer) {
110: MPI_Comm comm;
111: PetscObjectGetComm((PetscObject)snes,&comm);
112: viewer = PETSC_VIEWER_DRAW_(comm);
113: }
114: VecView(x,viewer);
116: return(0);
117: }
121: /*@C
122: SNESMonitorDefault - Monitors progress of the SNES solvers (default).
124: Collective on SNES
126: Input Parameters:
127: + snes - the SNES context
128: . its - iteration number
129: . fgnorm - 2-norm of residual
130: - dummy - unused context
132: Notes:
133: This routine prints the residual norm at each iteration.
135: Level: intermediate
137: .keywords: SNES, nonlinear, default, monitor, norm
139: .seealso: SNESMonitorSet(), SNESMonitorSolution()
140: @*/
141: PetscErrorCode SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
142: {
143: PetscErrorCode ierr;
144: PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
147: if (!dummy) {
148: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);
149: }
150: PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);
151: if (!dummy) {
152: PetscViewerASCIIMonitorDestroy(viewer);
153: }
154: return(0);
155: }
159: PetscErrorCode 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;
168: SNESGetFunction(snes,&resid,0,0);
169: VecNorm(resid,NORM_INFINITY,&rmax);
170: VecGetLocalSize(resid,&n);
171: VecGetSize(resid,&N);
172: VecGetArray(resid,&r);
173: pwork = 0.0;
174: for (i=0; i<n; i++) {
175: pwork += (PetscAbsScalar(r[i]) > .20*rmax);
176: }
177: MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);
178: VecRestoreArray(resid,&r);
179: *per = *per/N;
180: return(0);
181: }
185: /*@C
186: SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value.
188: Collective on SNES
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
196: Options Database Key:
197: . -snes_monitor_range - Activates SNESMonitorRange()
199: Level: intermediate
201: .keywords: SNES, default, monitor, residual
203: .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate()
204: @*/
205: PetscErrorCode 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;
214: if (!it) prev = rnorm;
215: if (!dummy) {PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);}
216: SNESMonitorRange_Private(snes,it,&perc);
218: rel = (prev - rnorm)/prev;
219: prev = rnorm;
220: 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);
221: if (!dummy) {PetscViewerASCIIMonitorDestroy(viewer);}
222: return(0);
223: }
225: typedef struct {
226: PetscViewerASCIIMonitor viewer;
227: PetscReal *history;
228: } SNESMonitorRatioContext;
232: /*@C
233: SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio
234: of residual norm at each iteration to the previous.
236: Collective on SNES
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
244: Level: intermediate
246: .keywords: SNES, nonlinear, monitor, norm
248: .seealso: SNESMonitorSet(), SNESMonitorSolution()
249: @*/
250: PetscErrorCode SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
251: {
252: PetscErrorCode ierr;
253: PetscInt len;
254: PetscReal *history;
255: SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy;
258: SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);
259: if (!its || !history || its > len) {
260: PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);
261: } else {
262: PetscReal ratio = fgnorm/history[its-1];
263: PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %G \n",its,fgnorm,ratio);
264: }
265: return(0);
266: }
268: /*
269: If the we set the history monitor space then we must destroy it
270: */
273: PetscErrorCode SNESMonitorRatioDestroy(void *ct)
274: {
275: PetscErrorCode ierr;
276: SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)ct;
279: PetscFree(ctx->history);
280: PetscViewerASCIIMonitorDestroy(ctx->viewer);
281: PetscFree(ctx);
282: return(0);
283: }
287: /*@C
288: SNESMonitorSetRatio - Sets SNES to use a monitor that prints the
289: ratio of the function norm at each iteration.
291: Collective on SNES
293: Input Parameters:
294: + snes - the SNES context
295: - viewer - ASCII viewer to print output
297: Level: intermediate
299: .keywords: SNES, nonlinear, monitor, norm
301: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
302: @*/
303: PetscErrorCode SNESMonitorSetRatio(SNES snes,PetscViewerASCIIMonitor viewer)
304: {
305: PetscErrorCode ierr;
306: SNESMonitorRatioContext *ctx;
307: PetscReal *history;
310: if (!viewer) {
311: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);
312: PetscObjectReference((PetscObject)viewer);
313: }
314: PetscNewLog(snes,SNESMonitorRatioContext,&ctx);
315: SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);
316: if (!history) {
317: PetscMalloc(100*sizeof(PetscReal),&ctx->history);
318: SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);
319: }
320: ctx->viewer = viewer;
321: SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);
322: return(0);
323: }
325: /* ---------------------------------------------------------------- */
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 SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
336: {
337: PetscErrorCode ierr;
338: PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
341: if (!dummy) {
342: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);
343: }
344: if (fgnorm > 1.e-9) {
345: PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);
346: } else if (fgnorm > 1.e-11){
347: PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);
348: } else {
349: PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);
350: }
351: if (!dummy) {
352: PetscViewerASCIIMonitorDestroy(viewer);
353: }
354: return(0);
355: }
356: /* ---------------------------------------------------------------- */
359: /*@C
360: SNESDefaultConverged - Convergence test of the solvers for
361: systems of nonlinear equations (default).
363: Collective on SNES
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
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),
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()
390: Level: intermediate
392: .keywords: SNES, nonlinear, default, converged, convergence
394: .seealso: SNESSetConvergenceTest()
395: @*/
396: PetscErrorCode SNESDefaultConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
397: {
403:
404: *reason = SNES_CONVERGED_ITERATING;
406: if (!it) {
407: /* set parameter for default relative tolerance convergence test */
408: snes->ttol = fnorm*snes->rtol;
409: }
410: if (fnorm != fnorm) {
411: PetscInfo(snes,"Failed to converged, function norm is NaN\n");
412: *reason = SNES_DIVERGED_FNORM_NAN;
413: } else if (fnorm < snes->abstol) {
414: PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);
415: *reason = SNES_CONVERGED_FNORM_ABS;
416: } else if (snes->nfuncs >= snes->max_funcs) {
417: PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);
418: *reason = SNES_DIVERGED_FUNCTION_COUNT;
419: }
421: if (it && !*reason) {
422: if (fnorm <= snes->ttol) {
423: PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);
424: *reason = SNES_CONVERGED_FNORM_RELATIVE;
425: } else if (pnorm < snes->xtol*xnorm) {
426: PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes->xtol,xnorm);
427: *reason = SNES_CONVERGED_PNORM_RELATIVE;
428: }
429: }
430: return(0);
431: }
435: /*@C
436: SNESSkipConverged - Convergence test for SNES that NEVER returns as
437: converged, UNLESS the maximum number of iteration have been reached.
439: Collective on SNES
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
449: Output Parameter:
450: . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN
452: Notes:
453: Convergence is then declared after a fixed number of iterations have been used.
454:
455: Level: advanced
457: .keywords: SNES, nonlinear, skip, converged, convergence
459: .seealso: SNESSetConvergenceTest()
460: @*/
461: PetscErrorCode SNESSkipConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
462: {
469: *reason = SNES_CONVERGED_ITERATING;
471: if (fnorm != fnorm) {
472: PetscInfo(snes,"Failed to converged, function norm is NaN\n");
473: *reason = SNES_DIVERGED_FNORM_NAN;
474: } else if(it == snes->max_its) {
475: *reason = SNES_CONVERGED_ITS;
476: }
477: return(0);
478: }