Actual source code: snesut.c
petsc-3.14.6 2021-03-30
2: #include <petsc/private/snesimpl.h>
3: #include <petscdm.h>
4: #include <petscsection.h>
5: #include <petscblaslapack.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 - a viewer
19: Options Database Keys:
20: . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
22: Level: intermediate
24: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
25: @*/
26: PetscErrorCode SNESMonitorSolution(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf)
27: {
29: Vec x;
30: PetscViewer viewer = vf->viewer;
34: SNESGetSolution(snes,&x);
35: PetscViewerPushFormat(viewer,vf->format);
36: VecView(x,viewer);
37: PetscViewerPopFormat(viewer);
38: return(0);
39: }
41: /*@C
42: SNESMonitorResidual - Monitors progress of the SNES solvers by calling
43: VecView() for the residual at each iteration.
45: Collective on SNES
47: Input Parameters:
48: + snes - the SNES context
49: . its - iteration number
50: . fgnorm - 2-norm of residual
51: - dummy - a viewer
53: Options Database Keys:
54: . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration
56: Level: intermediate
58: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
59: @*/
60: PetscErrorCode SNESMonitorResidual(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf)
61: {
63: Vec x;
64: PetscViewer viewer = vf->viewer;
68: SNESGetFunction(snes,&x,NULL,NULL);
69: PetscViewerPushFormat(viewer,vf->format);
70: VecView(x,viewer);
71: PetscViewerPopFormat(viewer);
72: return(0);
73: }
75: /*@C
76: SNESMonitorSolutionUpdate - Monitors progress of the SNES solvers by calling
77: VecView() for the UPDATE to the solution at each iteration.
79: Collective on SNES
81: Input Parameters:
82: + snes - the SNES context
83: . its - iteration number
84: . fgnorm - 2-norm of residual
85: - dummy - a viewer
87: Options Database Keys:
88: . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
90: Level: intermediate
92: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
93: @*/
94: PetscErrorCode SNESMonitorSolutionUpdate(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf)
95: {
97: Vec x;
98: PetscViewer viewer = vf->viewer;
102: SNESGetSolutionUpdate(snes,&x);
103: PetscViewerPushFormat(viewer,vf->format);
104: VecView(x,viewer);
105: PetscViewerPopFormat(viewer);
106: return(0);
107: }
109: /*@C
110: KSPMonitorSNES - Print the residual norm of the nonlinear function at each iteration of the linear iterative solver.
112: Collective on KSP
114: Input Parameters:
115: + ksp - iterative context
116: . n - iteration number
117: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
118: - dummy - unused monitor context
120: Level: intermediate
122: .seealso: KSPMonitorSet(), KSPMonitorTrueResidualNorm(), KSPMonitorLGResidualNormCreate()
123: @*/
124: PetscErrorCode KSPMonitorSNES(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
125: {
127: PetscViewer viewer;
128: SNES snes = (SNES) dummy;
129: Vec snes_solution,work1,work2;
130: PetscReal snorm;
133: SNESGetSolution(snes,&snes_solution);
134: VecDuplicate(snes_solution,&work1);
135: VecDuplicate(snes_solution,&work2);
136: KSPBuildSolution(ksp,work1,NULL);
137: VecAYPX(work1,-1.0,snes_solution);
138: SNESComputeFunction(snes,work1,work2);
139: VecNorm(work2,NORM_2,&snorm);
140: VecDestroy(&work1);
141: VecDestroy(&work2);
143: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ksp),&viewer);
144: PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);
145: if (n == 0 && ((PetscObject)ksp)->prefix) {
146: PetscViewerASCIIPrintf(viewer," Residual norms for %s solve.\n",((PetscObject)ksp)->prefix);
147: }
148: PetscViewerASCIIPrintf(viewer,"%3D SNES Residual norm %5.3e KSP Residual norm %5.3e \n",n,(double)snorm,(double)rnorm);
149: PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);
150: return(0);
151: }
153: #include <petscdraw.h>
155: /*@C
156: KSPMonitorSNESLGResidualNormCreate - Creates a line graph context for use with
157: KSP to monitor convergence of preconditioned residual norms.
159: Collective on KSP
161: Input Parameters:
162: + comm - communicator context
163: . host - the X display to open, or null for the local machine
164: . label - the title to put in the title bar
165: . x, y - the screen coordinates of the upper left coordinate of
166: the window
167: - m, n - the screen width and height in pixels
169: Output Parameter:
170: . draw - the drawing context
172: Options Database Key:
173: . -ksp_monitor_lg_residualnorm - Sets line graph monitor
175: Notes:
176: Use KSPMonitorSNESLGResidualNormDestroy() to destroy this line graph; do not use PetscDrawLGDestroy().
178: Level: intermediate
180: .seealso: KSPMonitorSNESLGResidualNormDestroy(), KSPMonitorSet(), KSPMonitorSNESLGTrueResidualCreate()
181: @*/
182: PetscErrorCode KSPMonitorSNESLGResidualNormCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscObject **objs)
183: {
184: PetscDraw draw;
186: PetscDrawAxis axis;
187: PetscDrawLG lg;
188: const char *names[] = {"Linear residual","Nonlinear residual"};
191: PetscDrawCreate(comm,host,label,x,y,m,n,&draw);
192: PetscDrawSetFromOptions(draw);
193: PetscDrawLGCreate(draw,2,&lg);
194: PetscDrawLGSetLegend(lg,names);
195: PetscDrawLGSetFromOptions(lg);
196: PetscDrawLGGetAxis(lg,&axis);
197: PetscDrawAxisSetLabels(axis,"Convergence of Residual Norm","Iteration","Residual Norm");
198: PetscDrawDestroy(&draw);
200: PetscMalloc1(2,objs);
201: (*objs)[1] = (PetscObject)lg;
202: return(0);
203: }
205: PetscErrorCode KSPMonitorSNESLGResidualNorm(KSP ksp,PetscInt n,PetscReal rnorm,PetscObject *objs)
206: {
207: SNES snes = (SNES) objs[0];
208: PetscDrawLG lg = (PetscDrawLG) objs[1];
210: PetscReal y[2];
211: Vec snes_solution,work1,work2;
214: if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
215: else y[0] = -15.0;
217: SNESGetSolution(snes,&snes_solution);
218: VecDuplicate(snes_solution,&work1);
219: VecDuplicate(snes_solution,&work2);
220: KSPBuildSolution(ksp,work1,NULL);
221: VecAYPX(work1,-1.0,snes_solution);
222: SNESComputeFunction(snes,work1,work2);
223: VecNorm(work2,NORM_2,y+1);
224: if (y[1] > 0.0) y[1] = PetscLog10Real(y[1]);
225: else y[1] = -15.0;
226: VecDestroy(&work1);
227: VecDestroy(&work2);
229: PetscDrawLGAddPoint(lg,NULL,y);
230: if (n < 20 || !(n % 5) || snes->reason) {
231: PetscDrawLGDraw(lg);
232: PetscDrawLGSave(lg);
233: }
234: return(0);
235: }
237: /*@
238: KSPMonitorSNESLGResidualNormDestroy - Destroys a line graph context that was created
239: with KSPMonitorSNESLGResidualNormCreate().
241: Collective on KSP
243: Input Parameter:
244: . draw - the drawing context
246: Level: intermediate
248: .seealso: KSPMonitorSNESLGResidualNormCreate(), KSPMonitorSNESLGTrueResidualDestroy(), KSPMonitorSet()
249: @*/
250: PetscErrorCode KSPMonitorSNESLGResidualNormDestroy(PetscObject **objs)
251: {
253: PetscDrawLG lg = (PetscDrawLG) (*objs)[1];
256: PetscDrawLGDestroy(&lg);
257: PetscFree(*objs);
258: return(0);
259: }
261: /*@C
262: SNESMonitorDefault - Monitors progress of the SNES solvers (default).
264: Collective on SNES
266: Input Parameters:
267: + snes - the SNES context
268: . its - iteration number
269: . fgnorm - 2-norm of residual
270: - vf - viewer and format structure
272: Notes:
273: This routine prints the residual norm at each iteration.
275: Level: intermediate
277: .seealso: SNESMonitorSet(), SNESMonitorSolution()
278: @*/
279: PetscErrorCode SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf)
280: {
282: PetscViewer viewer = vf->viewer;
286: PetscViewerPushFormat(viewer,vf->format);
287: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
288: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);
289: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
290: PetscViewerPopFormat(viewer);
291: return(0);
292: }
294: /*@C
295: SNESMonitorScaling - Monitors the largest value in each row of the Jacobian.
297: Collective on SNES
299: Input Parameters:
300: + snes - the SNES context
301: . its - iteration number
302: . fgnorm - 2-norm of residual
303: - vf - viewer and format structure
305: Notes:
306: This routine prints the largest value in each row of the Jacobian
308: Level: intermediate
310: .seealso: SNESMonitorSet(), SNESMonitorSolution()
311: @*/
312: PetscErrorCode SNESMonitorScaling(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf)
313: {
315: PetscViewer viewer = vf->viewer;
316: KSP ksp;
317: Mat J;
318: Vec v;
322: SNESGetKSP(snes,&ksp);
323: KSPGetOperators(ksp,&J,NULL);
324: MatCreateVecs(J,&v,NULL);
325: MatGetRowMaxAbs(J,v,NULL);
326: PetscViewerPushFormat(viewer,vf->format);
327: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
328: PetscViewerASCIIPrintf(viewer,"%3D SNES Jacobian maximum row entries \n");
329: VecView(v,viewer);
330: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
331: PetscViewerPopFormat(viewer);
332: VecDestroy(&v);
333: return(0);
334: }
336: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes,PetscInt it,PetscReal fnorm,PetscViewerAndFormat *vf)
337: {
338: #if defined(PETSC_HAVE_ESSL)
339: SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - No support for ESSL Lapack Routines");
340: #else
341: Vec X;
342: Mat J,dJ,dJdense;
344: PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
345: PetscInt n,i;
346: PetscBLASInt nb = 0,lwork;
347: PetscReal *eigr,*eigi;
348: PetscScalar *work;
349: PetscScalar *a;
352: if (it == 0) return(0);
353: /* create the difference between the current update and the current jacobian */
354: SNESGetSolution(snes,&X);
355: SNESGetJacobian(snes,NULL,&J,&func,NULL);
356: MatDuplicate(J,MAT_COPY_VALUES,&dJ);
357: SNESComputeJacobian(snes,X,dJ,dJ);
358: MatAXPY(dJ,-1.0,J,SAME_NONZERO_PATTERN);
360: /* compute the spectrum directly */
361: MatConvert(dJ,MATSEQDENSE,MAT_INITIAL_MATRIX,&dJdense);
362: MatGetSize(dJ,&n,NULL);
363: PetscBLASIntCast(n,&nb);
364: lwork = 3*nb;
365: PetscMalloc1(n,&eigr);
366: PetscMalloc1(n,&eigi);
367: PetscMalloc1(lwork,&work);
368: MatDenseGetArray(dJdense,&a);
369: #if !defined(PETSC_USE_COMPLEX)
370: {
371: PetscBLASInt lierr;
372: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
373: PetscStackCallBLAS("LAPACKgeev",LAPACKgeev_("N","N",&nb,a,&nb,eigr,eigi,NULL,&nb,NULL,&nb,work,&lwork,&lierr));
374: if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"geev() error %d",lierr);
375: PetscFPTrapPop();
376: }
377: #else
378: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded for complex");
379: #endif
380: PetscPrintf(PetscObjectComm((PetscObject)snes),"Eigenvalues of J_%d - J_%d:\n",it,it-1);
381: for (i=0;i<n;i++) {
382: PetscPrintf(PetscObjectComm((PetscObject)snes),"%5d: %20.5g + %20.5gi\n",i,(double)eigr[i],(double)eigi[i]);
383: }
384: MatDenseRestoreArray(dJdense,&a);
385: MatDestroy(&dJ);
386: MatDestroy(&dJdense);
387: PetscFree(eigr);
388: PetscFree(eigi);
389: PetscFree(work);
390: return(0);
391: #endif
392: }
394: PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES,PetscInt,PetscReal*);
396: PetscErrorCode SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per)
397: {
399: Vec resid;
400: PetscReal rmax,pwork;
401: PetscInt i,n,N;
402: PetscScalar *r;
405: SNESGetFunction(snes,&resid,NULL,NULL);
406: VecNorm(resid,NORM_INFINITY,&rmax);
407: VecGetLocalSize(resid,&n);
408: VecGetSize(resid,&N);
409: VecGetArray(resid,&r);
410: pwork = 0.0;
411: for (i=0; i<n; i++) {
412: pwork += (PetscAbsScalar(r[i]) > .20*rmax);
413: }
414: MPIU_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));
415: VecRestoreArray(resid,&r);
416: *per = *per/N;
417: return(0);
418: }
420: /*@C
421: SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value.
423: Collective on SNES
425: Input Parameters:
426: + snes - iterative context
427: . it - iteration number
428: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
429: - dummy - unused monitor context
431: Options Database Key:
432: . -snes_monitor_range - Activates SNESMonitorRange()
434: Level: intermediate
436: .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate()
437: @*/
438: PetscErrorCode SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,PetscViewerAndFormat *vf)
439: {
441: PetscReal perc,rel;
442: PetscViewer viewer = vf->viewer;
443: /* should be in a MonitorRangeContext */
444: static PetscReal prev;
448: if (!it) prev = rnorm;
449: SNESMonitorRange_Private(snes,it,&perc);
451: rel = (prev - rnorm)/prev;
452: prev = rnorm;
453: PetscViewerPushFormat(viewer,vf->format);
454: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
455: 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));
456: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
457: PetscViewerPopFormat(viewer);
458: return(0);
459: }
461: /*@C
462: SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio
463: of residual norm at each iteration to the previous.
465: Collective on SNES
467: Input Parameters:
468: + snes - the SNES context
469: . its - iteration number
470: . fgnorm - 2-norm of residual (or gradient)
471: - dummy - context of monitor
473: Level: intermediate
475: Notes:
476: Insure that SNESMonitorRatio() is called when you set this monitor
477: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorRatio()
478: @*/
479: PetscErrorCode SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf)
480: {
481: PetscErrorCode ierr;
482: PetscInt len;
483: PetscReal *history;
484: PetscViewer viewer = vf->viewer;
487: SNESGetConvergenceHistory(snes,&history,NULL,&len);
488: PetscViewerPushFormat(viewer,vf->format);
489: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
490: if (!its || !history || its > len) {
491: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);
492: } else {
493: PetscReal ratio = fgnorm/history[its-1];
494: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e %14.12e \n",its,(double)fgnorm,(double)ratio);
495: }
496: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
497: PetscViewerPopFormat(viewer);
498: return(0);
499: }
501: /*@C
502: SNESMonitorRatioSetUp - Insures the SNES object is saving its history since this monitor needs access to it
504: Collective on SNES
506: Input Parameters:
507: + snes - the SNES context
508: - viewer - the PetscViewer object (ignored)
510: Level: intermediate
512: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault(), SNESMonitorRatio()
513: @*/
514: PetscErrorCode SNESMonitorRatioSetUp(SNES snes,PetscViewerAndFormat *vf)
515: {
516: PetscErrorCode ierr;
517: PetscReal *history;
520: SNESGetConvergenceHistory(snes,&history,NULL,NULL);
521: if (!history) {
522: SNESSetConvergenceHistory(snes,NULL,NULL,100,PETSC_TRUE);
523: }
524: return(0);
525: }
527: /* ---------------------------------------------------------------- */
528: /*
529: Default (short) SNES Monitor, same as SNESMonitorDefault() except
530: it prints fewer digits of the residual as the residual gets smaller.
531: This is because the later digits are meaningless and are often
532: different on different machines; by using this routine different
533: machines will usually generate the same output.
535: Deprecated: Intentionally has no manual page
536: */
537: PetscErrorCode SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf)
538: {
540: PetscViewer viewer = vf->viewer;
544: PetscViewerPushFormat(viewer,vf->format);
545: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
546: if (fgnorm > 1.e-9) {
547: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %g \n",its,(double)fgnorm);
548: } else if (fgnorm > 1.e-11) {
549: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,(double)fgnorm);
550: } else {
551: PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);
552: }
553: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
554: PetscViewerPopFormat(viewer);
555: return(0);
556: }
558: /*@C
559: SNESMonitorDefaultField - Monitors progress of the SNES solvers, separated into fields.
561: Collective on SNES
563: Input Parameters:
564: + snes - the SNES context
565: . its - iteration number
566: . fgnorm - 2-norm of residual
567: - ctx - the PetscViewer
569: Notes:
570: This routine uses the DM attached to the residual vector
572: Level: intermediate
574: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
575: @*/
576: PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
577: {
578: PetscViewer viewer = vf->viewer;
579: Vec r;
580: DM dm;
581: PetscReal res[256];
582: PetscInt tablevel;
587: SNESGetFunction(snes, &r, NULL, NULL);
588: VecGetDM(r, &dm);
589: if (!dm) {SNESMonitorDefault(snes, its, fgnorm, vf);}
590: else {
591: PetscSection s, gs;
592: PetscInt Nf, f;
594: DMGetLocalSection(dm, &s);
595: DMGetGlobalSection(dm, &gs);
596: if (!s || !gs) {SNESMonitorDefault(snes, its, fgnorm, vf);}
597: PetscSectionGetNumFields(s, &Nf);
598: if (Nf > 256) SETERRQ1(PetscObjectComm((PetscObject) snes), PETSC_ERR_SUP, "Do not support %d fields > 256", Nf);
599: PetscSectionVecNorm(s, gs, r, NORM_2, res);
600: PetscObjectGetTabLevel((PetscObject) snes, &tablevel);
601: PetscViewerPushFormat(viewer,vf->format);
602: PetscViewerASCIIAddTab(viewer, tablevel);
603: PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);
604: for (f = 0; f < Nf; ++f) {
605: if (f) {PetscViewerASCIIPrintf(viewer, ", ");}
606: PetscViewerASCIIPrintf(viewer, "%14.12e", res[f]);
607: }
608: PetscViewerASCIIPrintf(viewer, "] \n");
609: PetscViewerASCIISubtractTab(viewer, tablevel);
610: PetscViewerPopFormat(viewer);
611: }
612: return(0);
613: }
614: /* ---------------------------------------------------------------- */
615: /*@C
616: SNESConvergedDefault - Default onvergence test of the solvers for
617: systems of nonlinear equations.
619: Collective on SNES
621: Input Parameters:
622: + snes - the SNES context
623: . it - the iteration (0 indicates before any Newton steps)
624: . xnorm - 2-norm of current iterate
625: . snorm - 2-norm of current step
626: . fnorm - 2-norm of function at current iterate
627: - dummy - unused context
629: Output Parameter:
630: . reason - one of
631: $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol),
632: $ SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm),
633: $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0),
634: $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf),
635: $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN),
636: $ SNES_CONVERGED_ITERATING - (otherwise),
637: $ SNES_DIVERGED_DTOL - (fnorm > divtol*snes->fnorm0)
639: where
640: + maxf - maximum number of function evaluations, set with SNESSetTolerances()
641: . nfct - number of function evaluations,
642: . abstol - absolute function norm tolerance, set with SNESSetTolerances()
643: . rtol - relative function norm tolerance, set with SNESSetTolerances()
644: . divtol - divergence tolerance, set with SNESSetDivergenceTolerance()
645: - fnorm0 - 2-norm of the function at the initial solution (initial guess; zeroth iteration)
647: Options Database Keys:
648: + -snes_stol - convergence tolerance in terms of the norm of the change in the solution between steps
649: . -snes_atol <abstol> - absolute tolerance of residual norm
650: . -snes_rtol <rtol> - relative decrease in tolerance norm from the initial 2-norm of the solution
651: . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
652: . -snes_max_funcs <max_funcs> - maximum number of function evaluations
653: . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
654: - -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
656: Level: intermediate
658: .seealso: SNESSetConvergenceTest(), SNESSetTolerances(), SNESSetDivergenceTolerance()
659: @*/
660: PetscErrorCode SNESConvergedDefault(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
661: {
668: *reason = SNES_CONVERGED_ITERATING;
670: if (!it) {
671: /* set parameter for default relative tolerance convergence test */
672: snes->ttol = fnorm*snes->rtol;
673: snes->rnorm0 = fnorm;
674: }
675: if (PetscIsInfOrNanReal(fnorm)) {
676: PetscInfo(snes,"Failed to converged, function norm is NaN\n");
677: *reason = SNES_DIVERGED_FNORM_NAN;
678: } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) {
679: PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e\n",(double)fnorm,(double)snes->abstol);
680: *reason = SNES_CONVERGED_FNORM_ABS;
681: } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) {
682: PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);
683: *reason = SNES_DIVERGED_FUNCTION_COUNT;
684: }
686: if (it && !*reason) {
687: if (fnorm <= snes->ttol) {
688: PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e (relative tolerance)\n",(double)fnorm,(double)snes->ttol);
689: *reason = SNES_CONVERGED_FNORM_RELATIVE;
690: } else if (snorm < snes->stol*xnorm) {
691: PetscInfo3(snes,"Converged due to small update length: %14.12e < %14.12e * %14.12e\n",(double)snorm,(double)snes->stol,(double)xnorm);
692: *reason = SNES_CONVERGED_SNORM_RELATIVE;
693: } else if (snes->divtol > 0 && (fnorm > snes->divtol*snes->rnorm0)) {
694: PetscInfo3(snes,"Diverged due to increase in function norm: %14.12e > %14.12e * %14.12e\n",(double)fnorm,(double)snes->divtol,(double)snes->rnorm0);
695: *reason = SNES_DIVERGED_DTOL;
696: }
698: }
699: return(0);
700: }
702: /*@C
703: SNESConvergedSkip - Convergence test for SNES that NEVER returns as
704: converged, UNLESS the maximum number of iteration have been reached.
706: Logically Collective on SNES
708: Input Parameters:
709: + snes - the SNES context
710: . it - the iteration (0 indicates before any Newton steps)
711: . xnorm - 2-norm of current iterate
712: . snorm - 2-norm of current step
713: . fnorm - 2-norm of function at current iterate
714: - dummy - unused context
716: Output Parameter:
717: . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN
719: Notes:
720: Convergence is then declared after a fixed number of iterations have been used.
722: Level: advanced
724: .seealso: SNESSetConvergenceTest()
725: @*/
726: PetscErrorCode SNESConvergedSkip(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
727: {
734: *reason = SNES_CONVERGED_ITERATING;
736: if (fnorm != fnorm) {
737: PetscInfo(snes,"Failed to converged, function norm is NaN\n");
738: *reason = SNES_DIVERGED_FNORM_NAN;
739: } else if (it == snes->max_its) {
740: *reason = SNES_CONVERGED_ITS;
741: }
742: return(0);
743: }
745: /*@C
746: SNESSetWorkVecs - Gets a number of work vectors.
748: Input Parameters:
749: + snes - the SNES context
750: - nw - number of work vectors to allocate
752: Level: developer
754: @*/
755: PetscErrorCode SNESSetWorkVecs(SNES snes,PetscInt nw)
756: {
757: DM dm;
758: Vec v;
762: if (snes->work) {VecDestroyVecs(snes->nwork,&snes->work);}
763: snes->nwork = nw;
765: SNESGetDM(snes, &dm);
766: DMGetGlobalVector(dm, &v);
767: VecDuplicateVecs(v,snes->nwork,&snes->work);
768: DMRestoreGlobalVector(dm, &v);
769: PetscLogObjectParents(snes,nw,snes->work);
770: return(0);
771: }