Actual source code: snesut.c

  1: #define PETSCSNES_DLL

 3:  #include src/snes/snesimpl.h

  7: /*@C
  8:    SNESVecViewMonitor - 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: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
 24: @*/
 25: PetscErrorCode PETSCSNES_DLLEXPORT SNESVecViewMonitor(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:    SNESVecViewResidualMonitor - 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: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
 62: @*/
 63: PetscErrorCode PETSCSNES_DLLEXPORT SNESVecViewResidualMonitor(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:    SNESVecViewUpdateMonitor - 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: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
100: @*/
101: PetscErrorCode PETSCSNES_DLLEXPORT SNESVecViewUpdateMonitor(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:    SNESDefaultMonitor - 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: SNESSetMonitor(), SNESVecViewMonitor()
140: @*/
141: PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
142: {
144:   PetscViewer    viewer = (PetscViewer) dummy;

147:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(snes->comm);
148:   PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);
149:   return(0);
150: }

154: /*@C
155:    SNESRatioMonitor - Monitors progress of the SNES solvers by printing the ratio
156:    of residual norm at each iteration to the previous.

158:    Collective on SNES

160:    Input Parameters:
161: +  snes - the SNES context
162: .  its - iteration number
163: .  fgnorm - 2-norm of residual (or gradient)
164: -  dummy - unused context

166:    Level: intermediate

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

170: .seealso: SNESSetMonitor(), SNESVecViewMonitor()
171: @*/
172: PetscErrorCode PETSCSNES_DLLEXPORT SNESRatioMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
173: {
175:   PetscInt       len;
176:   PetscReal      *history;
177:   PetscViewer    viewer;

180:   viewer = PETSC_VIEWER_STDOUT_(snes->comm);

182:   SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);
183:   if (!its || !history || its > len) {
184:     PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);
185:   } else {
186:     PetscReal ratio = fgnorm/history[its-1];
187:     PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e %g \n",its,fgnorm,ratio);
188:   }
189:   return(0);
190: }

192: /*
193:    If the we set the history monitor space then we must destroy it
194: */
197: PetscErrorCode SNESRatioMonitorDestroy(void *history)
198: {

202:   PetscFree(history);
203:   return(0);
204: }

208: /*@C
209:    SNESSetRatioMonitor - Sets SNES to use a monitor that prints the 
210:    ratio of the function norm at each iteration.

212:    Collective on SNES

214:    Input Parameters:
215: .   snes - the SNES context

217:    Level: intermediate

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

221: .seealso: SNESSetMonitor(), SNESVecViewMonitor(), SNESDefaultMonitor()
222: @*/
223: PetscErrorCode PETSCSNES_DLLEXPORT SNESSetRatioMonitor(SNES snes)
224: {
226:   PetscReal      *history;


230:   SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);
231:   if (!history) {
232:     PetscMalloc(100*sizeof(double),&history);
233:     SNESSetConvergenceHistory(snes,history,0,100,PETSC_TRUE);
234:     SNESSetMonitor(snes,SNESRatioMonitor,history,SNESRatioMonitorDestroy);
235:   } else {
236:     SNESSetMonitor(snes,SNESRatioMonitor,0,0);
237:   }
238:   return(0);
239: }

