Actual source code: snesut.c

petsc-3.6.0 2015-06-09
Report Typos and Errors
  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:    KSPMonitorSNES - Print the residual norm of the nonlinear function at each iteration of the linear iterative solver.

122:    Collective on KSP

124:    Input Parameters:
125: +  ksp   - iterative context
126: .  n     - iteration number
127: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).
128: -  dummy - unused monitor context

130:    Level: intermediate

132: .keywords: KSP, default, monitor, residual

134: .seealso: KSPMonitorSet(), KSPMonitorTrueResidualNorm(), KSPMonitorLGResidualNormCreate()
135: @*/
136: PetscErrorCode  KSPMonitorSNES(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
137: {
139:   PetscViewer    viewer;
140:   SNES           snes = (SNES) dummy;
141:   Vec            snes_solution,work1,work2;
142:   PetscReal      snorm;

145:   SNESGetSolution(snes,&snes_solution);
146:   VecDuplicate(snes_solution,&work1);
147:   VecDuplicate(snes_solution,&work2);
148:   KSPBuildSolution(ksp,work1,NULL);
149:   VecAYPX(work1,-1.0,snes_solution);
150:   SNESComputeFunction(snes,work1,work2);
151:   VecNorm(work2,NORM_2,&snorm);
152:   VecDestroy(&work1);
153:   VecDestroy(&work2);

155:   PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ksp),&viewer);
156:   PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);
157:   if (n == 0 && ((PetscObject)ksp)->prefix) {
158:     PetscViewerASCIIPrintf(viewer,"  Residual norms for %s solve.\n",((PetscObject)ksp)->prefix);
159:   }
160:   PetscViewerASCIIPrintf(viewer,"%3D SNES Residual norm %5.3e KSP Residual norm %5.3e \n",n,(double)snorm,(double)rnorm);
161:   PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);
162:   return(0);
163: }

165: #include <petscdraw.h>

169: /*@C
170:    KSPMonitorSNESLGResidualNormCreate - Creates a line graph context for use with
171:    KSP to monitor convergence of preconditioned residual norms.

173:    Collective on KSP

175:    Input Parameters:
176: +  host - the X display to open, or null for the local machine
177: .  label - the title to put in the title bar
178: .  x, y - the screen coordinates of the upper left coordinate of
179:           the window
180: -  m, n - the screen width and height in pixels

182:    Output Parameter:
183: .  draw - the drawing context

185:    Options Database Key:
186: .  -ksp_monitor_lg_residualnorm - Sets line graph monitor

188:    Notes:
189:    Use KSPMonitorSNESLGResidualNormDestroy() to destroy this line graph; do not use PetscDrawLGDestroy().

191:    Level: intermediate

193: .keywords: KSP, monitor, line graph, residual, create

195: .seealso: KSPMonitorSNESLGResidualNormDestroy(), KSPMonitorSet(), KSPMonitorSNESLGTrueResidualCreate()
196: @*/
197: PetscErrorCode  KSPMonitorSNESLGResidualNormCreate(const char host[],const char label[],int x,int y,int m,int n,PetscObject **objs)
198: {
199:   PetscDraw      draw;
201:   PetscDrawAxis  axis;
202:   PetscDrawLG    drawlg;
203:   const char     *names[] = {"Linear residual","Nonlinear residual"};

206:   PetscDrawCreate(PETSC_COMM_SELF,host,label,x,y,m,n,&draw);
207:   PetscDrawSetFromOptions(draw);
208:   PetscDrawLGCreate(draw,2,&drawlg);
209:   PetscDrawLGSetFromOptions(drawlg);
210:   PetscDrawLGGetAxis(drawlg,&axis);
211:   PetscDrawAxisSetLabels(axis,"Convergence of Residual Norm","Iteration","Residual Norm");
212:   PetscDrawLGSetLegend(drawlg,names);
213:   PetscLogObjectParent((PetscObject)drawlg,(PetscObject)draw);

215:   PetscMalloc1(3,objs);
216:   (*objs)[1] = (PetscObject)drawlg;
217:   (*objs)[2] = (PetscObject)draw;
218:   return(0);
219: }

