Actual source code: snesut.c

  1: #define PETSCSNES_DLL

 3:  #include private/snesimpl.h

  7: /*@C
  8:    SNESMonitorSolution - Monitors progress of the SNES solvers by calling 
  9:    VecView() for the approximate solution at each iteration.

 11:    Collective on SNES

 13:    Input Parameters:
 14: +  snes - the SNES context
 15: .  its - iteration number
 16: .  fgnorm - 2-norm of residual
 17: -  dummy - either a viewer or PETSC_NULL

 19:    Level: intermediate

 21: .keywords: SNES, nonlinear, vector, monitor, view

 23: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
 24: @*/
 25: PetscErrorCode  SNESMonitorSolution(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
 26: {
 28:   Vec            x;
 29:   PetscViewer    viewer = (PetscViewer) dummy;

 32:   SNESGetSolution(snes,&x);
 33:   if (!viewer) {
 34:     MPI_Comm comm;
 35:     PetscObjectGetComm((PetscObject)snes,&comm);
 36:     viewer = PETSC_VIEWER_DRAW_(comm);
 37:   }
 38:   VecView(x,viewer);

 40:   return(0);
 41: }

 45: /*@C
 46:    SNESMonitorResidual - Monitors progress of the SNES solvers by calling 
 47:    VecView() for the residual at each iteration.

 49:    Collective on SNES

 51:    Input Parameters:
 52: +  snes - the SNES context
 53: .  its - iteration number
 54: .  fgnorm - 2-norm of residual
 55: -  dummy - either a viewer or PETSC_NULL

 57:    Level: intermediate

 59: .keywords: SNES, nonlinear, vector, monitor, view

 61: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
 62: @*/
 63: PetscErrorCode  SNESMonitorResidual(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
 64: {
 66:   Vec            x;
 67:   PetscViewer    viewer = (PetscViewer) dummy;

 70:   SNESGetFunction(snes,&x,0,0);
 71:   if (!viewer) {
 72:     MPI_Comm comm;
 73:     PetscObjectGetComm((PetscObject)snes,&comm);
 74:     viewer = PETSC_VIEWER_DRAW_(comm);
 75:   }
 76:   VecView(x,viewer);

 78:   return(0);
 79: }

 83: /*@C
 84:    SNESMonitorSolutionUpdate - Monitors progress of the SNES solvers by calling 
 85:    VecView() for the UPDATE to the solution at each iteration.

 87:    Collective on SNES

 89:    Input Parameters:
 90: +  snes - the SNES context
 91: .  its - iteration number
 92: .  fgnorm - 2-norm of residual
 93: -  dummy - either a viewer or PETSC_NULL

 95:    Level: intermediate

 97: .keywords: SNES, nonlinear, vector, monitor, view

 99: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
100: @*/
101: PetscErrorCode  SNESMonitorSolutionUpdate(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
102: {
104:   Vec            x;
105:   PetscViewer    viewer = (PetscViewer) dummy;

108:   SNESGetSolutionUpdate(snes,&x);
109:   if (!viewer) {
110:     MPI_Comm comm;
111:     PetscObjectGetComm((PetscObject)snes,&comm);
112:     viewer = PETSC_VIEWER_DRAW_(comm);
113:   }
114:   VecView(x,viewer);

116:   return(0);
117: }

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

124:    Collective on SNES

126:    Input Parameters:
127: +  snes - the SNES context
128: .  its - iteration number
129: .  fgnorm - 2-norm of residual
130: -  dummy - unused context

132:    Notes:
133:    This routine prints the residual norm at each iteration.

135:    Level: intermediate

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

139: .seealso: SNESMonitorSet(), SNESMonitorSolution()
140: @*/
141: PetscErrorCode  SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
142: {
143:   PetscErrorCode          ierr;
144:   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;

147:   if (!dummy) {
148:     PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);
149:   }
150:   PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);
151:   if (!dummy) {
152:     PetscViewerASCIIMonitorDestroy(viewer);
153:   }
154:   return(0);
155: }

159: PetscErrorCode  SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per)
160: {
161:   PetscErrorCode          ierr;
162:   Vec                     resid;
163:   PetscReal               rmax,pwork;
164:   PetscInt                i,n,N;
165:   PetscScalar             *r;

168:   SNESGetFunction(snes,&resid,0,0);
169:   VecNorm(resid,NORM_INFINITY,&rmax);
170:   VecGetLocalSize(resid,&n);
171:   VecGetSize(resid,&N);
172:   VecGetArray(resid,&r);
173:   pwork = 0.0;
174:   for (i=0; i<n; i++) {
175:     pwork += (PetscAbsScalar(r[i]) > .20*rmax);
176:   }
177:   MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);
178:   VecRestoreArray(resid,&r);
179:   *per  = *per/N;
180:   return(0);
181: }

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