241: /* ---------------------------------------------------------------- */
244: /*
245:      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
246:   it prints fewer digits of the residual as the residual gets smaller.
247:   This is because the later digits are meaningless and are often 
248:   different on different machines; by using this routine different 
249:   machines will usually generate the same output.
250: */
251: PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultSMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
252: {

256:   if (fgnorm > 1.e-9) {
257:     PetscPrintf(snes->comm,"%3D SNES Function norm %g \n",its,fgnorm);
258:   } else if (fgnorm > 1.e-11){
259:     PetscPrintf(snes->comm,"%3D SNES Function norm %5.3e \n",its,fgnorm);
260:   } else {
261:     PetscPrintf(snes->comm,"%3D SNES Function norm < 1.e-11\n",its);
262:   }
263:   return(0);
264: }
265: /* ---------------------------------------------------------------- */
268: /*@C 
269:    SNESConverged_LS - Monitors the convergence of the solvers for
270:    systems of nonlinear equations (default).

272:    Collective on SNES

274:    Input Parameters:
275: +  snes - the SNES context
276: .  xnorm - 2-norm of current iterate
277: .  pnorm - 2-norm of current step 
278: .  fnorm - 2-norm of function
279: -  dummy - unused context

281:    Output Parameter:
282: .   reason  - one of
283: $  SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
284: $  SNES_CONVERGED_PNORM_RELATIVE  - (pnorm < xtol*xnorm),
285: $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
286: $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
287: $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
288: $  SNES_CONVERGED_ITERATING       - (otherwise),

290:    where
291: +    maxf - maximum number of function evaluations,
292:             set with SNESSetTolerances()
293: .    nfct - number of function evaluations,
294: .    abstol - absolute function norm tolerance,
295:             set with SNESSetTolerances()
296: -    rtol - relative function norm tolerance, set with SNESSetTolerances()

298:    Level: intermediate

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

302: .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
303: @*/
304: PetscErrorCode PETSCSNES_DLLEXPORT SNESConverged_LS(SNES snes,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
305: {

309:   if (fnorm != fnorm) {
310:     PetscLogInfo((snes,"SNESConverged_LS:Failed to converged, function norm is NaN\n"));
311:     *reason = SNES_DIVERGED_FNORM_NAN;
312:   } else if (fnorm <= snes->ttol) {
313:     PetscLogInfo((snes,"SNESConverged_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol));
314:     *reason = SNES_CONVERGED_FNORM_RELATIVE;
315:   } else if (fnorm < snes->abstol) {
316:     PetscLogInfo((snes,"SNESConverged_LS:Converged due to function norm %g < %g\n",fnorm,snes->abstol));
317:     *reason = SNES_CONVERGED_FNORM_ABS;
318:   } else if (pnorm < snes->xtol*xnorm) {
319:     PetscLogInfo((snes,"SNESConverged_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm));
320:     *reason = SNES_CONVERGED_PNORM_RELATIVE;
321:   } else if (snes->nfuncs >= snes->max_funcs) {
322:     PetscLogInfo((snes,"SNESConverged_LS:Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs));
323:     *reason = SNES_DIVERGED_FUNCTION_COUNT ;
324:   } else {
325:     *reason = SNES_CONVERGED_ITERATING;
326:   }
327:   return(0);
328: }
329: /* ------------------------------------------------------------ */
332: /*@
333:    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
334:    for the linear solvers within an inexact Newton method.  

336:    Collective on SNES

338:    Input Parameter:
339: .  snes - SNES context

341:    Notes:
342:    Currently, the default is to use a constant relative tolerance for 
343:    the inner linear solvers.  Alternatively, one can use the 
344:    Eisenstat-Walker method, where the relative convergence tolerance 
345:    is reset at each Newton iteration according progress of the nonlinear 
346:    solver. 

348:    Level: advanced

350:    Reference:
351:    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 
352:    inexact Newton method", SISC 17 (1), pp.16-32, 1996.

354: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
355: @*/
356: PetscErrorCode PETSCSNES_DLLEXPORT SNES_KSP_SetConvergenceTestEW(SNES snes)
357: {
359:   snes->ksp_ewconv = PETSC_TRUE;
360:   return(0);
361: }

365: /*@
366:    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
367:    convergence criteria for the linear solvers within an inexact
368:    Newton method.

370:    Collective on SNES
371:  
372:    Input Parameters:
373: +    snes - SNES context
374: .    version - version 1 or 2 (default is 2)
375: .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
376: .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
377: .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
378: .    alpha2 - power for safeguard
379: .    gamma2 - multiplicative factor for version 2 rtol computation
380:               (0 <= gamma2 <= 1)
381: -    threshold - threshold for imposing safeguard (0 < threshold < 1)

383:    Note:
384:    Use PETSC_DEFAULT to retain the default for any of the parameters.

386:    Level: advanced

388:    Reference:
389:    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 
390:    inexact Newton method", Utah State University Math. Stat. Dept. Res. 
391:    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 

393: .keywords: SNES, KSP, Eisenstat, Walker, set, parameters

395: .seealso: SNES_KSP_SetConvergenceTestEW()
396: @*/
397: PetscErrorCode PETSCSNES_DLLEXPORT SNES_KSP_SetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,PetscReal gamma2,PetscReal alpha,
398:                                         PetscReal alpha2,PetscReal threshold)
399: {
400:   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;

403:   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
404:   if (version != PETSC_DEFAULT)   kctx->version   = version;
405:   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0    = rtol_0;
406:   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max  = rtol_max;
407:   if (gamma2 != PETSC_DEFAULT)    kctx->gamma     = gamma2;
408:   if (alpha != PETSC_DEFAULT)     kctx->alpha     = alpha;
409:   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2    = alpha2;
410:   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
411:   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
412:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0);
413:   }
414:   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
415:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%g) < 1.0\n",kctx->rtol_max);
416:   }
417:   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
418:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%g) < 1.0\n",kctx->threshold);
419:   }
420:   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
421:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%g) <= 1.0\n",kctx->gamma);
422:   }
423:   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
424:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%g) <= 2.0\n",kctx->alpha);
425:   }
426:   if (kctx->version != 1 && kctx->version !=2) {
427:     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 and 2 are supported: %D",kctx->version);
428:   }
429:   return(0);
430: }

434: PetscErrorCode SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
435: {
436:   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
437:   PetscReal           rtol = 0.0,stol;
438:   PetscErrorCode      ierr;

441:   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists");
442:   if (!snes->iter) { /* first time in, so use the original user rtol */
443:     rtol = kctx->rtol_0;
444:   } else {
445:     if (kctx->version == 1) {
446:       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
447:       if (rtol < 0.0) rtol = -rtol;
448:       stol = pow(kctx->rtol_last,kctx->alpha2);
449:       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
450:     } else if (kctx->version == 2) {
451:       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
452:       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
453:       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
454:     } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 or 2 are supported: %D",kctx->version);
455:   }
456:   rtol = PetscMin(rtol,kctx->rtol_max);
457:   kctx->rtol_last = rtol;
458:   PetscLogInfo((snes,"SNES_KSP_EW_ComputeRelativeTolerance_Private: iter %D, Eisenstat-Walker (version %D) KSP rtol = %g\n",snes->iter,kctx->version,rtol));
459:   KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
460:   kctx->norm_last = snes->norm;
461:   return(0);
462: }

466: PetscErrorCode SNES_KSP_EW_Converged_Private(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx)
467: {
468:   SNES                snes = (SNES)ctx;
469:   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
470:   PetscErrorCode      ierr;

473:   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context set");
474:   if (!n) {SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);}
475:   KSPDefaultConverged(ksp,n,rnorm,reason,ctx);
476:   kctx->lresid_last = rnorm;
477:   if (*reason) {
478:     PetscLogInfo((snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%D, rnorm=%g\n",n,rnorm));
479:   }
480:   return(0);
481: }