223: PetscErrorCode  KSPMonitorSNESLGResidualNorm(KSP ksp,PetscInt n,PetscReal rnorm,PetscObject *objs)
224: {
225:   PetscDrawLG    lg = (PetscDrawLG) objs[1];
227:   PetscReal      y[2];
228:   SNES           snes = (SNES) objs[0];
229:   Vec            snes_solution,work1,work2;

232:   if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
233:   else y[0] = -15.0;

235:   SNESGetSolution(snes,&snes_solution);
236:   VecDuplicate(snes_solution,&work1);
237:   VecDuplicate(snes_solution,&work2);
238:   KSPBuildSolution(ksp,work1,NULL);
239:   VecAYPX(work1,-1.0,snes_solution);
240:   SNESComputeFunction(snes,work1,work2);
241:   VecNorm(work2,NORM_2,y+1);
242:   if (y[1] > 0.0) y[1] = PetscLog10Real(y[1]);
243:   else y[1] = -15.0;
244:   VecDestroy(&work1);
245:   VecDestroy(&work2);

247:   PetscDrawLGAddPoint(lg,NULL,y);
248:   if (n < 20 || !(n % 5)) {
249:     PetscDrawLGDraw(lg);
250:   }
251:   return(0);
252: }

256: /*@
257:    KSPMonitorSNESLGResidualNormDestroy - Destroys a line graph context that was created
258:    with KSPMonitorSNESLGResidualNormCreate().

260:    Collective on KSP

262:    Input Parameter:
263: .  draw - the drawing context

265:    Level: intermediate

267: .keywords: KSP, monitor, line graph, destroy

269: .seealso: KSPMonitorSNESLGResidualNormCreate(), KSPMonitorSNESLGTrueResidualDestroy(), KSPMonitorSet()
270: @*/
271: PetscErrorCode  KSPMonitorSNESLGResidualNormDestroy(PetscObject **objs)
272: {
274:   PetscDrawLG    drawlg = (PetscDrawLG) (*objs)[1];
275:   PetscDraw      draw = (PetscDraw) (*objs)[2];

278:   PetscDrawDestroy(&draw);
279:   PetscDrawLGDestroy(&drawlg);
280:   PetscFree(*objs);
281:   return(0);
282: }

286: /*@C
287:    SNESMonitorDefault - Monitors progress of the SNES solvers (default).

289:    Collective on SNES

291:    Input Parameters:
292: +  snes - the SNES context
293: .  its - iteration number
294: .  fgnorm - 2-norm of residual
295: -  dummy - unused context

297:    Notes:
298:    This routine prints the residual norm at each iteration.

300:    Level: intermediate

302: .keywords: SNES, nonlinear, default, monitor, norm

304: .seealso: SNESMonitorSet(), SNESMonitorSolution()
305: @*/
306: PetscErrorCode  SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
307: {
309:   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));

312:   PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
313:   PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);
314:   PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
315:   return(0);
316: }

320: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes,PetscInt it,PetscReal fnorm,void *ctx)
321: {
322: #if defined(PETSC_MISSING_LAPACK_GEEV)
323:   SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - Lapack routine is unavailable\nNot able to provide eigen values.");
324: #elif defined(PETSC_HAVE_ESSL)
325:   SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - No support for ESSL Lapack Routines");
326: #else
327:   Vec            X;
328:   Mat            J,dJ,dJdense;
330:   PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
331:   PetscInt       n,i;
332:   PetscBLASInt   nb,lwork;
333:   PetscReal      *eigr,*eigi;
334:   PetscScalar    *work;
335:   PetscScalar    *a;

338:   if (it == 0) return(0);
339:   /* create the difference between the current update and the current jacobian */
340:   SNESGetSolution(snes,&X);
341:   SNESGetJacobian(snes,NULL,&J,&func,NULL);
342:   MatDuplicate(J,MAT_COPY_VALUES,&dJ);
343:   SNESComputeJacobian(snes,X,dJ,dJ);
344:   MatAXPY(dJ,-1.0,J,SAME_NONZERO_PATTERN);

346:   /* compute the spectrum directly */
347:   MatConvert(dJ,MATSEQDENSE,MAT_INITIAL_MATRIX,&dJdense);
348:   MatGetSize(dJ,&n,NULL);
349:   PetscBLASIntCast(n,&nb);
350:   lwork = 3*nb;
351:   PetscMalloc1(n,&eigr);
352:   PetscMalloc1(n,&eigi);
353:   PetscMalloc1(lwork,&work);
354:   MatDenseGetArray(dJdense,&a);
355: #if !defined(PETSC_USE_COMPLEX)
356:   {
357:     PetscBLASInt lierr;
358:     PetscFPTrapPush(PETSC_FP_TRAP_OFF);
359:     PetscStackCallBLAS("LAPACKgeev",LAPACKgeev_("N","N",&nb,a,&nb,eigr,eigi,NULL,&nb,NULL,&nb,work,&lwork,&lierr));
360:     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"geev() error %d",lierr);
361:     PetscFPTrapPop();
362:   }
363: #else
364:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded for complex");
365: #endif
366:   PetscPrintf(PetscObjectComm((PetscObject)snes),"Eigenvalues of J_%d - J_%d:\n",it,it-1);
367:   for (i=0;i<n;i++) {
368:     PetscPrintf(PetscObjectComm((PetscObject)snes),"%5d: %20.5g + %20.5gi\n",i,(double)eigr[i],(double)eigi[i]);
369:   }
370:   MatDenseRestoreArray(dJdense,&a);
371:   MatDestroy(&dJ);
372:   MatDestroy(&dJdense);
373:   PetscFree(eigr);
374:   PetscFree(eigi);
375:   PetscFree(work);
376:   return(0);
377: #endif
378: }

