xref: /petsc/src/snes/interface/snesut.c (revision e090d5668ba2b2ea997ebb925e3a05be0dc5d9ab)
1*e090d566SSatish Balay /*$Id: snesut.c,v 1.55 2000/04/12 04:25:27 bsmith Exp balay $*/
2e7e93795SLois Curfman McInnes 
3*e090d566SSatish Balay #include "src/snes/snesimpl.h"       /*I   "petscsnes.h"   I*/
4e7e93795SLois Curfman McInnes 
55615d1e5SSatish Balay #undef __FUNC__
6b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"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 @*/
25329f5518SBarry Smith int SNESVecViewMonitor(SNES snes,int its,PetscReal 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__
44b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"SNESVecViewUpdateMonitor"
45d132466eSBarry Smith /*@C
467c922b88SBarry Smith    SNESVecViewUpdateMonitor - 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 @*/
63329f5518SBarry Smith int SNESVecViewUpdateMonitor(SNES snes,int its,PetscReal 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__
82b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"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 @*/
107329f5518SBarry Smith int SNESDefaultMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
108e7e93795SLois Curfman McInnes {
109d132466eSBarry Smith   int    ierr;
1107c922b88SBarry Smith   Viewer viewer = (Viewer) dummy;
111d132466eSBarry Smith 
1123a40ed3dSBarry Smith   PetscFunctionBegin;
1137c922b88SBarry Smith   if (!viewer) viewer = VIEWER_STDOUT_(snes->comm);
1147c922b88SBarry Smith 
11576be9ce4SBarry Smith   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
1167c922b88SBarry Smith     ierr = ViewerASCIIPrintf(viewer,"iter = %d, SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr);
11776be9ce4SBarry Smith   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
1187c922b88SBarry Smith     ierr = ViewerASCIIPrintf(viewer,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
11976be9ce4SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
1203a40ed3dSBarry Smith   PetscFunctionReturn(0);
121e7e93795SLois Curfman McInnes }
1223f1db9ecSBarry Smith 
123e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
1245615d1e5SSatish Balay #undef __FUNC__
125b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"SNESDefaultSMonitor"
126be1f7002SBarry Smith /*
127be1f7002SBarry Smith      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
128be1f7002SBarry Smith   it prints fewer digits of the residual as the residual gets smaller.
129be1f7002SBarry Smith   This is because the later digits are meaningless and are often
130be1f7002SBarry Smith   different on different machines; by using this routine different
131be1f7002SBarry Smith   machines will usually generate the same output.
132be1f7002SBarry Smith */
133329f5518SBarry Smith int SNESDefaultSMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
134e7e93795SLois Curfman McInnes {
135d132466eSBarry Smith   int ierr;
136d132466eSBarry Smith 
1373a40ed3dSBarry Smith   PetscFunctionBegin;
138e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
1398f240d10SBarry Smith     if (fgnorm > 1.e-9) {
140d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr);
1413a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11){
142d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr);
1433a40ed3dSBarry Smith     } else {
144d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr);
145e7e93795SLois Curfman McInnes     }
146e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
1478f240d10SBarry Smith     if (fgnorm > 1.e-9) {
148d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
1493a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11) {
150d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
1513a40ed3dSBarry Smith     } else {
152d132466eSBarry Smith       ierr = PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);CHKERRQ(ierr);
153e7e93795SLois Curfman McInnes     }
154a8c6a408SBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class");
1553a40ed3dSBarry Smith   PetscFunctionReturn(0);
156e7e93795SLois Curfman McInnes }
157e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
1585615d1e5SSatish Balay #undef __FUNC__
159b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"SNESConverged_EQ_LS"
1604b828684SBarry Smith /*@C
161f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
162f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
163e7e93795SLois Curfman McInnes 
164c7afd0dbSLois Curfman McInnes    Collective on SNES
165c7afd0dbSLois Curfman McInnes 
166e7e93795SLois Curfman McInnes    Input Parameters:
167c7afd0dbSLois Curfman McInnes +  snes - the SNES context
168e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
169e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
170e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
171c7afd0dbSLois Curfman McInnes -  dummy - unused context
172e7e93795SLois Curfman McInnes 
173184914b5SBarry Smith    Output Parameter:
174184914b5SBarry Smith .   reason  - one of
175184914b5SBarry Smith $  SNES_CONVERGED_FNORM_ABS       - (fnorm < atol),
176184914b5SBarry Smith $  SNES_CONVERGED_PNORM_RELATIVE  - (pnorm < xtol*xnorm),
177184914b5SBarry Smith $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
178184914b5SBarry Smith $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
179184914b5SBarry Smith $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
180184914b5SBarry Smith $  SNES_CONVERGED_ITERATING       - (otherwise),
181e7e93795SLois Curfman McInnes 
182e7e93795SLois Curfman McInnes    where
183c7afd0dbSLois Curfman McInnes +    maxf - maximum number of function evaluations,
184c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
185c7afd0dbSLois Curfman McInnes .    nfct - number of function evaluations,
186c7afd0dbSLois Curfman McInnes .    atol - absolute function norm tolerance,
187c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
188c7afd0dbSLois Curfman McInnes -    rtol - relative function norm tolerance, set with SNESSetTolerances()
189fee21e36SBarry Smith 
19036851e7fSLois Curfman McInnes    Level: intermediate
19136851e7fSLois Curfman McInnes 
192e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
193e7e93795SLois Curfman McInnes 
194e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
195e7e93795SLois Curfman McInnes @*/
196329f5518SBarry Smith int SNESConverged_EQ_LS(SNES snes,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
197e7e93795SLois Curfman McInnes {
1983a40ed3dSBarry Smith   PetscFunctionBegin;
199d252947aSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
200a8c6a408SBarry Smith      SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only");
201d252947aSBarry Smith   }
202184914b5SBarry Smith 
203d252947aSBarry Smith   if (fnorm != fnorm) {
204981c4779SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n");
205184914b5SBarry Smith     *reason = SNES_DIVERGED_FNORM_NAN;
206184914b5SBarry Smith   } else if (fnorm <= snes->ttol) {
20715091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
208184914b5SBarry Smith     *reason = SNES_CONVERGED_FNORM_RELATIVE;
209184914b5SBarry Smith   } else if (fnorm < snes->atol) {
21015091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol);
211184914b5SBarry Smith     *reason = SNES_CONVERGED_FNORM_ABS;
212184914b5SBarry Smith   } else if (pnorm < snes->xtol*(xnorm)) {
21315091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm);
214184914b5SBarry Smith     *reason = SNES_CONVERGED_PNORM_RELATIVE;
215184914b5SBarry Smith   } else if (snes->nfuncs > snes->max_funcs) {
21615091d37SBarry Smith     PLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs,snes->max_funcs);
217184914b5SBarry Smith     *reason = SNES_DIVERGED_FUNCTION_COUNT ;
218184914b5SBarry Smith   } else {
219184914b5SBarry Smith     *reason = SNES_CONVERGED_ITERATING;
220e7e93795SLois Curfman McInnes   }
2213a40ed3dSBarry Smith   PetscFunctionReturn(0);
222e7e93795SLois Curfman McInnes }
223e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
2245615d1e5SSatish Balay #undef __FUNC__
225b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"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__
258b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"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 @*/
291329f5518SBarry Smith int SNES_KSP_SetParametersEW(SNES snes,int version,PetscReal rtol_0,
292329f5518SBarry Smith                              PetscReal rtol_max,PetscReal gamma2,PetscReal alpha,
293329f5518SBarry Smith                              PetscReal alpha2,PetscReal 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__
328b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"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;
332329f5518SBarry Smith   PetscReal           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");
337c38d4ed2SBarry Smith   if (!snes->iter) { /* first time in, so use the original user rtol */
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;
353184914b5SBarry Smith   PLogInfo(snes,"SNES_KSP_EW_ComputeRelativeTolerance_Private: 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__
360b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"SNES_KSP_EW_Converged_Private"
361329f5518SBarry Smith int SNES_KSP_EW_Converged_Private(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,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;
3653acb151aSSatish Balay   int                 ierr;
3663acb151aSSatish Balay   KSPConvergedReason  convinfo;
367e7e93795SLois Curfman McInnes 
3683a40ed3dSBarry Smith   PetscFunctionBegin;
369a8c6a408SBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context set");
370184914b5SBarry Smith   if (n == 0) {ierr = SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);CHKERRQ(ierr);}
3713acb151aSSatish Balay   ierr = KSPDefaultConverged(ksp,n,rnorm,&convinfo,ctx);CHKERRQ(ierr);
372e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
3733a40ed3dSBarry Smith   if (convinfo) {
374981c4779SBarry Smith     PLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm);
3753a40ed3dSBarry Smith   }
3763a40ed3dSBarry Smith   PetscFunctionReturn(convinfo);
377e7e93795SLois Curfman McInnes }
378e7e93795SLois Curfman McInnes 
379e7e93795SLois Curfman McInnes 
380