xref: /petsc/src/snes/interface/snesut.c (revision c38d4ed214221df9ea04de46f7761bef149d00ff)
1*c38d4ed2SBarry Smith /*$Id: snesut.c,v 1.49 1999/10/24 14:03:31 bsmith Exp bsmith $*/
2e7e93795SLois Curfman McInnes 
370f55243SBarry Smith #include "src/snes/snesimpl.h"       /*I   "snes.h"   I*/
4e7e93795SLois Curfman McInnes 
55615d1e5SSatish Balay #undef __FUNC__
63f1db9ecSBarry Smith #define __FUNC__ "SNESVecViewMonitor"
73f1db9ecSBarry Smith /*@C
836851e7fSLois Curfman McInnes    SNESVecViewMonitor - Monitors progress of the SNES solvers by calling
936851e7fSLois Curfman McInnes    VecView() for the approximate solution at each iteration.
103f1db9ecSBarry Smith 
113f1db9ecSBarry Smith    Collective on SNES
123f1db9ecSBarry Smith 
133f1db9ecSBarry Smith    Input Parameters:
143f1db9ecSBarry Smith +  snes - the SNES context
153f1db9ecSBarry Smith .  its - iteration number
163f1db9ecSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
173f1db9ecSBarry Smith -  dummy - either a viewer or PETSC_NULL
183f1db9ecSBarry Smith 
1936851e7fSLois Curfman McInnes    Level: intermediate
203f1db9ecSBarry Smith 
2136851e7fSLois Curfman McInnes .keywords: SNES, nonlinear, vector, monitor, view
223f1db9ecSBarry Smith 
2336851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
243f1db9ecSBarry Smith @*/
253f1db9ecSBarry Smith int SNESVecViewMonitor(SNES snes,int its,double fgnorm,void *dummy)
263f1db9ecSBarry Smith {
273f1db9ecSBarry Smith   int    ierr;
283f1db9ecSBarry Smith   Vec    x;
293f1db9ecSBarry Smith   Viewer viewer = (Viewer) dummy;
303f1db9ecSBarry Smith 
313f1db9ecSBarry Smith   PetscFunctionBegin;
323f1db9ecSBarry Smith   ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr);
333f1db9ecSBarry Smith   if (!viewer) {
343f1db9ecSBarry Smith     MPI_Comm comm;
353f1db9ecSBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
36c655490fSBarry Smith     viewer = VIEWER_DRAW_(comm);
373f1db9ecSBarry Smith   }
383f1db9ecSBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
393f1db9ecSBarry Smith 
403f1db9ecSBarry Smith   PetscFunctionReturn(0);
413f1db9ecSBarry Smith }
423f1db9ecSBarry Smith 
433f1db9ecSBarry Smith #undef __FUNC__
44d132466eSBarry Smith #define __FUNC__ "SNESVecViewMonitorUpdate"
45d132466eSBarry Smith /*@C
46d132466eSBarry Smith    SNESVecViewMonitorUpdate - Monitors progress of the SNES solvers by calling
47d132466eSBarry Smith    VecView() for the UPDATE to the solution at each iteration.
48d132466eSBarry Smith 
49d132466eSBarry Smith    Collective on SNES
50d132466eSBarry Smith 
51d132466eSBarry Smith    Input Parameters:
52d132466eSBarry Smith +  snes - the SNES context
53d132466eSBarry Smith .  its - iteration number
54d132466eSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
55d132466eSBarry Smith -  dummy - either a viewer or PETSC_NULL
56d132466eSBarry Smith 
57d132466eSBarry Smith    Level: intermediate
58d132466eSBarry Smith 
59d132466eSBarry Smith .keywords: SNES, nonlinear, vector, monitor, view
60d132466eSBarry Smith 
61d132466eSBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
62d132466eSBarry Smith @*/
63d132466eSBarry Smith int SNESVecViewMonitorUpdate(SNES snes,int its,double fgnorm,void *dummy)
64d132466eSBarry Smith {
65d132466eSBarry Smith   int    ierr;
66d132466eSBarry Smith   Vec    x;
67d132466eSBarry Smith   Viewer viewer = (Viewer) dummy;
68d132466eSBarry Smith 
69d132466eSBarry Smith   PetscFunctionBegin;
70d132466eSBarry Smith   ierr = SNESGetSolutionUpdate(snes,&x);CHKERRQ(ierr);
71d132466eSBarry Smith   if (!viewer) {
72d132466eSBarry Smith     MPI_Comm comm;
73d132466eSBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
74d132466eSBarry Smith     viewer = VIEWER_DRAW_(comm);
75d132466eSBarry Smith   }
76d132466eSBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
77d132466eSBarry Smith 
78d132466eSBarry Smith   PetscFunctionReturn(0);
79d132466eSBarry Smith }
80d132466eSBarry Smith 
81d132466eSBarry Smith #undef __FUNC__
82d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultMonitor"
834b828684SBarry Smith /*@C
84f525115eSLois Curfman McInnes    SNESDefaultMonitor - Monitoring progress of the SNES solvers (default).
85e7e93795SLois Curfman McInnes 
86c7afd0dbSLois Curfman McInnes    Collective on SNES
87c7afd0dbSLois Curfman McInnes 
88e7e93795SLois Curfman McInnes    Input Parameters:
89c7afd0dbSLois Curfman McInnes +  snes - the SNES context
90e7e93795SLois Curfman McInnes .  its - iteration number
91e7e93795SLois Curfman McInnes .  fgnorm - 2-norm of residual (or gradient)
92c7afd0dbSLois Curfman McInnes -  dummy - unused context
93fee21e36SBarry Smith 
94e7e93795SLois Curfman McInnes    Notes:
95e7e93795SLois Curfman McInnes    For SNES_NONLINEAR_EQUATIONS methods the routine prints the
96e7e93795SLois Curfman McInnes    residual norm at each iteration.
97e7e93795SLois Curfman McInnes 
98e7e93795SLois Curfman McInnes    For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the
99e7e93795SLois Curfman McInnes    function value and gradient norm at each iteration.
100e7e93795SLois Curfman McInnes 
10136851e7fSLois Curfman McInnes    Level: intermediate
10236851e7fSLois Curfman McInnes 
103e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm
104e7e93795SLois Curfman McInnes 
10536851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESVecViewMonitor()
106e7e93795SLois Curfman McInnes @*/
107e7e93795SLois Curfman McInnes int SNESDefaultMonitor(SNES snes,int its,double fgnorm,void *dummy)
108e7e93795SLois Curfman McInnes {
109d132466eSBarry Smith   int ierr;
110d132466eSBarry Smith 
1113a40ed3dSBarry Smith   PetscFunctionBegin;
11276be9ce4SBarry Smith   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
113d132466eSBarry Smith     ierr = PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr);
11476be9ce4SBarry Smith   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
115d132466eSBarry Smith     ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
11676be9ce4SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
1173a40ed3dSBarry Smith   PetscFunctionReturn(0);
118e7e93795SLois Curfman McInnes }
1193f1db9ecSBarry Smith 
120e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
1215615d1e5SSatish Balay #undef __FUNC__
122d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultSMonitor"
123be1f7002SBarry Smith /*
124be1f7002SBarry Smith      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
125be1f7002SBarry Smith   it prints fewer digits of the residual as the residual gets smaller.
126be1f7002SBarry Smith   This is because the later digits are meaningless and are often
127be1f7002SBarry Smith   different on different machines; by using this routine different
128be1f7002SBarry Smith   machines will usually generate the same output.
129be1f7002SBarry Smith */
130e7e93795SLois Curfman McInnes int SNESDefaultSMonitor(SNES snes,int its, double fgnorm,void *dummy)
131e7e93795SLois Curfman McInnes {
132d132466eSBarry Smith   int ierr;
133d132466eSBarry Smith 
1343a40ed3dSBarry Smith   PetscFunctionBegin;
135e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
1368f240d10SBarry Smith     if (fgnorm > 1.e-9) {
137d132466eSBarry Smith       ierr = PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr);
1383a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11){
139d132466eSBarry Smith       ierr = PetscPrintf(snes->comm, "iter = %d, SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr);
1403a40ed3dSBarry Smith     } else {
141d132466eSBarry Smith       ierr = PetscPrintf(snes->comm, "iter = %d, SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr);
142e7e93795SLois Curfman McInnes     }
143e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
1448f240d10SBarry Smith     if (fgnorm > 1.e-9) {
145d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
1463a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11) {
147d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
1483a40ed3dSBarry Smith     } else {
149d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);CHKERRQ(ierr);
150e7e93795SLois Curfman McInnes     }
151a8c6a408SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
1523a40ed3dSBarry Smith   PetscFunctionReturn(0);
153e7e93795SLois Curfman McInnes }
154e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
1555615d1e5SSatish Balay #undef __FUNC__
1565615d1e5SSatish Balay #define __FUNC__ "SNESConverged_EQ_LS"
1574b828684SBarry Smith /*@C
158f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
159f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
160e7e93795SLois Curfman McInnes 
161c7afd0dbSLois Curfman McInnes    Collective on SNES
162c7afd0dbSLois Curfman McInnes 
163e7e93795SLois Curfman McInnes    Input Parameters:
164c7afd0dbSLois Curfman McInnes +  snes - the SNES context
165e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
166e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
167e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
168c7afd0dbSLois Curfman McInnes -  dummy - unused context
169e7e93795SLois Curfman McInnes 
170184914b5SBarry Smith    Output Parameter:
171184914b5SBarry Smith .   reason  - one of
172184914b5SBarry Smith $  SNES_CONVERGED_FNORM_ABS       - ( fnorm < atol ),
173184914b5SBarry Smith $  SNES_CONVERGED_PNORM_RELATIVE  - ( pnorm < xtol*xnorm ),
174184914b5SBarry Smith $  SNES_CONVERGED_FNORM_RELATIVE  - ( fnorm < rtol*fnorm0 ),
175184914b5SBarry Smith $  SNES_DIVERGED_FUNCTION_COUNT   - ( nfct > maxf ),
176184914b5SBarry Smith $  SNES_DIVERGED_FNORM_NAN        - ( fnorm == NaN ),
177184914b5SBarry Smith $  SNES_CONVERGED_ITERATING       - ( 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 @*/
193184914b5SBarry Smith int SNESConverged_EQ_LS(SNES snes,double xnorm,double pnorm,double fnorm,SNESConvergedReason *reason,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   }
199184914b5SBarry Smith 
200d252947aSBarry Smith   if (fnorm != fnorm) {
201981c4779SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n");
202184914b5SBarry Smith     *reason = SNES_DIVERGED_FNORM_NAN;
203184914b5SBarry Smith   } else if (fnorm <= snes->ttol) {
20415091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
205184914b5SBarry Smith     *reason = SNES_CONVERGED_FNORM_RELATIVE;
206184914b5SBarry Smith   } else if (fnorm < snes->atol) {
20715091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol);
208184914b5SBarry Smith     *reason = SNES_CONVERGED_FNORM_ABS;
209184914b5SBarry Smith   } else if (pnorm < snes->xtol*(xnorm)) {
21015091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm);
211184914b5SBarry Smith     *reason = SNES_CONVERGED_PNORM_RELATIVE;
212184914b5SBarry Smith   } else if (snes->nfuncs > snes->max_funcs) {
21315091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs, snes->max_funcs);
214184914b5SBarry Smith     *reason = SNES_DIVERGED_FUNCTION_COUNT ;
215184914b5SBarry Smith   } else {
216184914b5SBarry Smith     *reason = SNES_CONVERGED_ITERATING;
217e7e93795SLois Curfman McInnes   }
2183a40ed3dSBarry Smith   PetscFunctionReturn(0);
219e7e93795SLois Curfman McInnes }
220e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
2215615d1e5SSatish Balay #undef __FUNC__
2225615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetConvergenceTestEW"
223e7e93795SLois Curfman McInnes /*@
224f525115eSLois Curfman McInnes    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
225e7e93795SLois Curfman McInnes    for the linear solvers within an inexact Newton method.
226e7e93795SLois Curfman McInnes 
227c7afd0dbSLois Curfman McInnes    Collective on SNES
228c7afd0dbSLois Curfman McInnes 
229e7e93795SLois Curfman McInnes    Input Parameter:
230e7e93795SLois Curfman McInnes .  snes - SNES context
231e7e93795SLois Curfman McInnes 
232e7e93795SLois Curfman McInnes    Notes:
233e7e93795SLois Curfman McInnes    Currently, the default is to use a constant relative tolerance for
234e7e93795SLois Curfman McInnes    the inner linear solvers.  Alternatively, one can use the
235e7e93795SLois Curfman McInnes    Eisenstat-Walker method, where the relative convergence tolerance
236e7e93795SLois Curfman McInnes    is reset at each Newton iteration according progress of the nonlinear
237e7e93795SLois Curfman McInnes    solver.
238e7e93795SLois Curfman McInnes 
23936851e7fSLois Curfman McInnes    Level: advanced
24036851e7fSLois Curfman McInnes 
241e7e93795SLois Curfman McInnes    Reference:
242e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
243e30ad881SLois Curfman McInnes    inexact Newton method", SISC 17 (1), pp.16-32, 1996.
244e7e93795SLois Curfman McInnes 
245e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
246e7e93795SLois Curfman McInnes @*/
247e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes)
248e7e93795SLois Curfman McInnes {
2493a40ed3dSBarry Smith   PetscFunctionBegin;
250e7e93795SLois Curfman McInnes   snes->ksp_ewconv = 1;
2513a40ed3dSBarry Smith   PetscFunctionReturn(0);
252e7e93795SLois Curfman McInnes }
253e7e93795SLois Curfman McInnes 
2545615d1e5SSatish Balay #undef __FUNC__
2555615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetParametersEW"
256e7e93795SLois Curfman McInnes /*@
257e7e93795SLois Curfman McInnes    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
258e7e93795SLois Curfman McInnes    convergence criteria for the linear solvers within an inexact
259e7e93795SLois Curfman McInnes    Newton method.
260e7e93795SLois Curfman McInnes 
261c7afd0dbSLois Curfman McInnes    Collective on SNES
262c7afd0dbSLois Curfman McInnes 
263e7e93795SLois Curfman McInnes    Input Parameters:
264c7afd0dbSLois Curfman McInnes +    snes - SNES context
265e7e93795SLois Curfman McInnes .    version - version 1 or 2 (default is 2)
266c7afd0dbSLois Curfman McInnes .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
267c7afd0dbSLois Curfman McInnes .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
268c7afd0dbSLois Curfman McInnes .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
269e7e93795SLois Curfman McInnes .    alpha2 - power for safeguard
270e7e93795SLois Curfman McInnes .    gamma2 - multiplicative factor for version 2 rtol computation
271c7afd0dbSLois Curfman McInnes               (0 <= gamma2 <= 1)
272c7afd0dbSLois Curfman McInnes -    threshold - threshold for imposing safeguard (0 < threshold < 1)
273fee21e36SBarry Smith 
274e7e93795SLois Curfman McInnes    Note:
275e7e93795SLois Curfman McInnes    Use PETSC_DEFAULT to retain the default for any of the parameters.
276e7e93795SLois Curfman McInnes 
27736851e7fSLois Curfman McInnes    Level: advanced
27836851e7fSLois Curfman McInnes 
279e7e93795SLois Curfman McInnes    Reference:
280e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
281e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
282e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
283e7e93795SLois Curfman McInnes 
284e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
285e7e93795SLois Curfman McInnes 
286e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW()
287e7e93795SLois Curfman McInnes @*/
288e7e93795SLois Curfman McInnes int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0,
289e7e93795SLois Curfman McInnes                              double rtol_max,double gamma2,double alpha,
290e7e93795SLois Curfman McInnes                              double alpha2,double threshold)
291e7e93795SLois Curfman McInnes {
292e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
2933a40ed3dSBarry Smith 
2943a40ed3dSBarry Smith   PetscFunctionBegin;
295a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context existing");
296e7e93795SLois Curfman McInnes   if (version != PETSC_DEFAULT)   kctx->version   = version;
297e7e93795SLois Curfman McInnes   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0    = rtol_0;
298e7e93795SLois Curfman McInnes   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max  = rtol_max;
299e7e93795SLois Curfman McInnes   if (gamma2 != PETSC_DEFAULT)    kctx->gamma     = gamma2;
300e7e93795SLois Curfman McInnes   if (alpha != PETSC_DEFAULT)     kctx->alpha     = alpha;
301e7e93795SLois Curfman McInnes   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2    = alpha2;
302e7e93795SLois Curfman McInnes   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
303a8c6a408SBarry Smith   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
304596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0);
305a8c6a408SBarry Smith   }
306a8c6a408SBarry Smith   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
307596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_max < 1.0\n",kctx->rtol_max);
308a8c6a408SBarry Smith   }
309a8c6a408SBarry Smith   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
310596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 < threshold < 1.0\n",kctx->threshold);
311a8c6a408SBarry Smith   }
312a8c6a408SBarry Smith   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
313596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= alpha <= 1.0\n",kctx->gamma);
314a8c6a408SBarry Smith   }
315a8c6a408SBarry Smith   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
316596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"1.0 < alpha <= 2.0\n",kctx->alpha);
317a8c6a408SBarry Smith   }
318a8c6a408SBarry Smith   if (kctx->version != 1 && kctx->version !=2) {
319596552b5SBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 and 2 are supported: %d",kctx->version);
320a8c6a408SBarry Smith   }
3213a40ed3dSBarry Smith   PetscFunctionReturn(0);
322e7e93795SLois Curfman McInnes }
323e7e93795SLois Curfman McInnes 
3245615d1e5SSatish Balay #undef __FUNC__
3255615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_ComputeRelativeTolerance_Private"
326e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
327e7e93795SLois Curfman McInnes {
328e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
3293f1db9ecSBarry Smith   double              rtol = 0.0, stol;
330e7e93795SLois Curfman McInnes   int                 ierr;
3313a40ed3dSBarry Smith 
3323a40ed3dSBarry Smith   PetscFunctionBegin;
333a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context exists");
334*c38d4ed2SBarry Smith   if (!snes->iter) { /* first time in, so use the original user rtol */
335e7e93795SLois Curfman McInnes     rtol = kctx->rtol_0;
336e7e93795SLois Curfman McInnes   } else {
337e7e93795SLois Curfman McInnes     if (kctx->version == 1) {
338e7e93795SLois Curfman McInnes       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
339e7e93795SLois Curfman McInnes       if (rtol < 0.0) rtol = -rtol;
340e7e93795SLois Curfman McInnes       stol = pow(kctx->rtol_last,kctx->alpha2);
3410452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
342e7e93795SLois Curfman McInnes     } else if (kctx->version == 2) {
343e7e93795SLois Curfman McInnes       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
344e7e93795SLois Curfman McInnes       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
3450452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
346596552b5SBarry Smith     } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 or 2 are supported: %d",kctx->version);
347e7e93795SLois Curfman McInnes   }
3480452661fSBarry Smith   rtol = PetscMin(rtol,kctx->rtol_max);
349e7e93795SLois Curfman McInnes   kctx->rtol_last = rtol;
350184914b5SBarry Smith   PLogInfo(snes,"SNES_KSP_EW_ComputeRelativeTolerance_Private: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol);
3513131a8b6SLois Curfman McInnes   ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
352e7e93795SLois Curfman McInnes   kctx->norm_last = snes->norm;
3533a40ed3dSBarry Smith   PetscFunctionReturn(0);
354e7e93795SLois Curfman McInnes }
355e7e93795SLois Curfman McInnes 
3565615d1e5SSatish Balay #undef __FUNC__
3575615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_Converged_Private"
358e7e93795SLois Curfman McInnes int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx)
359e7e93795SLois Curfman McInnes {
360e7e93795SLois Curfman McInnes   SNES                snes = (SNES)ctx;
361e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
362184914b5SBarry Smith   int                 convinfo,ierr;
363e7e93795SLois Curfman McInnes 
3643a40ed3dSBarry Smith   PetscFunctionBegin;
365a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context set");
366184914b5SBarry Smith   if (n == 0) {ierr = SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);CHKERRQ(ierr);}
367e7e93795SLois Curfman McInnes   convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx);
368e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
3693a40ed3dSBarry Smith   if (convinfo) {
370981c4779SBarry Smith     PLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm);
3713a40ed3dSBarry Smith   }
3723a40ed3dSBarry Smith   PetscFunctionReturn(convinfo);
373e7e93795SLois Curfman McInnes }
374e7e93795SLois Curfman McInnes 
375e7e93795SLois Curfman McInnes 
376