382: PetscErrorCode  SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per)
383: {
385:   Vec            resid;
386:   PetscReal      rmax,pwork;
387:   PetscInt       i,n,N;
388:   PetscScalar    *r;

391:   SNESGetFunction(snes,&resid,0,0);
392:   VecNorm(resid,NORM_INFINITY,&rmax);
393:   VecGetLocalSize(resid,&n);
394:   VecGetSize(resid,&N);
395:   VecGetArray(resid,&r);
396:   pwork = 0.0;
397:   for (i=0; i<n; i++) {
398:     pwork += (PetscAbsScalar(r[i]) > .20*rmax);
399:   }
400:   MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));
401:   VecRestoreArray(resid,&r);
402:   *per = *per/N;
403:   return(0);
404: }

408: /*@C
409:    SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value.

411:    Collective on SNES

413:    Input Parameters:
414: +  snes   - iterative context
415: .  it    - iteration number
416: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).
417: -  dummy - unused monitor context

419:    Options Database Key:
420: .  -snes_monitor_range - Activates SNESMonitorRange()

422:    Level: intermediate

424: .keywords: SNES, default, monitor, residual

426: .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate()
427: @*/
428: PetscErrorCode  SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy)
429: {
431:   PetscReal      perc,rel;
432:   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
433:   /* should be in a MonitorRangeContext */
434:   static PetscReal prev;

437:   if (!it) prev = rnorm;
438:   SNESMonitorRange_Private(snes,it,&perc);

440:   rel  = (prev - rnorm)/prev;
441:   prev = rnorm;
442:   PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
443:   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));
444:   PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
445:   return(0);
446: }

448: typedef struct {
449:   PetscViewer viewer;
450:   PetscReal   *history;
451: } SNESMonitorRatioContext;

455: /*@C
456:    SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio
457:    of residual norm at each iteration to the previous.

459:    Collective on SNES

461:    Input Parameters:
462: +  snes - the SNES context
463: .  its - iteration number
464: .  fgnorm - 2-norm of residual (or gradient)
465: -  dummy -  context of monitor

467:    Level: intermediate

469: .keywords: SNES, nonlinear, monitor, norm

471: .seealso: SNESMonitorSet(), SNESMonitorSolution()
472: @*/
473: PetscErrorCode  SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
474: {
475:   PetscErrorCode          ierr;
476:   PetscInt                len;
477:   PetscReal               *history;
478:   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy;

481:   SNESGetConvergenceHistory(snes,&history,NULL,&len);
482:   PetscViewerASCIIAddTab(ctx->viewer,((PetscObject)snes)->tablevel);
483:   if (!its || !history || its > len) {
484:     PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);
485:   } else {
486:     PetscReal ratio = fgnorm/history[its-1];
487:     PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %14.12e \n",its,(double)fgnorm,(double)ratio);
488:   }
489:   PetscViewerASCIISubtractTab(ctx->viewer,((PetscObject)snes)->tablevel);
490:   return(0);
491: }

493: /*
494:    If the we set the history monitor space then we must destroy it
495: */
498: PetscErrorCode SNESMonitorRatioDestroy(void **ct)
499: {
500:   PetscErrorCode          ierr;
501:   SNESMonitorRatioContext *ctx = *(SNESMonitorRatioContext**)ct;

504:   PetscFree(ctx->history);
505:   PetscViewerDestroy(&ctx->viewer);
506:   PetscFree(ctx);
507:   return(0);
508: }

