Actual source code: snesut.c
petsc-dev 2014-02-02
2: #include <petsc-private/snesimpl.h> /*I "petsc-private/snesimpl.h" I*/
3: #include <petscdm.h>
4: #include <petscblaslapack.h>
8: /*@C
9: SNESMonitorSolution - Monitors progress of the SNES solvers by calling
10: VecView() for the approximate solution at each iteration.
12: Collective on SNES
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
20: Level: intermediate
22: .keywords: SNES, nonlinear, vector, monitor, view
24: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
25: @*/
26: PetscErrorCode SNESMonitorSolution(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
27: {
29: Vec x;
30: PetscViewer viewer = (PetscViewer) dummy;
33: SNESGetSolution(snes,&x);
34: if (!viewer) {
35: MPI_Comm comm;
36: PetscObjectGetComm((PetscObject)snes,&comm);
37: viewer = PETSC_VIEWER_DRAW_(comm);
38: }
39: 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 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);
77: return(0);
78: }
82: /*@C
83: SNESMonitorSolutionUpdate - Monitors progress of the SNES solvers by calling
84: VecView() for the UPDATE to the solution at each iteration.
86: Collective on SNES
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
94: Level: intermediate
96: .keywords: SNES, nonlinear, vector, monitor, view
98: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
99: @*/
100: PetscErrorCode SNESMonitorSolutionUpdate(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
101: {
103: Vec x;
104: PetscViewer viewer = (PetscViewer) dummy;
107: SNESGetSolutionUpdate(snes,&x);
108: if (!viewer) {
109: MPI_Comm comm;
110: PetscObjectGetComm((PetscObject)snes,&comm);
111: viewer = PETSC_VIEWER_DRAW_(comm);
112: }
113: VecView(x,viewer);
114: return(0);
115: }
119: /*@C
120: SNESMonitorDefault - Monitors progress of the SNES solvers (default).
122: Collective on SNES
124: Input Parameters:
125: + snes - the SNES context
126: . its - iteration number
127: . fgnorm - 2-norm of residual
128: - dummy - unused context
130: Notes:
131: This routine prints the residual norm at each iteration.
133: Level: intermediate
135: .keywords: SNES, nonlinear, default, monitor, norm
137: .seealso: SNESMonitorSet(), SNESMonitorSolution()
138: @*/
139: PetscErrorCode SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
140: {
142: PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
145: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
146: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);
147: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
148: return(0);
149: }
153: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes,PetscInt it,PetscReal fnorm,void *ctx)
154: {
155: #if defined(PETSC_MISSING_LAPACK_GEEV)
156: SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - Lapack routine is unavailable\nNot able to provide eigen values.");
157: #elif defined(PETSC_HAVE_ESSL)
158: SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - No support for ESSL Lapack Routines");
159: #else
160: Vec X;
161: Mat J,dJ,dJdense;
163: PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
164: PetscInt n,i;
165: PetscBLASInt nb,lwork;
166: PetscReal *eigr,*eigi;
167: MatStructure flg = DIFFERENT_NONZERO_PATTERN;
168: PetscScalar *work;
169: PetscScalar *a;
172: if (it == 0) return(0);
173: /* create the difference between the current update and the current jacobian */
174: SNESGetSolution(snes,&X);
175: SNESGetJacobian(snes,&J,NULL,&func,NULL);
176: MatDuplicate(J,MAT_COPY_VALUES,&dJ);
177: SNESComputeJacobian(snes,X,&dJ,&dJ,&flg);
178: MatAXPY(dJ,-1.0,J,SAME_NONZERO_PATTERN);
180: /* compute the spectrum directly */
181: MatConvert(dJ,MATSEQDENSE,MAT_INITIAL_MATRIX,&dJdense);
182: MatGetSize(dJ,&n,NULL);
183: PetscBLASIntCast(n,&nb);
184: lwork = 3*nb;
185: PetscMalloc1(n,&eigr);
186: PetscMalloc1(n,&eigi);
187: PetscMalloc1(lwork,&work);
188: MatDenseGetArray(dJdense,&a);
189: #if !defined(PETSC_USE_COMPLEX)
190: {
191: PetscBLASInt lierr;
192: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
193: PetscStackCallBLAS("LAPACKgeev",LAPACKgeev_("N","N",&nb,a,&nb,eigr,eigi,NULL,&nb,NULL,&nb,work,&lwork,&lierr));
194: if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"geev() error %d",lierr);
195: PetscFPTrapPop();
196: }
197: #else
198: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded for complex");
199: #endif
200: PetscPrintf(PetscObjectComm((PetscObject)snes),"Eigenvalues of J_%d - J_%d:\n",it,it-1);
201: for (i=0;i<n;i++) {
202: PetscPrintf(PetscObjectComm((PetscObject)snes),"%5d: %20.5g + %20.5gi\n",i,(double)eigr[i],(double)eigi[i]);
203: }
204: MatDenseRestoreArray(dJdense,&a);
205: MatDestroy(&dJ);
206: MatDestroy(&dJdense);
207: PetscFree(eigr);
208: PetscFree(eigi);
209: PetscFree(work);
210: return(0);
211: #endif
212: }
216: PetscErrorCode SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per)
217: {
219: Vec resid;
220: PetscReal rmax,pwork;
221: PetscInt i,n,N;
222: PetscScalar *r;
225: SNESGetFunction(snes,&resid,0,0);
226: VecNorm(resid,NORM_INFINITY,&rmax);
227: VecGetLocalSize(resid,&n);
228: VecGetSize(resid,&N);
229: VecGetArray(resid,&r);
230: pwork = 0.0;
231: for (i=0; i<n; i++) {
232: pwork += (PetscAbsScalar(r[i]) > .20*rmax);
233: }
234: MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));
235: VecRestoreArray(resid,&r);
236: *per = *per/N;
237: return(0);
238: }
242: /*@C
243: SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value.
245: Collective on SNES
247: Input Parameters:
248: + snes - iterative context
249: . it - iteration number
250: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
251: - dummy - unused monitor context
253: Options Database Key:
254: . -snes_monitor_range - Activates SNESMonitorRange()
256: Level: intermediate
258: .keywords: SNES, default, monitor, residual
260: .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate()
261: @*/
262: PetscErrorCode SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy)
263: {
265: PetscReal perc,rel;
266: PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
267: /* should be in a MonitorRangeContext */
268: static PetscReal prev;
271: if (!it) prev = rnorm;
272: SNESMonitorRange_Private(snes,it,&perc);
274: rel = (prev - rnorm)/prev;
275: prev = rnorm;
276: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
277: 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));
278: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
279: return(0);
280: }
282: typedef struct {
283: PetscViewer viewer;
284: PetscReal *history;
285: } SNESMonitorRatioContext;
289: /*@C
290: SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio
291: of residual norm at each iteration to the previous.
293: Collective on SNES
295: Input Parameters:
296: + snes - the SNES context
297: . its - iteration number
298: . fgnorm - 2-norm of residual (or gradient)
299: - dummy - context of monitor
301: Level: intermediate
303: .keywords: SNES, nonlinear, monitor, norm
305: .seealso: SNESMonitorSet(), SNESMonitorSolution()
306: @*/
307: PetscErrorCode SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
308: {
309: PetscErrorCode ierr;
310: PetscInt len;
311: PetscReal *history;
312: SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy;
315: SNESGetConvergenceHistory(snes,&history,NULL,&len);
316: PetscViewerASCIIAddTab(ctx->viewer,((PetscObject)snes)->tablevel);
317: if (!its || !history || its > len) {
318: PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);
319: } else {
320: PetscReal ratio = fgnorm/history[its-1];
321: PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %14.12e \n",its,(double)fgnorm,(double)ratio);
322: }
323: PetscViewerASCIISubtractTab(ctx->viewer,((PetscObject)snes)->tablevel);
324: return(0);
325: }
327: /*
328: If the we set the history monitor space then we must destroy it
329: */
332: PetscErrorCode SNESMonitorRatioDestroy(void **ct)
333: {
334: PetscErrorCode ierr;
335: SNESMonitorRatioContext *ctx = *(SNESMonitorRatioContext**)ct;
338: PetscFree(ctx->history);
339: PetscViewerDestroy(&ctx->viewer);
340: PetscFree(ctx);
341: return(0);
342: }
346: /*@C
347: SNESMonitorSetRatio - Sets SNES to use a monitor that prints the
348: ratio of the function norm at each iteration.
350: Collective on SNES
352: Input Parameters:
353: + snes - the SNES context
354: - viewer - ASCII viewer to print output
356: Level: intermediate
358: .keywords: SNES, nonlinear, monitor, norm
360: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
361: @*/
362: PetscErrorCode SNESMonitorSetRatio(SNES snes,PetscViewer viewer)
363: {
364: PetscErrorCode ierr;
365: SNESMonitorRatioContext *ctx;
366: PetscReal *history;
369: if (!viewer) {
370: PetscViewerASCIIOpen(PetscObjectComm((PetscObject)snes),"stdout",&viewer);
371: PetscObjectReference((PetscObject)viewer);
372: }
373: PetscNewLog(snes,&ctx);
374: SNESGetConvergenceHistory(snes,&history,NULL,NULL);
375: if (!history) {
376: PetscMalloc1(100,&ctx->history);
377: SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);
378: }
379: ctx->viewer = viewer;
381: SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);
382: return(0);
383: }
385: /* ---------------------------------------------------------------- */
388: /*
389: Default (short) SNES Monitor, same as SNESMonitorDefault() except
390: it prints fewer digits of the residual as the residual gets smaller.
391: This is because the later digits are meaningless and are often
392: different on different machines; by using this routine different
393: machines will usually generate the same output.
394: */
395: PetscErrorCode SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
396: {
398: PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
401: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
402: if (fgnorm > 1.e-9) {
403: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %g \n",its,(double)fgnorm);
404: } else if (fgnorm > 1.e-11) {
405: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,(double)fgnorm);
406: } else {
407: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);
408: }
409: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
410: return(0);
411: }
412: /* ---------------------------------------------------------------- */
415: /*@C
416: SNESConvergedDefault - Convergence test of the solvers for
417: systems of nonlinear equations (default).
419: Collective on SNES
421: Input Parameters:
422: + snes - the SNES context
423: . it - the iteration (0 indicates before any Newton steps)
424: . xnorm - 2-norm of current iterate
425: . snorm - 2-norm of current step
426: . fnorm - 2-norm of function at current iterate
427: - dummy - unused context
429: Output Parameter:
430: . reason - one of
431: $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol),
432: $ SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm),
433: $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0),
434: $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf),
435: $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN),
436: $ SNES_CONVERGED_ITERATING - (otherwise),
438: where
439: + maxf - maximum number of function evaluations,
440: set with SNESSetTolerances()
441: . nfct - number of function evaluations,
442: . abstol - absolute function norm tolerance,
443: set with SNESSetTolerances()
444: - rtol - relative function norm tolerance, set with SNESSetTolerances()
446: Level: intermediate
448: .keywords: SNES, nonlinear, default, converged, convergence
450: .seealso: SNESSetConvergenceTest()
451: @*/
452: PetscErrorCode SNESConvergedDefault(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
453: {
460: *reason = SNES_CONVERGED_ITERATING;
462: if (!it) {
463: /* set parameter for default relative tolerance convergence test */
464: snes->ttol = fnorm*snes->rtol;
465: }
466: if (PetscIsInfOrNanReal(fnorm)) {
467: PetscInfo(snes,"Failed to converged, function norm is NaN\n");
468: *reason = SNES_DIVERGED_FNORM_NAN;
469: } else if (fnorm < snes->abstol) {
470: PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e\n",(double)fnorm,(double)snes->abstol);
471: *reason = SNES_CONVERGED_FNORM_ABS;
472: } else if (snes->nfuncs >= snes->max_funcs) {
473: PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);
474: *reason = SNES_DIVERGED_FUNCTION_COUNT;
475: }
477: if (it && !*reason) {
478: if (fnorm <= snes->ttol) {
479: PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e (relative tolerance)\n",(double)fnorm,(double)snes->ttol);
480: *reason = SNES_CONVERGED_FNORM_RELATIVE;
481: } else if (snorm < snes->stol*xnorm) {
482: PetscInfo3(snes,"Converged due to small update length: %14.12e < %14.12e * %14.12e\n",(double)snorm,(double)snes->stol,(double)xnorm);
483: *reason = SNES_CONVERGED_SNORM_RELATIVE;
484: }
485: }
486: return(0);
487: }
491: /*@C
492: SNESConvergedSkip - Convergence test for SNES that NEVER returns as
493: converged, UNLESS the maximum number of iteration have been reached.
495: Logically Collective on SNES
497: Input Parameters:
498: + snes - the SNES context
499: . it - the iteration (0 indicates before any Newton steps)
500: . xnorm - 2-norm of current iterate
501: . snorm - 2-norm of current step
502: . fnorm - 2-norm of function at current iterate
503: - dummy - unused context
505: Output Parameter:
506: . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN
508: Notes:
509: Convergence is then declared after a fixed number of iterations have been used.
511: Level: advanced
513: .keywords: SNES, nonlinear, skip, converged, convergence
515: .seealso: SNESSetConvergenceTest()
516: @*/
517: PetscErrorCode SNESConvergedSkip(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
518: {
525: *reason = SNES_CONVERGED_ITERATING;
527: if (fnorm != fnorm) {
528: PetscInfo(snes,"Failed to converged, function norm is NaN\n");
529: *reason = SNES_DIVERGED_FNORM_NAN;
530: } else if (it == snes->max_its) {
531: *reason = SNES_CONVERGED_ITS;
532: }
533: return(0);
534: }
538: /*@C
539: SNESSetWorkVecs - Gets a number of work vectors.
541: Input Parameters:
542: . snes - the SNES context
543: . nw - number of work vectors to allocate
545: Level: developer
547: Developers Note: This is PETSC_EXTERN because it may be used by user written plugin SNES implementations
549: @*/
550: PetscErrorCode SNESSetWorkVecs(SNES snes,PetscInt nw)
551: {
552: DM dm;
553: Vec v;
557: if (snes->work) {VecDestroyVecs(snes->nwork,&snes->work);}
558: snes->nwork = nw;
560: SNESGetDM(snes, &dm);
561: DMGetGlobalVector(dm, &v);
562: VecDuplicateVecs(v,snes->nwork,&snes->work);
563: DMRestoreGlobalVector(dm, &v);
564: PetscLogObjectParents(snes,nw,snes->work);
565: return(0);
566: }