xref: /petsc/src/snes/interface/snesut.c (revision 15091d3721b14bd18f7efa625bb8738e103dca31)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*15091d37SBarry Smith static char vcid[] = "$Id: snesut.c,v 1.44 1999/02/01 03:22:39 curfman 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__
83f1db9ecSBarry Smith #define __FUNC__ "SNESVecViewMonitor"
93f1db9ecSBarry Smith /*@C
1036851e7fSLois Curfman McInnes    SNESVecViewMonitor - Monitors progress of the SNES solvers by calling
1136851e7fSLois Curfman McInnes    VecView() for the approximate solution at each iteration.
123f1db9ecSBarry Smith 
133f1db9ecSBarry Smith    Collective on SNES
143f1db9ecSBarry Smith 
153f1db9ecSBarry Smith    Input Parameters:
163f1db9ecSBarry Smith +  snes - the SNES context
173f1db9ecSBarry Smith .  its - iteration number
183f1db9ecSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
193f1db9ecSBarry Smith -  dummy - either a viewer or PETSC_NULL
203f1db9ecSBarry Smith 
2136851e7fSLois Curfman McInnes    Level: intermediate
223f1db9ecSBarry Smith 
2336851e7fSLois Curfman McInnes .keywords: SNES, nonlinear, vector, monitor, view
243f1db9ecSBarry Smith 
2536851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
263f1db9ecSBarry Smith @*/
273f1db9ecSBarry Smith int SNESVecViewMonitor(SNES snes,int its,double fgnorm,void *dummy)
283f1db9ecSBarry Smith {
293f1db9ecSBarry Smith   int    ierr;
303f1db9ecSBarry Smith   Vec    x;
313f1db9ecSBarry Smith   Viewer viewer = (Viewer) dummy;
323f1db9ecSBarry Smith 
333f1db9ecSBarry Smith   PetscFunctionBegin;
343f1db9ecSBarry Smith   ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr);
353f1db9ecSBarry Smith   if (!viewer) {
363f1db9ecSBarry Smith     MPI_Comm comm;
373f1db9ecSBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
38c655490fSBarry Smith     viewer = VIEWER_DRAW_(comm);
393f1db9ecSBarry Smith   }
403f1db9ecSBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
413f1db9ecSBarry Smith 
423f1db9ecSBarry Smith   PetscFunctionReturn(0);
433f1db9ecSBarry Smith }
443f1db9ecSBarry Smith 
453f1db9ecSBarry 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 
6536851e7fSLois Curfman McInnes    Level: intermediate
6636851e7fSLois Curfman McInnes 
67e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm
68e7e93795SLois Curfman McInnes 
6936851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESVecViewMonitor()
70e7e93795SLois Curfman McInnes @*/
71e7e93795SLois Curfman McInnes int SNESDefaultMonitor(SNES snes,int its,double fgnorm,void *dummy)
72e7e93795SLois Curfman McInnes {
733a40ed3dSBarry Smith   PetscFunctionBegin;
7476be9ce4SBarry Smith   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
7577c4ece6SBarry Smith     PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);
7676be9ce4SBarry Smith   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
773a40ed3dSBarry Smith     PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);
7876be9ce4SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
793a40ed3dSBarry Smith   PetscFunctionReturn(0);
80e7e93795SLois Curfman McInnes }
813f1db9ecSBarry Smith 
82e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
835615d1e5SSatish Balay #undef __FUNC__
84d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultSMonitor"
85be1f7002SBarry Smith /*
86be1f7002SBarry Smith      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
87be1f7002SBarry Smith   it prints fewer digits of the residual as the residual gets smaller.
88be1f7002SBarry Smith   This is because the later digits are meaningless and are often
89be1f7002SBarry Smith   different on different machines; by using this routine different
90be1f7002SBarry Smith   machines will usually generate the same output.
91be1f7002SBarry Smith */
92e7e93795SLois Curfman McInnes int SNESDefaultSMonitor(SNES snes,int its, double fgnorm,void *dummy)
93e7e93795SLois Curfman McInnes {
943a40ed3dSBarry Smith   PetscFunctionBegin;
95e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
968f240d10SBarry Smith     if (fgnorm > 1.e-9) {
97c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);
983a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11){
99c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm %5.3e \n",its,fgnorm);
1003a40ed3dSBarry Smith     } else {
101c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm < 1.e-11\n",its);
102e7e93795SLois Curfman McInnes     }
103e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
1048f240d10SBarry Smith     if (fgnorm > 1.e-9) {
10577c4ece6SBarry Smith       PetscPrintf(snes->comm,
1063a40ed3dSBarry Smith        "iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);
1073a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11) {
10877c4ece6SBarry Smith       PetscPrintf(snes->comm,
1093a40ed3dSBarry Smith         "iter = %d, SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);
1103a40ed3dSBarry Smith     } else {
11177c4ece6SBarry Smith       PetscPrintf(snes->comm,
1123a40ed3dSBarry Smith         "iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);
113e7e93795SLois Curfman McInnes     }
114a8c6a408SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
1153a40ed3dSBarry Smith   PetscFunctionReturn(0);
116e7e93795SLois Curfman McInnes }
117e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
1185615d1e5SSatish Balay #undef __FUNC__
1195615d1e5SSatish Balay #define __FUNC__ "SNESConverged_EQ_LS"
1204b828684SBarry Smith /*@C
121f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
122f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
123e7e93795SLois Curfman McInnes 
124c7afd0dbSLois Curfman McInnes    Collective on SNES
125c7afd0dbSLois Curfman McInnes 
126e7e93795SLois Curfman McInnes    Input Parameters:
127c7afd0dbSLois Curfman McInnes +  snes - the SNES context
128e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
129e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
130e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
131c7afd0dbSLois Curfman McInnes -  dummy - unused context
132e7e93795SLois Curfman McInnes 
133e7e93795SLois Curfman McInnes    Returns:
134c7afd0dbSLois Curfman McInnes +  2  - if  ( fnorm < atol ),
135c7afd0dbSLois Curfman McInnes .  3  - if  ( pnorm < xtol*xnorm ),
136c7afd0dbSLois Curfman McInnes .  4  - if  ( fnorm < rtol*fnorm0 ),
137c7afd0dbSLois Curfman McInnes . -2  - if  ( nfct > maxf ),
138c7afd0dbSLois Curfman McInnes -  0  - otherwise,
139e7e93795SLois Curfman McInnes 
140e7e93795SLois Curfman McInnes    where
141c7afd0dbSLois Curfman McInnes +    maxf - maximum number of function evaluations,
142c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
143c7afd0dbSLois Curfman McInnes .    nfct - number of function evaluations,
144c7afd0dbSLois Curfman McInnes .    atol - absolute function norm tolerance,
145c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
146c7afd0dbSLois Curfman McInnes -    rtol - relative function norm tolerance, set with SNESSetTolerances()
147fee21e36SBarry Smith 
14836851e7fSLois Curfman McInnes    Level: intermediate
14936851e7fSLois Curfman McInnes 
150e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
151e7e93795SLois Curfman McInnes 
152e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
153e7e93795SLois Curfman McInnes @*/
15440191667SLois Curfman McInnes int SNESConverged_EQ_LS(SNES snes,double xnorm,double pnorm,double fnorm,void *dummy)
155e7e93795SLois Curfman McInnes {
1563a40ed3dSBarry Smith   PetscFunctionBegin;
157d252947aSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
158a8c6a408SBarry Smith      SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only");
159d252947aSBarry Smith   }
160082acdaeSLois Curfman McInnes   /* Note:  Reserve return code 1, -1 for compatibility with SNESConverged_EQ_TR */
161d252947aSBarry Smith   if (fnorm != fnorm) {
162981c4779SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n");
1633a40ed3dSBarry Smith     PetscFunctionReturn(-3);
164d252947aSBarry Smith   }
1655d2e0e51SBarry Smith   if (fnorm <= snes->ttol) {
166*15091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
1673a40ed3dSBarry Smith     PetscFunctionReturn(4);
1685d2e0e51SBarry Smith   }
1695d2e0e51SBarry Smith 
170e7e93795SLois Curfman McInnes   if (fnorm < snes->atol) {
171*15091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol);
1723a40ed3dSBarry Smith     PetscFunctionReturn(2);
173e7e93795SLois Curfman McInnes   }
174e7e93795SLois Curfman McInnes   if (pnorm < snes->xtol*(xnorm)) {
175*15091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm);
1763a40ed3dSBarry Smith     PetscFunctionReturn(3);
177e7e93795SLois Curfman McInnes   }
178e7e93795SLois Curfman McInnes   if (snes->nfuncs > snes->max_funcs) {
179*15091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs, snes->max_funcs);
1803a40ed3dSBarry Smith     PetscFunctionReturn(-2);
181e7e93795SLois Curfman McInnes   }
1823a40ed3dSBarry Smith   PetscFunctionReturn(0);
183e7e93795SLois Curfman McInnes }
184e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
1855615d1e5SSatish Balay #undef __FUNC__
1865615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetConvergenceTestEW"
187e7e93795SLois Curfman McInnes /*@
188f525115eSLois Curfman McInnes    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
189e7e93795SLois Curfman McInnes    for the linear solvers within an inexact Newton method.
190e7e93795SLois Curfman McInnes 
191c7afd0dbSLois Curfman McInnes    Collective on SNES
192c7afd0dbSLois Curfman McInnes 
193e7e93795SLois Curfman McInnes    Input Parameter:
194e7e93795SLois Curfman McInnes .  snes - SNES context
195e7e93795SLois Curfman McInnes 
196e7e93795SLois Curfman McInnes    Notes:
197e7e93795SLois Curfman McInnes    Currently, the default is to use a constant relative tolerance for
198e7e93795SLois Curfman McInnes    the inner linear solvers.  Alternatively, one can use the
199e7e93795SLois Curfman McInnes    Eisenstat-Walker method, where the relative convergence tolerance
200e7e93795SLois Curfman McInnes    is reset at each Newton iteration according progress of the nonlinear
201e7e93795SLois Curfman McInnes    solver.
202e7e93795SLois Curfman McInnes 
20336851e7fSLois Curfman McInnes    Level: advanced
20436851e7fSLois Curfman McInnes 
205e7e93795SLois Curfman McInnes    Reference:
206e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
207e30ad881SLois Curfman McInnes    inexact Newton method", SISC 17 (1), pp.16-32, 1996.
208e7e93795SLois Curfman McInnes 
209e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
210e7e93795SLois Curfman McInnes @*/
211e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes)
212e7e93795SLois Curfman McInnes {
2133a40ed3dSBarry Smith   PetscFunctionBegin;
214e7e93795SLois Curfman McInnes   snes->ksp_ewconv = 1;
2153a40ed3dSBarry Smith   PetscFunctionReturn(0);
216e7e93795SLois Curfman McInnes }
217e7e93795SLois Curfman McInnes 
2185615d1e5SSatish Balay #undef __FUNC__
2195615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetParametersEW"
220e7e93795SLois Curfman McInnes /*@
221e7e93795SLois Curfman McInnes    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
222e7e93795SLois Curfman McInnes    convergence criteria for the linear solvers within an inexact
223e7e93795SLois Curfman McInnes    Newton method.
224e7e93795SLois Curfman McInnes 
225c7afd0dbSLois Curfman McInnes    Collective on SNES
226c7afd0dbSLois Curfman McInnes 
227e7e93795SLois Curfman McInnes    Input Parameters:
228c7afd0dbSLois Curfman McInnes +    snes - SNES context
229e7e93795SLois Curfman McInnes .    version - version 1 or 2 (default is 2)
230c7afd0dbSLois Curfman McInnes .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
231c7afd0dbSLois Curfman McInnes .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
232c7afd0dbSLois Curfman McInnes .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
233e7e93795SLois Curfman McInnes .    alpha2 - power for safeguard
234e7e93795SLois Curfman McInnes .    gamma2 - multiplicative factor for version 2 rtol computation
235c7afd0dbSLois Curfman McInnes               (0 <= gamma2 <= 1)
236c7afd0dbSLois Curfman McInnes -    threshold - threshold for imposing safeguard (0 < threshold < 1)
237fee21e36SBarry Smith 
238e7e93795SLois Curfman McInnes    Note:
239e7e93795SLois Curfman McInnes    Use PETSC_DEFAULT to retain the default for any of the parameters.
240e7e93795SLois Curfman McInnes 
24136851e7fSLois Curfman McInnes    Level: advanced
24236851e7fSLois Curfman McInnes 
243e7e93795SLois Curfman McInnes    Reference:
244e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
245e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
246e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
247e7e93795SLois Curfman McInnes 
248e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
249e7e93795SLois Curfman McInnes 
250e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW()
251e7e93795SLois Curfman McInnes @*/
252e7e93795SLois Curfman McInnes int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0,
253e7e93795SLois Curfman McInnes                              double rtol_max,double gamma2,double alpha,
254e7e93795SLois Curfman McInnes                              double alpha2,double threshold)
255e7e93795SLois Curfman McInnes {
256e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
2573a40ed3dSBarry Smith 
2583a40ed3dSBarry Smith   PetscFunctionBegin;
259a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context existing");
260e7e93795SLois Curfman McInnes   if (version != PETSC_DEFAULT)   kctx->version   = version;
261e7e93795SLois Curfman McInnes   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0    = rtol_0;
262e7e93795SLois Curfman McInnes   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max  = rtol_max;
263e7e93795SLois Curfman McInnes   if (gamma2 != PETSC_DEFAULT)    kctx->gamma     = gamma2;
264e7e93795SLois Curfman McInnes   if (alpha != PETSC_DEFAULT)     kctx->alpha     = alpha;
265e7e93795SLois Curfman McInnes   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2    = alpha2;
266e7e93795SLois Curfman McInnes   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
267a8c6a408SBarry Smith   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
268596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0);
269a8c6a408SBarry Smith   }
270a8c6a408SBarry Smith   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
271596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_max < 1.0\n",kctx->rtol_max);
272a8c6a408SBarry Smith   }
273a8c6a408SBarry Smith   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
274596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 < threshold < 1.0\n",kctx->threshold);
275a8c6a408SBarry Smith   }
276a8c6a408SBarry Smith   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
277596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= alpha <= 1.0\n",kctx->gamma);
278a8c6a408SBarry Smith   }
279a8c6a408SBarry Smith   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
280596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"1.0 < alpha <= 2.0\n",kctx->alpha);
281a8c6a408SBarry Smith   }
282a8c6a408SBarry Smith   if (kctx->version != 1 && kctx->version !=2) {
283596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 and 2 are supported: %d",kctx->version);
284a8c6a408SBarry Smith   }
2853a40ed3dSBarry Smith   PetscFunctionReturn(0);
286e7e93795SLois Curfman McInnes }
287e7e93795SLois Curfman McInnes 
2885615d1e5SSatish Balay #undef __FUNC__
2895615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_ComputeRelativeTolerance_Private"
290e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
291e7e93795SLois Curfman McInnes {
292e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
2933f1db9ecSBarry Smith   double              rtol = 0.0, stol;
294e7e93795SLois Curfman McInnes   int                 ierr;
2953a40ed3dSBarry Smith 
2963a40ed3dSBarry Smith   PetscFunctionBegin;
297a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context exists");
298e7e93795SLois Curfman McInnes   if (snes->iter == 1) {
299e7e93795SLois Curfman McInnes     rtol = kctx->rtol_0;
300e7e93795SLois Curfman McInnes   } else {
301e7e93795SLois Curfman McInnes     if (kctx->version == 1) {
302e7e93795SLois Curfman McInnes       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
303e7e93795SLois Curfman McInnes       if (rtol < 0.0) rtol = -rtol;
304e7e93795SLois Curfman McInnes       stol = pow(kctx->rtol_last,kctx->alpha2);
3050452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
306e7e93795SLois Curfman McInnes     } else if (kctx->version == 2) {
307e7e93795SLois Curfman McInnes       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
308e7e93795SLois Curfman McInnes       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
3090452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
310596552b5SBarry Smith     } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 or 2 are supported: %d",kctx->version);
311e7e93795SLois Curfman McInnes   }
3120452661fSBarry Smith   rtol = PetscMin(rtol,kctx->rtol_max);
313e7e93795SLois Curfman McInnes   kctx->rtol_last = rtol;
314596552b5SBarry Smith   PLogInfo(snes,"SNESConverged_EQ_LS: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol);
3153131a8b6SLois Curfman McInnes   ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); CHKERRQ(ierr);
316e7e93795SLois Curfman McInnes   kctx->norm_last = snes->norm;
3173a40ed3dSBarry Smith   PetscFunctionReturn(0);
318e7e93795SLois Curfman McInnes }
319e7e93795SLois Curfman McInnes 
3205615d1e5SSatish Balay #undef __FUNC__
3215615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_Converged_Private"
322e7e93795SLois Curfman McInnes int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx)
323e7e93795SLois Curfman McInnes {
324e7e93795SLois Curfman McInnes   SNES                snes = (SNES)ctx;
325e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
326e7e93795SLois Curfman McInnes   int                 convinfo;
327e7e93795SLois Curfman McInnes 
3283a40ed3dSBarry Smith   PetscFunctionBegin;
329a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context set");
330e7e93795SLois Curfman McInnes   if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);
331e7e93795SLois Curfman McInnes   convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx);
332e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
3333a40ed3dSBarry Smith   if (convinfo) {
334981c4779SBarry Smith     PLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm);
3353a40ed3dSBarry Smith   }
3363a40ed3dSBarry Smith   PetscFunctionReturn(convinfo);
337e7e93795SLois Curfman McInnes }
338e7e93795SLois Curfman McInnes 
339e7e93795SLois Curfman McInnes 
340