512: /*@C
513:    SNESMonitorSetRatio - Sets SNES to use a monitor that prints the
514:    ratio of the function norm at each iteration.

516:    Collective on SNES

518:    Input Parameters:
519: +   snes - the SNES context
520: -   viewer - ASCII viewer to print output

522:    Level: intermediate

524: .keywords: SNES, nonlinear, monitor, norm

526: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
527: @*/
528: PetscErrorCode  SNESMonitorSetRatio(SNES snes,PetscViewer viewer)
529: {
530:   PetscErrorCode          ierr;
531:   SNESMonitorRatioContext *ctx;
532:   PetscReal               *history;

535:   if (!viewer) {
536:     PetscViewerASCIIOpen(PetscObjectComm((PetscObject)snes),"stdout",&viewer);
537:     PetscObjectReference((PetscObject)viewer);
538:   }
539:   PetscNewLog(snes,&ctx);
540:   SNESGetConvergenceHistory(snes,&history,NULL,NULL);
541:   if (!history) {
542:     PetscMalloc1(100,&ctx->history);
543:     SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);
544:   }
545:   ctx->viewer = viewer;

547:   SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);
548:   return(0);
549: }

551: /* ---------------------------------------------------------------- */
554: /*
555:      Default (short) SNES Monitor, same as SNESMonitorDefault() except
556:   it prints fewer digits of the residual as the residual gets smaller.
557:   This is because the later digits are meaningless and are often
558:   different on different machines; by using this routine different
559:   machines will usually generate the same output.
560: */
561: PetscErrorCode  SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
562: {
564:   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));

567:   PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
568:   if (fgnorm > 1.e-9) {
569:     PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %g \n",its,(double)fgnorm);
570:   } else if (fgnorm > 1.e-11) {
571:     PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,(double)fgnorm);
572:   } else {
573:     PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);
574:   }
575:   PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
576:   return(0);
577: }

581: /*@C
582:   SNESMonitorDefaultField - Monitors progress of the SNES solvers, separated into fields.

584:   Collective on SNES

586:   Input Parameters:
587: + snes   - the SNES context
588: . its    - iteration number
589: . fgnorm - 2-norm of residual
590: - ctx    - the PetscViewer

592:   Notes:
593:   This routine uses the DM attached to the residual vector

595:   Level: intermediate

597: .keywords: SNES, nonlinear, field, monitor, norm
598: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault(), SNESMonitorDefaultShort()
599: @*/
600: PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, void *ctx)
601: {
602:   PetscViewer    viewer = ctx ? (PetscViewer) ctx : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) snes));
603:   Vec            r;
604:   DM             dm;
605:   PetscReal      res[256];
606:   PetscInt       tablevel;

