xref: /petsc/src/snes/interface/snesut.c (revision 3f1db9ec2fd39765c6c3a00831044586630c4cca)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*3f1db9ecSBarry Smith static char vcid[] = "$Id: snesut.c,v 1.40 1998/12/03 04:05:20 bsmith Exp bsmith $";
3e7e93795SLois Curfman McInnes #endif
4e7e93795SLois Curfman McInnes 
570f55243SBarry Smith #include "src/snes/snesimpl.h"       /*I   "snes.h"   I*/
6e7e93795SLois Curfman McInnes 
75615d1e5SSatish Balay #undef __FUNC__
8*3f1db9ecSBarry Smith #define __FUNC__ "SNESVecViewMonitor"
9*3f1db9ecSBarry Smith /*@C
10*3f1db9ecSBarry Smith    SNESVecViewMonitor - Monitoring progress of the SNES solvers, by calling
11*3f1db9ecSBarry Smith        VecView() on the solution each iteration.
12*3f1db9ecSBarry Smith 
13*3f1db9ecSBarry Smith    Collective on SNES
14*3f1db9ecSBarry Smith 
15*3f1db9ecSBarry Smith    Input Parameters:
16*3f1db9ecSBarry Smith +  snes - the SNES context
17*3f1db9ecSBarry Smith .  its - iteration number
18*3f1db9ecSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
19*3f1db9ecSBarry Smith -  dummy - either a viewer or PETSC_NULL
20*3f1db9ecSBarry Smith 
21*3f1db9ecSBarry Smith    Notes:
22*3f1db9ecSBarry Smith 
23*3f1db9ecSBarry Smith .keywords: SNES, nonlinear, default, monitor, norm
24*3f1db9ecSBarry Smith 
25*3f1db9ecSBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor()
26*3f1db9ecSBarry Smith @*/
27*3f1db9ecSBarry Smith int SNESVecViewMonitor(SNES snes,int its,double fgnorm,void *dummy)
28*3f1db9ecSBarry Smith {
29*3f1db9ecSBarry Smith   int    ierr;
30*3f1db9ecSBarry Smith   Vec    x;
31*3f1db9ecSBarry Smith   Viewer viewer = (Viewer) dummy;
32*3f1db9ecSBarry Smith 
33*3f1db9ecSBarry Smith   PetscFunctionBegin;
34*3f1db9ecSBarry Smith   ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr);
35*3f1db9ecSBarry Smith   if (!viewer) {
36*3f1db9ecSBarry Smith     MPI_Comm comm;
37*3f1db9ecSBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
38*3f1db9ecSBarry Smith     viewer = VIEWER_DRAWX_(comm);
39*3f1db9ecSBarry Smith   }
40*3f1db9ecSBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
41*3f1db9ecSBarry Smith 
42*3f1db9ecSBarry Smith   PetscFunctionReturn(0);
43*3f1db9ecSBarry Smith }
44*3f1db9ecSBarry Smith 
45*3f1db9ecSBarry Smith #undef __FUNC__
46d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultMonitor"
474b828684SBarry Smith /*@C
48f525115eSLois Curfman McInnes    SNESDefaultMonitor - Monitoring progress of the SNES solvers (default).
49e7e93795SLois Curfman McInnes 
50c7afd0dbSLois Curfman McInnes    Collective on SNES
51c7afd0dbSLois Curfman McInnes 
52e7e93795SLois Curfman McInnes    Input Parameters:
53c7afd0dbSLois Curfman McInnes +  snes - the SNES context
54e7e93795SLois Curfman McInnes .  its - iteration number
55e7e93795SLois Curfman McInnes .  fgnorm - 2-norm of residual (or gradient)
56c7afd0dbSLois Curfman McInnes -  dummy - unused context
57fee21e36SBarry Smith 
58e7e93795SLois Curfman McInnes    Notes:
59e7e93795SLois Curfman McInnes    For SNES_NONLINEAR_EQUATIONS methods the routine prints the
60e7e93795SLois Curfman McInnes    residual norm at each iteration.
61e7e93795SLois Curfman McInnes 
62e7e93795SLois Curfman McInnes    For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the
63e7e93795SLois Curfman McInnes    function value and gradient norm at each iteration.
64e7e93795SLois Curfman McInnes 
65e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm
66e7e93795SLois Curfman McInnes 
67e7e93795SLois Curfman McInnes .seealso: SNESSetMonitor()
68e7e93795SLois Curfman McInnes @*/
69e7e93795SLois Curfman McInnes int SNESDefaultMonitor(SNES snes,int its,double fgnorm,void *dummy)
70e7e93795SLois Curfman McInnes {
713a40ed3dSBarry Smith   PetscFunctionBegin;
7276be9ce4SBarry Smith   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
7377c4ece6SBarry Smith     PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);
7476be9ce4SBarry Smith   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
753a40ed3dSBarry Smith     PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);
7676be9ce4SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
773a40ed3dSBarry Smith   PetscFunctionReturn(0);
78e7e93795SLois Curfman McInnes }
79*3f1db9ecSBarry Smith 
80e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
815615d1e5SSatish Balay #undef __FUNC__
82d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultSMonitor"
83be1f7002SBarry Smith /*
84be1f7002SBarry Smith      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
85be1f7002SBarry Smith   it prints fewer digits of the residual as the residual gets smaller.
86be1f7002SBarry Smith   This is because the later digits are meaningless and are often
87be1f7002SBarry Smith   different on different machines; by using this routine different
88be1f7002SBarry Smith   machines will usually generate the same output.
89be1f7002SBarry Smith */
90e7e93795SLois Curfman McInnes int SNESDefaultSMonitor(SNES snes,int its, double fgnorm,void *dummy)
91e7e93795SLois Curfman McInnes {
923a40ed3dSBarry Smith   PetscFunctionBegin;
93e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
948f240d10SBarry Smith     if (fgnorm > 1.e-9) {
95c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);
963a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11){
97c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm %5.3e \n",its,fgnorm);
983a40ed3dSBarry Smith     } else {
99c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm < 1.e-11\n",its);
100e7e93795SLois Curfman McInnes     }
101e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
1028f240d10SBarry Smith     if (fgnorm > 1.e-9) {
10377c4ece6SBarry Smith       PetscPrintf(snes->comm,
1043a40ed3dSBarry Smith        "iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);
1053a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11) {
10677c4ece6SBarry Smith       PetscPrintf(snes->comm,
1073a40ed3dSBarry Smith         "iter = %d, SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);
1083a40ed3dSBarry Smith     } else {
10977c4ece6SBarry Smith       PetscPrintf(snes->comm,
1103a40ed3dSBarry Smith         "iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);
111e7e93795SLois Curfman McInnes     }
112a8c6a408SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
1133a40ed3dSBarry Smith   PetscFunctionReturn(0);
114e7e93795SLois Curfman McInnes }
115e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
1165615d1e5SSatish Balay #undef __FUNC__
1175615d1e5SSatish Balay #define __FUNC__ "SNESConverged_EQ_LS"
1184b828684SBarry Smith /*@C
119f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
120f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
121e7e93795SLois Curfman McInnes 
122c7afd0dbSLois Curfman McInnes    Collective on SNES
123c7afd0dbSLois Curfman McInnes 
124e7e93795SLois Curfman McInnes    Input Parameters:
125c7afd0dbSLois Curfman McInnes +  snes - the SNES context
126e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
127e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
128e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
129c7afd0dbSLois Curfman McInnes -  dummy - unused context
130e7e93795SLois Curfman McInnes 
131e7e93795SLois Curfman McInnes    Returns:
132c7afd0dbSLois Curfman McInnes +  2  - if  ( fnorm < atol ),
133c7afd0dbSLois Curfman McInnes .  3  - if  ( pnorm < xtol*xnorm ),
134c7afd0dbSLois Curfman McInnes .  4  - if  ( fnorm < rtol*fnorm0 ),
135c7afd0dbSLois Curfman McInnes . -2  - if  ( nfct > maxf ),
136c7afd0dbSLois Curfman McInnes -  0  - otherwise,
137e7e93795SLois Curfman McInnes 
138e7e93795SLois Curfman McInnes    where
139c7afd0dbSLois Curfman McInnes +    maxf - maximum number of function evaluations,
140c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
141c7afd0dbSLois Curfman McInnes .    nfct - number of function evaluations,
142c7afd0dbSLois Curfman McInnes .    atol - absolute function norm tolerance,
143c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
144c7afd0dbSLois Curfman McInnes -    rtol - relative function norm tolerance, set with SNESSetTolerances()
145fee21e36SBarry Smith 
146e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
147e7e93795SLois Curfman McInnes 
148e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
149e7e93795SLois Curfman McInnes @*/
15040191667SLois Curfman McInnes int SNESConverged_EQ_LS(SNES snes,double xnorm,double pnorm,double fnorm,void *dummy)
151e7e93795SLois Curfman McInnes {
1523a40ed3dSBarry Smith   PetscFunctionBegin;
153d252947aSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
154a8c6a408SBarry Smith      SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only");
155d252947aSBarry Smith   }
156082acdaeSLois Curfman McInnes   /* Note:  Reserve return code 1, -1 for compatibility with SNESConverged_EQ_TR */
157d252947aSBarry Smith   if (fnorm != fnorm) {
158981c4779SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n");
1593a40ed3dSBarry Smith     PetscFunctionReturn(-3);
160d252947aSBarry Smith   }
1615d2e0e51SBarry Smith   if (fnorm <= snes->ttol) {
16294a424c1SBarry Smith     PLogInfo(snes,
163981c4779SBarry Smith     "SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
1643a40ed3dSBarry Smith     PetscFunctionReturn(4);
1655d2e0e51SBarry Smith   }
1665d2e0e51SBarry Smith 
167e7e93795SLois Curfman McInnes   if (fnorm < snes->atol) {
16894a424c1SBarry Smith     PLogInfo(snes,
169981c4779SBarry Smith       "SNESConverged_EQ_LS: Converged due to function norm %g < %g\n",fnorm,snes->atol);
1703a40ed3dSBarry Smith     PetscFunctionReturn(2);
171e7e93795SLois Curfman McInnes   }
172e7e93795SLois Curfman McInnes   if (pnorm < snes->xtol*(xnorm)) {
17394a424c1SBarry Smith     PLogInfo(snes,
174981c4779SBarry Smith       "SNESConverged_EQ_LS: Converged due to small update length: %g < %g * %g\n",
175e7e93795SLois Curfman McInnes        pnorm,snes->xtol,xnorm);
1763a40ed3dSBarry Smith     PetscFunctionReturn(3);
177e7e93795SLois Curfman McInnes   }
178e7e93795SLois Curfman McInnes   if (snes->nfuncs > snes->max_funcs) {
179981c4779SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS: Exceeded maximum number of function evaluations: %d > %d\n",
180e7e93795SLois Curfman McInnes       snes->nfuncs, snes->max_funcs );
1813a40ed3dSBarry Smith     PetscFunctionReturn(-2);
182e7e93795SLois Curfman McInnes   }
1833a40ed3dSBarry Smith   PetscFunctionReturn(0);
184e7e93795SLois Curfman McInnes }
185e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
1865615d1e5SSatish Balay #undef __FUNC__
1875615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetConvergenceTestEW"
188e7e93795SLois Curfman McInnes /*@
189f525115eSLois Curfman McInnes    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
190e7e93795SLois Curfman McInnes    for the linear solvers within an inexact Newton method.
191e7e93795SLois Curfman McInnes 
192c7afd0dbSLois Curfman McInnes    Collective on SNES
193c7afd0dbSLois Curfman McInnes 
194e7e93795SLois Curfman McInnes    Input Parameter:
195e7e93795SLois Curfman McInnes .  snes - SNES context
196e7e93795SLois Curfman McInnes 
197e7e93795SLois Curfman McInnes    Notes:
198e7e93795SLois Curfman McInnes    Currently, the default is to use a constant relative tolerance for
199e7e93795SLois Curfman McInnes    the inner linear solvers.  Alternatively, one can use the
200e7e93795SLois Curfman McInnes    Eisenstat-Walker method, where the relative convergence tolerance
201e7e93795SLois Curfman McInnes    is reset at each Newton iteration according progress of the nonlinear
202e7e93795SLois Curfman McInnes    solver.
203e7e93795SLois Curfman McInnes 
204e7e93795SLois Curfman McInnes    Reference:
205e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
206e30ad881SLois Curfman McInnes    inexact Newton method", SISC 17 (1), pp.16-32, 1996.
207e7e93795SLois Curfman McInnes 
208e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
209e7e93795SLois Curfman McInnes @*/
210e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes)
211e7e93795SLois Curfman McInnes {
2123a40ed3dSBarry Smith   PetscFunctionBegin;
213e7e93795SLois Curfman McInnes   snes->ksp_ewconv = 1;
2143a40ed3dSBarry Smith   PetscFunctionReturn(0);
215e7e93795SLois Curfman McInnes }
216e7e93795SLois Curfman McInnes 
2175615d1e5SSatish Balay #undef __FUNC__
2185615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetParametersEW"
219e7e93795SLois Curfman McInnes /*@
220e7e93795SLois Curfman McInnes    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
221e7e93795SLois Curfman McInnes    convergence criteria for the linear solvers within an inexact
222e7e93795SLois Curfman McInnes    Newton method.
223e7e93795SLois Curfman McInnes 
224c7afd0dbSLois Curfman McInnes    Collective on SNES
225c7afd0dbSLois Curfman McInnes 
226e7e93795SLois Curfman McInnes    Input Parameters:
227c7afd0dbSLois Curfman McInnes +    snes - SNES context
228e7e93795SLois Curfman McInnes .    version - version 1 or 2 (default is 2)
229c7afd0dbSLois Curfman McInnes .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
230c7afd0dbSLois Curfman McInnes .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
231c7afd0dbSLois Curfman McInnes .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
232e7e93795SLois Curfman McInnes .    alpha2 - power for safeguard
233e7e93795SLois Curfman McInnes .    gamma2 - multiplicative factor for version 2 rtol computation
234c7afd0dbSLois Curfman McInnes               (0 <= gamma2 <= 1)
235c7afd0dbSLois Curfman McInnes -    threshold - threshold for imposing safeguard (0 < threshold < 1)
236fee21e36SBarry Smith 
237e7e93795SLois Curfman McInnes    Note:
238e7e93795SLois Curfman McInnes    Use PETSC_DEFAULT to retain the default for any of the parameters.
239e7e93795SLois Curfman McInnes 
240e7e93795SLois Curfman McInnes    Reference:
241e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
242e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
243e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
244e7e93795SLois Curfman McInnes 
245e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
246e7e93795SLois Curfman McInnes 
247e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW()
248e7e93795SLois Curfman McInnes @*/
249e7e93795SLois Curfman McInnes int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0,
250e7e93795SLois Curfman McInnes                              double rtol_max,double gamma2,double alpha,
251e7e93795SLois Curfman McInnes                              double alpha2,double threshold)
252e7e93795SLois Curfman McInnes {
253e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
2543a40ed3dSBarry Smith 
2553a40ed3dSBarry Smith   PetscFunctionBegin;
256a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context existing");
257e7e93795SLois Curfman McInnes   if (version != PETSC_DEFAULT)   kctx->version = version;
258e7e93795SLois Curfman McInnes   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0 = rtol_0;
259e7e93795SLois Curfman McInnes   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max = rtol_max;
260e7e93795SLois Curfman McInnes   if (gamma2 != PETSC_DEFAULT)    kctx->gamma = gamma2;
261e7e93795SLois Curfman McInnes   if (alpha != PETSC_DEFAULT)     kctx->alpha = alpha;
262e7e93795SLois Curfman McInnes   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2 = alpha2;
263e7e93795SLois Curfman McInnes   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
264a8c6a408SBarry Smith   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
265a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_0 < 1.0\n");
266a8c6a408SBarry Smith   }
267a8c6a408SBarry Smith   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
268a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_max < 1.0\n");
269a8c6a408SBarry Smith   }
270a8c6a408SBarry Smith   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
271a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 < threshold < 1.0\n");
272a8c6a408SBarry Smith   }
273a8c6a408SBarry Smith   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
274a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= alpha <= 1.0\n");
275a8c6a408SBarry Smith   }
276a8c6a408SBarry Smith   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
277a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"1.0 < alpha <= 2.0\n");
278a8c6a408SBarry Smith   }
279a8c6a408SBarry Smith   if (kctx->version != 1 && kctx->version !=2) {
280a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 and 2 are supported");
281a8c6a408SBarry Smith   }
2823a40ed3dSBarry Smith   PetscFunctionReturn(0);
283e7e93795SLois Curfman McInnes }
284e7e93795SLois Curfman McInnes 
2855615d1e5SSatish Balay #undef __FUNC__
2865615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_ComputeRelativeTolerance_Private"
287e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
288e7e93795SLois Curfman McInnes {
289e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
290*3f1db9ecSBarry Smith   double              rtol = 0.0, stol;
291e7e93795SLois Curfman McInnes   int                 ierr;
2923a40ed3dSBarry Smith 
2933a40ed3dSBarry Smith   PetscFunctionBegin;
294a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context exists");
295e7e93795SLois Curfman McInnes   if (snes->iter == 1) {
296e7e93795SLois Curfman McInnes     rtol = kctx->rtol_0;
297e7e93795SLois Curfman McInnes   } else {
298e7e93795SLois Curfman McInnes     if (kctx->version == 1) {
299e7e93795SLois Curfman McInnes       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
300e7e93795SLois Curfman McInnes       if (rtol < 0.0) rtol = -rtol;
301e7e93795SLois Curfman McInnes       stol = pow(kctx->rtol_last,kctx->alpha2);
3020452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
303e7e93795SLois Curfman McInnes     } else if (kctx->version == 2) {
304e7e93795SLois Curfman McInnes       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
305e7e93795SLois Curfman McInnes       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
3060452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
307a8c6a408SBarry Smith     } else SETERRQ( PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 or 2 are supported");
308e7e93795SLois Curfman McInnes   }
3090452661fSBarry Smith   rtol = PetscMin(rtol,kctx->rtol_max);
310e7e93795SLois Curfman McInnes   kctx->rtol_last = rtol;
311981c4779SBarry Smith   PLogInfo(snes,"SNESConverged_EQ_LS: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",
312e7e93795SLois Curfman McInnes            snes->iter,kctx->version,rtol);
3133131a8b6SLois Curfman McInnes   ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); CHKERRQ(ierr);
314e7e93795SLois Curfman McInnes   kctx->norm_last = snes->norm;
3153a40ed3dSBarry Smith   PetscFunctionReturn(0);
316e7e93795SLois Curfman McInnes }
317e7e93795SLois Curfman McInnes 
3185615d1e5SSatish Balay #undef __FUNC__
3195615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_Converged_Private"
320e7e93795SLois Curfman McInnes int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx)
321e7e93795SLois Curfman McInnes {
322e7e93795SLois Curfman McInnes   SNES                snes = (SNES)ctx;
323e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
324e7e93795SLois Curfman McInnes   int                 convinfo;
325e7e93795SLois Curfman McInnes 
3263a40ed3dSBarry Smith   PetscFunctionBegin;
327a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context set");
328e7e93795SLois Curfman McInnes   if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);
329e7e93795SLois Curfman McInnes   convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx);
330e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
3313a40ed3dSBarry Smith   if (convinfo) {
332981c4779SBarry Smith     PLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm);
3333a40ed3dSBarry Smith   }
3343a40ed3dSBarry Smith   PetscFunctionReturn(convinfo);
335e7e93795SLois Curfman McInnes }
336e7e93795SLois Curfman McInnes 
337e7e93795SLois Curfman McInnes 
338