Date: 2021-03-03T22:27:40+00:00

Actual source code: snesut.c
petsc-3.14.5 2021-03-03
Report Typos and Errors

      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: }