610:   SNESGetFunction(snes, &r, NULL, NULL);
611:   VecGetDM(r, &dm);
612:   if (!dm) {SNESMonitorDefault(snes, its, fgnorm, ctx);}
613:   else {
614:     PetscSection s, gs;
615:     PetscInt     Nf, f;

617:     DMGetDefaultSection(dm, &s);
618:     DMGetDefaultGlobalSection(dm, &gs);
619:     if (!s || !gs) {SNESMonitorDefault(snes, its, fgnorm, ctx);}
620:     PetscSectionGetNumFields(s, &Nf);
621:     if (Nf > 256) SETERRQ1(PetscObjectComm((PetscObject) snes), PETSC_ERR_SUP, "Do not support %d fields > 256", Nf);
622:     PetscSectionVecNorm(s, gs, r, NORM_2, res);
623:     PetscObjectGetTabLevel((PetscObject) snes, &tablevel);
624:     PetscViewerASCIIAddTab(viewer, tablevel);
625:     PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);
626:     for (f = 0; f < Nf; ++f) {
627:       if (f) {PetscViewerASCIIPrintf(viewer, ", ");}
628:       PetscViewerASCIIPrintf(viewer, "%14.12e", res[f]);
629:     }
630:     PetscViewerASCIIPrintf(viewer, "] \n");
631:     PetscViewerASCIISubtractTab(viewer, tablevel);
632:   }
633:   return(0);
634: }
635: /* ---------------------------------------------------------------- */
638: /*@C
639:    SNESConvergedDefault - Convergence test of the solvers for
640:    systems of nonlinear equations (default).

642:    Collective on SNES

644:    Input Parameters:
645: +  snes - the SNES context
646: .  it - the iteration (0 indicates before any Newton steps)
647: .  xnorm - 2-norm of current iterate
648: .  snorm - 2-norm of current step
649: .  fnorm - 2-norm of function at current iterate
650: -  dummy - unused context

652:    Output Parameter:
653: .   reason  - one of
654: $  SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
655: $  SNES_CONVERGED_SNORM_RELATIVE  - (snorm < stol*xnorm),
656: $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
657: $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
658: $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
659: $  SNES_CONVERGED_ITERATING       - (otherwise),

661:    where
662: +    maxf - maximum number of function evaluations,
663:             set with SNESSetTolerances()
664: .    nfct - number of function evaluations,
665: .    abstol - absolute function norm tolerance,
666:             set with SNESSetTolerances()
667: -    rtol - relative function norm tolerance, set with SNESSetTolerances()

669:    Level: intermediate

671: .keywords: SNES, nonlinear, default, converged, convergence

673: .seealso: SNESSetConvergenceTest()
674: @*/
675: PetscErrorCode  SNESConvergedDefault(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
676: {


683:   *reason = SNES_CONVERGED_ITERATING;

685:   if (!it) {
686:     /* set parameter for default relative tolerance convergence test */
687:     snes->ttol = fnorm*snes->rtol;
688:   }
689:   if (PetscIsInfOrNanReal(fnorm)) {
690:     PetscInfo(snes,"Failed to converged, function norm is NaN\n");
691:     *reason = SNES_DIVERGED_FNORM_NAN;
692:   } else if (fnorm < snes->abstol) {
693:     PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e\n",(double)fnorm,(double)snes->abstol);
694:     *reason = SNES_CONVERGED_FNORM_ABS;
695:   } else if (snes->nfuncs >= snes->max_funcs) {
696:     PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);
697:     *reason = SNES_DIVERGED_FUNCTION_COUNT;
698:   }

700:   if (it && !*reason) {
701:     if (fnorm <= snes->ttol) {
702:       PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e (relative tolerance)\n",(double)fnorm,(double)snes->ttol);
703:       *reason = SNES_CONVERGED_FNORM_RELATIVE;
704:     } else if (snorm < snes->stol*xnorm) {
705:       PetscInfo3(snes,"Converged due to small update length: %14.12e < %14.12e * %14.12e\n",(double)snorm,(double)snes->stol,(double)xnorm);
706:       *reason = SNES_CONVERGED_SNORM_RELATIVE;
707:     }
708:   }
709:   return(0);
710: }

714: /*@C
715:    SNESConvergedSkip - Convergence test for SNES that NEVER returns as
716:    converged, UNLESS the maximum number of iteration have been reached.

718:    Logically Collective on SNES

720:    Input Parameters:
721: +  snes - the SNES context
722: .  it - the iteration (0 indicates before any Newton steps)
723: .  xnorm - 2-norm of current iterate
724: .  snorm - 2-norm of current step
725: .  fnorm - 2-norm of function at current iterate
726: -  dummy - unused context

728:    Output Parameter:
729: .   reason  - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN

731:    Notes:
732:    Convergence is then declared after a fixed number of iterations have been used.

734:    Level: advanced

736: .keywords: SNES, nonlinear, skip, converged, convergence

738: .seealso: SNESSetConvergenceTest()
739: @*/
740: PetscErrorCode  SNESConvergedSkip(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
741: {


748:   *reason = SNES_CONVERGED_ITERATING;

750:   if (fnorm != fnorm) {
751:     PetscInfo(snes,"Failed to converged, function norm is NaN\n");
752:     *reason = SNES_DIVERGED_FNORM_NAN;
753:   } else if (it == snes->max_its) {
754:     *reason = SNES_CONVERGED_ITS;
755:   }
756:   return(0);
757: }

761: /*@C
762:   SNESSetWorkVecs - Gets a number of work vectors.

764:   Input Parameters:
765: . snes  - the SNES context
766: . nw - number of work vectors to allocate

768:    Level: developer

770:    Developers Note: This is PETSC_EXTERN because it may be used by user written plugin SNES implementations

772: @*/
773: PetscErrorCode SNESSetWorkVecs(SNES snes,PetscInt nw)
774: {
775:   DM             dm;
776:   Vec            v;

780:   if (snes->work) {VecDestroyVecs(snes->nwork,&snes->work);}
781:   snes->nwork = nw;

783:   SNESGetDM(snes, &dm);
784:   DMGetGlobalVector(dm, &v);
785:   VecDuplicateVecs(v,snes->nwork,&snes->work);
786:   DMRestoreGlobalVector(dm, &v);
787:   PetscLogObjectParents(snes,nw,snes->work);
788:   return(0);
789: }