188:    Collective on SNES

190:    Input Parameters:
191: +  snes   - iterative context
192: .  it    - iteration number
193: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).  
194: -  dummy - unused monitor context 

196:    Options Database Key:
197: .  -snes_monitor_range - Activates SNESMonitorRange()

199:    Level: intermediate

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

203: .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate()
204: @*/
205: PetscErrorCode  SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy)
206: {
207:   PetscErrorCode          ierr;
208:   PetscReal               perc,rel;
209:   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
210:   /* should be in a MonitorRangeContext */
211:   static PetscReal        prev;

214:   if (!it) prev = rnorm;
215:   if (!dummy) {PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);}
216:   SNESMonitorRange_Private(snes,it,&perc);

218:   rel  = (prev - rnorm)/prev;
219:   prev = rnorm;
220:   PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES preconditioned resid norm %14.12e Percent values above 20 percent of maximum %5.2f relative decrease %5.2e ratio %5.2e \n",it,rnorm,100.0*perc,rel,rel/perc);
221:   if (!dummy) {PetscViewerASCIIMonitorDestroy(viewer);}
222:   return(0);
223: }

225: typedef struct {
226:   PetscViewerASCIIMonitor viewer;
227:   PetscReal               *history;
228: } SNESMonitorRatioContext;

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

236:    Collective on SNES

238:    Input Parameters:
239: +  snes - the SNES context
240: .  its - iteration number
241: .  fgnorm - 2-norm of residual (or gradient)
242: -  dummy -  context of monitor

244:    Level: intermediate

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

248: .seealso: SNESMonitorSet(), SNESMonitorSolution()
249: @*/
250: PetscErrorCode  SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
251: {
252:   PetscErrorCode          ierr;
253:   PetscInt                len;
254:   PetscReal               *history;
255:   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy;

258:   SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);
259:   if (!its || !history || its > len) {
260:     PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);
261:   } else {
262:     PetscReal ratio = fgnorm/history[its-1];
263:     PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %G \n",its,fgnorm,ratio);
264:   }
265:   return(0);
266: }

268: /*
269:    If the we set the history monitor space then we must destroy it
270: */
273: PetscErrorCode SNESMonitorRatioDestroy(void *ct)
274: {
275:   PetscErrorCode          ierr;
276:   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)ct;

279:   PetscFree(ctx->history);
280:   PetscViewerASCIIMonitorDestroy(ctx->viewer);
281:   PetscFree(ctx);
282:   return(0);
283: }

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

291:    Collective on SNES

293:    Input Parameters:
294: +   snes - the SNES context
295: -   viewer - ASCII viewer to print output

297:    Level: intermediate

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

301: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
302: @*/
303: PetscErrorCode  SNESMonitorSetRatio(SNES snes,PetscViewerASCIIMonitor viewer)
304: {
305:   PetscErrorCode          ierr;
306:   SNESMonitorRatioContext *ctx;
307:   PetscReal               *history;

310:   if (!viewer) {
311:     PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);
312:     PetscObjectReference((PetscObject)viewer);
313:   }
314:   PetscNewLog(snes,SNESMonitorRatioContext,&ctx);
315:   SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);
316:   if (!history) {
317:     PetscMalloc(100*sizeof(PetscReal),&ctx->history);
318:     SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);
319:   }
320:   ctx->viewer = viewer;
321:   SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);
322:   return(0);
323: }

