xref: /petsc/src/snes/interface/snesut.c (revision d132466e10dddff923c4add9c18d7fc5c6003d46)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*d132466eSBarry Smith static char vcid[] = "$Id: snesut.c,v 1.45 1999/03/17 23:24:18 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__
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__
46*d132466eSBarry Smith #define __FUNC__ "SNESVecViewMonitorUpdate"
47*d132466eSBarry Smith /*@C
48*d132466eSBarry Smith    SNESVecViewMonitorUpdate - Monitors progress of the SNES solvers by calling
49*d132466eSBarry Smith    VecView() for the UPDATE to the solution at each iteration.
50*d132466eSBarry Smith 
51*d132466eSBarry Smith    Collective on SNES
52*d132466eSBarry Smith 
53*d132466eSBarry Smith    Input Parameters:
54*d132466eSBarry Smith +  snes - the SNES context
55*d132466eSBarry Smith .  its - iteration number
56*d132466eSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
57*d132466eSBarry Smith -  dummy - either a viewer or PETSC_NULL
58*d132466eSBarry Smith 
59*d132466eSBarry Smith    Level: intermediate
60*d132466eSBarry Smith 
61*d132466eSBarry Smith .keywords: SNES, nonlinear, vector, monitor, view
62*d132466eSBarry Smith 
63*d132466eSBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
64*d132466eSBarry Smith @*/
65*d132466eSBarry Smith int SNESVecViewMonitorUpdate(SNES snes,int its,double fgnorm,void *dummy)
66*d132466eSBarry Smith {
67*d132466eSBarry Smith   int    ierr;
68*d132466eSBarry Smith   Vec    x;
69*d132466eSBarry Smith   Viewer viewer = (Viewer) dummy;
70*d132466eSBarry Smith 
71*d132466eSBarry Smith   PetscFunctionBegin;
72*d132466eSBarry Smith   ierr = SNESGetSolutionUpdate(snes,&x);CHKERRQ(ierr);
73*d132466eSBarry Smith   if (!viewer) {
74*d132466eSBarry Smith     MPI_Comm comm;
75*d132466eSBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
76*d132466eSBarry Smith     viewer = VIEWER_DRAW_(comm);
77*d132466eSBarry Smith   }
78*d132466eSBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
79*d132466eSBarry Smith 
80*d132466eSBarry Smith   PetscFunctionReturn(0);
81*d132466eSBarry Smith }
82*d132466eSBarry Smith 
83*d132466eSBarry Smith #undef __FUNC__
84d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultMonitor"
854b828684SBarry Smith /*@C
86f525115eSLois Curfman McInnes    SNESDefaultMonitor - Monitoring progress of the SNES solvers (default).
87e7e93795SLois Curfman McInnes 
88c7afd0dbSLois Curfman McInnes    Collective on SNES
89c7afd0dbSLois Curfman McInnes 
90e7e93795SLois Curfman McInnes    Input Parameters:
91c7afd0dbSLois Curfman McInnes +  snes - the SNES context
92e7e93795SLois Curfman McInnes .  its - iteration number
93e7e93795SLois Curfman McInnes .  fgnorm - 2-norm of residual (or gradient)
94c7afd0dbSLois Curfman McInnes -  dummy - unused context
95fee21e36SBarry Smith 
96e7e93795SLois Curfman McInnes    Notes:
97e7e93795SLois Curfman McInnes    For SNES_NONLINEAR_EQUATIONS methods the routine prints the
98e7e93795SLois Curfman McInnes    residual norm at each iteration.
99e7e93795SLois Curfman McInnes 
100e7e93795SLois Curfman McInnes    For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the
101e7e93795SLois Curfman McInnes    function value and gradient norm at each iteration.
102e7e93795SLois Curfman McInnes 
10336851e7fSLois Curfman McInnes    Level: intermediate
10436851e7fSLois Curfman McInnes 
105e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm
106e7e93795SLois Curfman McInnes 
10736851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESVecViewMonitor()
108e7e93795SLois Curfman McInnes @*/
109e7e93795SLois Curfman McInnes int SNESDefaultMonitor(SNES snes,int its,double fgnorm,void *dummy)
110e7e93795SLois Curfman McInnes {
111*d132466eSBarry Smith   int ierr;
112*d132466eSBarry Smith 
1133a40ed3dSBarry Smith   PetscFunctionBegin;
11476be9ce4SBarry Smith   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
115*d132466eSBarry Smith     ierr = PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr);
11676be9ce4SBarry Smith   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
117*d132466eSBarry Smith     ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
11876be9ce4SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
1193a40ed3dSBarry Smith   PetscFunctionReturn(0);
120e7e93795SLois Curfman McInnes }
1213f1db9ecSBarry Smith 
122e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
1235615d1e5SSatish Balay #undef __FUNC__
124d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultSMonitor"
125be1f7002SBarry Smith /*
126be1f7002SBarry Smith      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
127be1f7002SBarry Smith   it prints fewer digits of the residual as the residual gets smaller.
128be1f7002SBarry Smith   This is because the later digits are meaningless and are often
129be1f7002SBarry Smith   different on different machines; by using this routine different
130be1f7002SBarry Smith   machines will usually generate the same output.
131be1f7002SBarry Smith */
132e7e93795SLois Curfman McInnes int SNESDefaultSMonitor(SNES snes,int its, double fgnorm,void *dummy)
133e7e93795SLois Curfman McInnes {
134*d132466eSBarry Smith   int ierr;
135*d132466eSBarry Smith 
1363a40ed3dSBarry Smith   PetscFunctionBegin;
137e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
1388f240d10SBarry Smith     if (fgnorm > 1.e-9) {
139*d132466eSBarry Smith       ierr = PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr);
1403a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11){
141*d132466eSBarry Smith       ierr = PetscPrintf(snes->comm, "iter = %d, SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr);
1423a40ed3dSBarry Smith     } else {
143*d132466eSBarry Smith       ierr = PetscPrintf(snes->comm, "iter = %d, SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr);
144e7e93795SLois Curfman McInnes     }
145e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
1468f240d10SBarry Smith     if (fgnorm > 1.e-9) {
147*d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
1483a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11) {
149*d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
1503a40ed3dSBarry Smith     } else {
151*d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);CHKERRQ(ierr);
152e7e93795SLois Curfman McInnes     }
153a8c6a408SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
1543a40ed3dSBarry Smith   PetscFunctionReturn(0);
155e7e93795SLois Curfman McInnes }
156e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
1575615d1e5SSatish Balay #undef __FUNC__
1585615d1e5SSatish Balay #define __FUNC__ "SNESConverged_EQ_LS"
1594b828684SBarry Smith /*@C
160f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
161f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
162e7e93795SLois Curfman McInnes 
163c7afd0dbSLois Curfman McInnes    Collective on SNES
164c7afd0dbSLois Curfman McInnes 
165e7e93795SLois Curfman McInnes    Input Parameters:
166c7afd0dbSLois Curfman McInnes +  snes - the SNES context
167e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
168e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
169e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
170c7afd0dbSLois Curfman McInnes -  dummy - unused context
171e7e93795SLois Curfman McInnes 
172e7e93795SLois Curfman McInnes    Returns:
173c7afd0dbSLois Curfman McInnes +  2  - if  ( fnorm < atol ),
174c7afd0dbSLois Curfman McInnes .  3  - if  ( pnorm < xtol*xnorm ),
175c7afd0dbSLois Curfman McInnes .  4  - if  ( fnorm < rtol*fnorm0 ),
176c7afd0dbSLois Curfman McInnes . -2  - if  ( nfct > maxf ),
177c7afd0dbSLois Curfman McInnes -  0  - otherwise,
178e7e93795SLois Curfman McInnes 
179e7e93795SLois Curfman McInnes    where
180c7afd0dbSLois Curfman McInnes +    maxf - maximum number of function evaluations,
181c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
182c7afd0dbSLois Curfman McInnes .    nfct - number of function evaluations,
183c7afd0dbSLois Curfman McInnes .    atol - absolute function norm tolerance,
184c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
185c7afd0dbSLois Curfman McInnes -    rtol - relative function norm tolerance, set with SNESSetTolerances()
186fee21e36SBarry Smith 
18736851e7fSLois Curfman McInnes    Level: intermediate
18836851e7fSLois Curfman McInnes 
189e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
190e7e93795SLois Curfman McInnes 
191e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
192e7e93795SLois Curfman McInnes @*/
19340191667SLois Curfman McInnes int SNESConverged_EQ_LS(SNES snes,double xnorm,double pnorm,double fnorm,void *dummy)
194e7e93795SLois Curfman McInnes {
1953a40ed3dSBarry Smith   PetscFunctionBegin;
196d252947aSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
197a8c6a408SBarry Smith      SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only");
198d252947aSBarry Smith   }
199082acdaeSLois Curfman McInnes   /* Note:  Reserve return code 1, -1 for compatibility with SNESConverged_EQ_TR */
200d252947aSBarry Smith   if (fnorm != fnorm) {
201981c4779SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n");
2023a40ed3dSBarry Smith     PetscFunctionReturn(-3);
203d252947aSBarry Smith   }
2045d2e0e51SBarry Smith   if (fnorm <= snes->ttol) {
20515091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
2063a40ed3dSBarry Smith     PetscFunctionReturn(4);
2075d2e0e51SBarry Smith   }
2085d2e0e51SBarry Smith 
209e7e93795SLois Curfman McInnes   if (fnorm < snes->atol) {
21015091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol);
2113a40ed3dSBarry Smith     PetscFunctionReturn(2);
212e7e93795SLois Curfman McInnes   }
213e7e93795SLois Curfman McInnes   if (pnorm < snes->xtol*(xnorm)) {
21415091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm);
2153a40ed3dSBarry Smith     PetscFunctionReturn(3);
216e7e93795SLois Curfman McInnes   }
217e7e93795SLois Curfman McInnes   if (snes->nfuncs > snes->max_funcs) {
21815091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs, snes->max_funcs);
2193a40ed3dSBarry Smith     PetscFunctionReturn(-2);
220e7e93795SLois Curfman McInnes   }
2213a40ed3dSBarry Smith   PetscFunctionReturn(0);
222e7e93795SLois Curfman McInnes }
223e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
2245615d1e5SSatish Balay #undef __FUNC__
2255615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetConvergenceTestEW"
226e7e93795SLois Curfman McInnes /*@
227f525115eSLois Curfman McInnes    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
228e7e93795SLois Curfman McInnes    for the linear solvers within an inexact Newton method.
229e7e93795SLois Curfman McInnes 
230c7afd0dbSLois Curfman McInnes    Collective on SNES
231c7afd0dbSLois Curfman McInnes 
232e7e93795SLois Curfman McInnes    Input Parameter:
233e7e93795SLois Curfman McInnes .  snes - SNES context
234e7e93795SLois Curfman McInnes 
235e7e93795SLois Curfman McInnes    Notes:
236e7e93795SLois Curfman McInnes    Currently, the default is to use a constant relative tolerance for
237e7e93795SLois Curfman McInnes    the inner linear solvers.  Alternatively, one can use the
238e7e93795SLois Curfman McInnes    Eisenstat-Walker method, where the relative convergence tolerance
239e7e93795SLois Curfman McInnes    is reset at each Newton iteration according progress of the nonlinear
240e7e93795SLois Curfman McInnes    solver.
241e7e93795SLois Curfman McInnes 
24236851e7fSLois Curfman McInnes    Level: advanced
24336851e7fSLois Curfman McInnes 
244e7e93795SLois Curfman McInnes    Reference:
245e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
246e30ad881SLois Curfman McInnes    inexact Newton method", SISC 17 (1), pp.16-32, 1996.
247e7e93795SLois Curfman McInnes 
248e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
249e7e93795SLois Curfman McInnes @*/
250e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes)
251e7e93795SLois Curfman McInnes {
2523a40ed3dSBarry Smith   PetscFunctionBegin;
253e7e93795SLois Curfman McInnes   snes->ksp_ewconv = 1;
2543a40ed3dSBarry Smith   PetscFunctionReturn(0);
255e7e93795SLois Curfman McInnes }
256e7e93795SLois Curfman McInnes 
2575615d1e5SSatish Balay #undef __FUNC__
2585615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetParametersEW"
259e7e93795SLois Curfman McInnes /*@
260e7e93795SLois Curfman McInnes    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
261e7e93795SLois Curfman McInnes    convergence criteria for the linear solvers within an inexact
262e7e93795SLois Curfman McInnes    Newton method.
263e7e93795SLois Curfman McInnes 
264c7afd0dbSLois Curfman McInnes    Collective on SNES
265c7afd0dbSLois Curfman McInnes 
266e7e93795SLois Curfman McInnes    Input Parameters:
267c7afd0dbSLois Curfman McInnes +    snes - SNES context
268e7e93795SLois Curfman McInnes .    version - version 1 or 2 (default is 2)
269c7afd0dbSLois Curfman McInnes .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
270c7afd0dbSLois Curfman McInnes .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
271c7afd0dbSLois Curfman McInnes .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
272e7e93795SLois Curfman McInnes .    alpha2 - power for safeguard
273e7e93795SLois Curfman McInnes .    gamma2 - multiplicative factor for version 2 rtol computation
274c7afd0dbSLois Curfman McInnes               (0 <= gamma2 <= 1)
275c7afd0dbSLois Curfman McInnes -    threshold - threshold for imposing safeguard (0 < threshold < 1)
276fee21e36SBarry Smith 
277e7e93795SLois Curfman McInnes    Note:
278e7e93795SLois Curfman McInnes    Use PETSC_DEFAULT to retain the default for any of the parameters.
279e7e93795SLois Curfman McInnes 
28036851e7fSLois Curfman McInnes    Level: advanced
28136851e7fSLois Curfman McInnes 
282e7e93795SLois Curfman McInnes    Reference:
283e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
284e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
285e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
286e7e93795SLois Curfman McInnes 
287e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
288e7e93795SLois Curfman McInnes 
289e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW()
290e7e93795SLois Curfman McInnes @*/
291e7e93795SLois Curfman McInnes int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0,
292e7e93795SLois Curfman McInnes                              double rtol_max,double gamma2,double alpha,
293e7e93795SLois Curfman McInnes                              double alpha2,double threshold)
294e7e93795SLois Curfman McInnes {
295e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
2963a40ed3dSBarry Smith 
2973a40ed3dSBarry Smith   PetscFunctionBegin;
298a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context existing");
299e7e93795SLois Curfman McInnes   if (version != PETSC_DEFAULT)   kctx->version   = version;
300e7e93795SLois Curfman McInnes   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0    = rtol_0;
301e7e93795SLois Curfman McInnes   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max  = rtol_max;
302e7e93795SLois Curfman McInnes   if (gamma2 != PETSC_DEFAULT)    kctx->gamma     = gamma2;
303e7e93795SLois Curfman McInnes   if (alpha != PETSC_DEFAULT)     kctx->alpha     = alpha;
304e7e93795SLois Curfman McInnes   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2    = alpha2;
305e7e93795SLois Curfman McInnes   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
306a8c6a408SBarry Smith   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
307596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0);
308a8c6a408SBarry Smith   }
309a8c6a408SBarry Smith   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
310596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_max < 1.0\n",kctx->rtol_max);
311a8c6a408SBarry Smith   }
312a8c6a408SBarry Smith   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
313596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 < threshold < 1.0\n",kctx->threshold);
314a8c6a408SBarry Smith   }
315a8c6a408SBarry Smith   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
316596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= alpha <= 1.0\n",kctx->gamma);
317a8c6a408SBarry Smith   }
318a8c6a408SBarry Smith   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
319596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"1.0 < alpha <= 2.0\n",kctx->alpha);
320a8c6a408SBarry Smith   }
321a8c6a408SBarry Smith   if (kctx->version != 1 && kctx->version !=2) {
322596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 and 2 are supported: %d",kctx->version);
323a8c6a408SBarry Smith   }
3243a40ed3dSBarry Smith   PetscFunctionReturn(0);
325e7e93795SLois Curfman McInnes }
326e7e93795SLois Curfman McInnes 
3275615d1e5SSatish Balay #undef __FUNC__
3285615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_ComputeRelativeTolerance_Private"
329e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
330e7e93795SLois Curfman McInnes {
331e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
3323f1db9ecSBarry Smith   double              rtol = 0.0, stol;
333e7e93795SLois Curfman McInnes   int                 ierr;
3343a40ed3dSBarry Smith 
3353a40ed3dSBarry Smith   PetscFunctionBegin;
336a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context exists");
337e7e93795SLois Curfman McInnes   if (snes->iter == 1) {
338e7e93795SLois Curfman McInnes     rtol = kctx->rtol_0;
339e7e93795SLois Curfman McInnes   } else {
340e7e93795SLois Curfman McInnes     if (kctx->version == 1) {
341e7e93795SLois Curfman McInnes       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
342e7e93795SLois Curfman McInnes       if (rtol < 0.0) rtol = -rtol;
343e7e93795SLois Curfman McInnes       stol = pow(kctx->rtol_last,kctx->alpha2);
3440452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
345e7e93795SLois Curfman McInnes     } else if (kctx->version == 2) {
346e7e93795SLois Curfman McInnes       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
347e7e93795SLois Curfman McInnes       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
3480452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
349596552b5SBarry Smith     } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 or 2 are supported: %d",kctx->version);
350e7e93795SLois Curfman McInnes   }
3510452661fSBarry Smith   rtol = PetscMin(rtol,kctx->rtol_max);
352e7e93795SLois Curfman McInnes   kctx->rtol_last = rtol;
353596552b5SBarry Smith   PLogInfo(snes,"SNESConverged_EQ_LS: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol);
3543131a8b6SLois Curfman McInnes   ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); CHKERRQ(ierr);
355e7e93795SLois Curfman McInnes   kctx->norm_last = snes->norm;
3563a40ed3dSBarry Smith   PetscFunctionReturn(0);
357e7e93795SLois Curfman McInnes }
358e7e93795SLois Curfman McInnes 
3595615d1e5SSatish Balay #undef __FUNC__
3605615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_Converged_Private"
361e7e93795SLois Curfman McInnes int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx)
362e7e93795SLois Curfman McInnes {
363e7e93795SLois Curfman McInnes   SNES                snes = (SNES)ctx;
364e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
365e7e93795SLois Curfman McInnes   int                 convinfo;
366e7e93795SLois Curfman McInnes 
3673a40ed3dSBarry Smith   PetscFunctionBegin;
368a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context set");
369e7e93795SLois Curfman McInnes   if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);
370e7e93795SLois Curfman McInnes   convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx);
371e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
3723a40ed3dSBarry Smith   if (convinfo) {
373981c4779SBarry Smith     PLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm);
3743a40ed3dSBarry Smith   }
3753a40ed3dSBarry Smith   PetscFunctionReturn(convinfo);
376e7e93795SLois Curfman McInnes }
377e7e93795SLois Curfman McInnes 
378e7e93795SLois Curfman McInnes 
379