325: /* ---------------------------------------------------------------- */
328: /*
329:      Default (short) SNES Monitor, same as SNESMonitorDefault() except
330:   it prints fewer digits of the residual as the residual gets smaller.
331:   This is because the later digits are meaningless and are often 
332:   different on different machines; by using this routine different 
333:   machines will usually generate the same output.
334: */
335: PetscErrorCode  SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
336: {
337:   PetscErrorCode          ierr;
338:   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;

341:   if (!dummy) {
342:     PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);
343:   }
344:   if (fgnorm > 1.e-9) {
345:     PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);
346:   } else if (fgnorm > 1.e-11){
347:     PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);
348:   } else {
349:     PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);
350:   }
351:   if (!dummy) {
352:     PetscViewerASCIIMonitorDestroy(viewer);
353:   }
354:   return(0);
355: }
356: /* ---------------------------------------------------------------- */
359: /*@C 
360:    SNESDefaultConverged - Convergence test of the solvers for
361:    systems of nonlinear equations (default).

363:    Collective on SNES

365:    Input Parameters:
366: +  snes - the SNES context
367: .  it - the iteration (0 indicates before any Newton steps)
368: .  xnorm - 2-norm of current iterate
369: .  pnorm - 2-norm of current step 
370: .  fnorm - 2-norm of function at current iterate
371: -  dummy - unused context

373:    Output Parameter:
374: .   reason  - one of
375: $  SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
376: $  SNES_CONVERGED_PNORM_RELATIVE  - (pnorm < xtol*xnorm),
377: $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
378: $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
379: $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
380: $  SNES_CONVERGED_ITERATING       - (otherwise),

382:    where
383: +    maxf - maximum number of function evaluations,
384:             set with SNESSetTolerances()
385: .    nfct - number of function evaluations,
386: .    abstol - absolute function norm tolerance,
387:             set with SNESSetTolerances()
388: -    rtol - relative function norm tolerance, set with SNESSetTolerances()

390:    Level: intermediate

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

394: .seealso: SNESSetConvergenceTest()
395: @*/
396: PetscErrorCode  SNESDefaultConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
397: {

403: 
404:   *reason = SNES_CONVERGED_ITERATING;

406:   if (!it) {
407:     /* set parameter for default relative tolerance convergence test */
408:     snes->ttol = fnorm*snes->rtol;
409:   }
410:   if (fnorm != fnorm) {
411:     PetscInfo(snes,"Failed to converged, function norm is NaN\n");
412:     *reason = SNES_DIVERGED_FNORM_NAN;
413:   } else if (fnorm < snes->abstol) {
414:     PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);
415:     *reason = SNES_CONVERGED_FNORM_ABS;
416:   } else if (snes->nfuncs >= snes->max_funcs) {
417:     PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);
418:     *reason = SNES_DIVERGED_FUNCTION_COUNT;
419:   }

421:   if (it && !*reason) {
422:     if (fnorm <= snes->ttol) {
423:       PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);
424:       *reason = SNES_CONVERGED_FNORM_RELATIVE;
425:     } else if (pnorm < snes->xtol*xnorm) {
426:       PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes->xtol,xnorm);
427:       *reason = SNES_CONVERGED_PNORM_RELATIVE;
428:     }
429:   }
430:   return(0);
431: }

435: /*@C 
436:    SNESSkipConverged - Convergence test for SNES that NEVER returns as
437:    converged, UNLESS the maximum number of iteration have been reached.

439:    Collective on SNES

441:    Input Parameters:
442: +  snes - the SNES context
443: .  it - the iteration (0 indicates before any Newton steps)
444: .  xnorm - 2-norm of current iterate
445: .  pnorm - 2-norm of current step 
446: .  fnorm - 2-norm of function at current iterate
447: -  dummy - unused context

449:    Output Parameter:
450: .   reason  - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN

452:    Notes:
453:    Convergence is then declared after a fixed number of iterations have been used.
454:                     
455:    Level: advanced

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

459: .seealso: SNESSetConvergenceTest()
460: @*/
461: PetscErrorCode  SNESSkipConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
462: {


469:   *reason = SNES_CONVERGED_ITERATING;

471:   if (fnorm != fnorm) {
472:     PetscInfo(snes,"Failed to converged, function norm is NaN\n");
473:     *reason = SNES_DIVERGED_FNORM_NAN;
474:   } else if(it == snes->max_its) {
475:     *reason = SNES_CONVERGED_ITS;
476:   }
477:   return(0);
478: }