xref: /petsc/src/snes/interface/snesut.c (revision d4bb536f0e426e9a0292bbfd5743770a9b03f0d5)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*d4bb536fSBarry Smith static char vcid[] = "$Id: snesut.c,v 1.31 1997/07/18 19:10:14 bsmith Exp bsmith $";
3e7e93795SLois Curfman McInnes #endif
4e7e93795SLois Curfman McInnes 
5e7e93795SLois Curfman McInnes #include <math.h>
670f55243SBarry Smith #include "src/snes/snesimpl.h"       /*I   "snes.h"   I*/
7e7e93795SLois Curfman McInnes 
85615d1e5SSatish Balay #undef __FUNC__
9*d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultMonitor"
104b828684SBarry Smith /*@C
11f525115eSLois Curfman McInnes    SNESDefaultMonitor - Monitoring progress of the SNES solvers (default).
12e7e93795SLois Curfman McInnes 
13e7e93795SLois Curfman McInnes    Input Parameters:
14e7e93795SLois Curfman McInnes .  snes - the SNES context
15e7e93795SLois Curfman McInnes .  its - iteration number
16e7e93795SLois Curfman McInnes .  fgnorm - 2-norm of residual (or gradient)
17e7e93795SLois Curfman McInnes .  dummy - unused context
18e7e93795SLois Curfman McInnes 
19e7e93795SLois Curfman McInnes    Notes:
20e7e93795SLois Curfman McInnes    For SNES_NONLINEAR_EQUATIONS methods the routine prints the
21e7e93795SLois Curfman McInnes    residual norm at each iteration.
22e7e93795SLois Curfman McInnes 
23e7e93795SLois Curfman McInnes    For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the
24e7e93795SLois Curfman McInnes    function value and gradient norm at each iteration.
25e7e93795SLois Curfman McInnes 
26e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm
27e7e93795SLois Curfman McInnes 
28e7e93795SLois Curfman McInnes .seealso: SNESSetMonitor()
29e7e93795SLois Curfman McInnes @*/
30e7e93795SLois Curfman McInnes int SNESDefaultMonitor(SNES snes,int its,double fgnorm,void *dummy)
31e7e93795SLois Curfman McInnes {
32e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS)
3377c4ece6SBarry Smith     PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);
34e7e93795SLois Curfman McInnes   else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION)
3577c4ece6SBarry Smith     PetscPrintf(snes->comm,
36c7ab52efSLois Curfman McInnes      "iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);
37e3372554SBarry Smith   else SETERRQ(1,0,"Unknown method class");
38e7e93795SLois Curfman McInnes   return 0;
39e7e93795SLois Curfman McInnes }
40e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
415615d1e5SSatish Balay #undef __FUNC__
42*d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultSMonitor"
43be1f7002SBarry Smith /*
44be1f7002SBarry Smith      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
45be1f7002SBarry Smith   it prints fewer digits of the residual as the residual gets smaller.
46be1f7002SBarry Smith   This is because the later digits are meaningless and are often
47be1f7002SBarry Smith   different on different machines; by using this routine different
48be1f7002SBarry Smith   machines will usually generate the same output.
49be1f7002SBarry Smith */
50e7e93795SLois Curfman McInnes int SNESDefaultSMonitor(SNES snes,int its, double fgnorm,void *dummy)
51e7e93795SLois Curfman McInnes {
52e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
538f240d10SBarry Smith     if (fgnorm > 1.e-9) {
54c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);
55e7e93795SLois Curfman McInnes     }
56e7e93795SLois Curfman McInnes     else if (fgnorm > 1.e-11){
57c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm %5.3e \n",its,fgnorm);
58e7e93795SLois Curfman McInnes     }
59e7e93795SLois Curfman McInnes     else {
60c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm < 1.e-11\n",its);
61e7e93795SLois Curfman McInnes     }
62e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
638f240d10SBarry Smith     if (fgnorm > 1.e-9) {
6477c4ece6SBarry Smith       PetscPrintf(snes->comm,
65c7ab52efSLois Curfman McInnes        "iter = %d, SNES Function value %g, Gradient norm %g \n",
66e7e93795SLois Curfman McInnes        its,snes->fc,fgnorm);
67e7e93795SLois Curfman McInnes     }
68e7e93795SLois Curfman McInnes     else if (fgnorm > 1.e-11) {
6977c4ece6SBarry Smith       PetscPrintf(snes->comm,
70c7ab52efSLois Curfman McInnes         "iter = %d, SNES Function value %g, Gradient norm %5.3e \n",
71e7e93795SLois Curfman McInnes         its,snes->fc,fgnorm);
72e7e93795SLois Curfman McInnes     }
73e7e93795SLois Curfman McInnes     else {
7477c4ece6SBarry Smith       PetscPrintf(snes->comm,
75c7ab52efSLois Curfman McInnes         "iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",
76e7e93795SLois Curfman McInnes         its,snes->fc);
77e7e93795SLois Curfman McInnes     }
78e3372554SBarry Smith   } else SETERRQ(1,0,"Unknown method class");
79e7e93795SLois Curfman McInnes   return 0;
80e7e93795SLois Curfman McInnes }
81e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
825615d1e5SSatish Balay #undef __FUNC__
835615d1e5SSatish Balay #define __FUNC__ "SNESConverged_EQ_LS"
844b828684SBarry Smith /*@C
85f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
86f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
87e7e93795SLois Curfman McInnes 
88e7e93795SLois Curfman McInnes    Input Parameters:
89e7e93795SLois Curfman McInnes .  snes - the SNES context
90e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
91e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
92e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
93e7e93795SLois Curfman McInnes .  dummy - unused context
94e7e93795SLois Curfman McInnes 
95e7e93795SLois Curfman McInnes    Returns:
96e7e93795SLois Curfman McInnes $  2  if  ( fnorm < atol ),
97e7e93795SLois Curfman McInnes $  3  if  ( pnorm < xtol*xnorm ),
985d2e0e51SBarry Smith $  4  if  ( fnorm < rtol*fnorm0 ),
99e7e93795SLois Curfman McInnes $ -2  if  ( nfct > maxf ),
100e7e93795SLois Curfman McInnes $  0  otherwise,
101e7e93795SLois Curfman McInnes 
102e7e93795SLois Curfman McInnes    where
103e7e93795SLois Curfman McInnes $    maxf - maximum number of function evaluations,
104acd914d5SLois Curfman McInnes $           set with SNESSetTolerances()
105e7e93795SLois Curfman McInnes $    nfct - number of function evaluations,
106e7e93795SLois Curfman McInnes $    atol - absolute function norm tolerance,
107acd914d5SLois Curfman McInnes $           set with SNESSetTolerances()
108d7a720efSLois Curfman McInnes $    rtol - relative function norm tolerance,
109acd914d5SLois Curfman McInnes $           set with SNESSetTolerances()
110e7e93795SLois Curfman McInnes 
111e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
112e7e93795SLois Curfman McInnes 
113e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
114e7e93795SLois Curfman McInnes @*/
11540191667SLois Curfman McInnes int SNESConverged_EQ_LS(SNES snes,double xnorm,double pnorm,double fnorm,void *dummy)
116e7e93795SLois Curfman McInnes {
117d252947aSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
118d252947aSBarry Smith      SETERRQ(1,0,"For SNES_NONLINEAR_EQUATIONS only");
119d252947aSBarry Smith   }
120082acdaeSLois Curfman McInnes   /* Note:  Reserve return code 1, -1 for compatibility with SNESConverged_EQ_TR */
121d252947aSBarry Smith   if (fnorm != fnorm) {
122d252947aSBarry Smith     PLogInfo(snes,"SNES:Failed to converged, function norm is NaN\n");
123d252947aSBarry Smith     return -3;
124d252947aSBarry Smith   }
1255d2e0e51SBarry Smith   if (fnorm <= snes->ttol) {
12694a424c1SBarry Smith     PLogInfo(snes,
1275d2e0e51SBarry Smith     "SNES:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
1285d2e0e51SBarry Smith     return 4;
1295d2e0e51SBarry Smith   }
1305d2e0e51SBarry Smith 
131e7e93795SLois Curfman McInnes   if (fnorm < snes->atol) {
13294a424c1SBarry Smith     PLogInfo(snes,
1330de55854SLois Curfman McInnes       "SNES: Converged due to function norm %g < %g\n",fnorm,snes->atol);
134e7e93795SLois Curfman McInnes     return 2;
135e7e93795SLois Curfman McInnes   }
136e7e93795SLois Curfman McInnes   if (pnorm < snes->xtol*(xnorm)) {
13794a424c1SBarry Smith     PLogInfo(snes,
138e7e93795SLois Curfman McInnes       "SNES: Converged due to small update length: %g < %g * %g\n",
139e7e93795SLois Curfman McInnes        pnorm,snes->xtol,xnorm);
140e7e93795SLois Curfman McInnes     return 3;
141e7e93795SLois Curfman McInnes   }
142e7e93795SLois Curfman McInnes   if (snes->nfuncs > snes->max_funcs) {
143d252947aSBarry Smith     PLogInfo(snes,"SNES: Exceeded maximum number of function evaluations: %d > %d\n",
144e7e93795SLois Curfman McInnes       snes->nfuncs, snes->max_funcs );
145e7e93795SLois Curfman McInnes     return -2;
146e7e93795SLois Curfman McInnes   }
147e7e93795SLois Curfman McInnes   return 0;
148e7e93795SLois Curfman McInnes }
149e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
1505615d1e5SSatish Balay #undef __FUNC__
1515615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetConvergenceTestEW"
152e7e93795SLois Curfman McInnes /*@
153f525115eSLois Curfman McInnes    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
154e7e93795SLois Curfman McInnes    for the linear solvers within an inexact Newton method.
155e7e93795SLois Curfman McInnes 
156e7e93795SLois Curfman McInnes    Input Parameter:
157e7e93795SLois Curfman McInnes .  snes - SNES context
158e7e93795SLois Curfman McInnes 
159e7e93795SLois Curfman McInnes    Notes:
160e7e93795SLois Curfman McInnes    Currently, the default is to use a constant relative tolerance for
161e7e93795SLois Curfman McInnes    the inner linear solvers.  Alternatively, one can use the
162e7e93795SLois Curfman McInnes    Eisenstat-Walker method, where the relative convergence tolerance
163e7e93795SLois Curfman McInnes    is reset at each Newton iteration according progress of the nonlinear
164e7e93795SLois Curfman McInnes    solver.
165e7e93795SLois Curfman McInnes 
166e7e93795SLois Curfman McInnes    Reference:
167e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
168e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
169e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
170e7e93795SLois Curfman McInnes 
171e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
172e7e93795SLois Curfman McInnes @*/
173e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes)
174e7e93795SLois Curfman McInnes {
175e7e93795SLois Curfman McInnes   snes->ksp_ewconv = 1;
176e7e93795SLois Curfman McInnes   return 0;
177e7e93795SLois Curfman McInnes }
178e7e93795SLois Curfman McInnes 
1795615d1e5SSatish Balay #undef __FUNC__
1805615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetParametersEW"
181e7e93795SLois Curfman McInnes /*@
182e7e93795SLois Curfman McInnes    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
183e7e93795SLois Curfman McInnes    convergence criteria for the linear solvers within an inexact
184e7e93795SLois Curfman McInnes    Newton method.
185e7e93795SLois Curfman McInnes 
186e7e93795SLois Curfman McInnes    Input Parameters:
187e7e93795SLois Curfman McInnes .  snes - SNES context
188e7e93795SLois Curfman McInnes .  version - version 1 or 2 (default is 2)
189e7e93795SLois Curfman McInnes .  rtol_0 - initial relative tolerance
190e7e93795SLois Curfman McInnes $    (0 <= rtol_0 < 1)
191e7e93795SLois Curfman McInnes .  rtol_max - maximum relative tolerance
192e7e93795SLois Curfman McInnes $    (0 <= rtol_max < 1)
193e7e93795SLois Curfman McInnes .  alpha - power for version 2 rtol computation
194e7e93795SLois Curfman McInnes $    (1 < alpha <= 2)
195e7e93795SLois Curfman McInnes .  alpha2 - power for safeguard
196e7e93795SLois Curfman McInnes .  gamma2 - multiplicative factor for version 2 rtol computation
197e7e93795SLois Curfman McInnes $    (0 <= gamma2 <= 1)
198e7e93795SLois Curfman McInnes .  threshold - threshold for imposing safeguard
199e7e93795SLois Curfman McInnes $    (0 < threshold < 1)
200e7e93795SLois Curfman McInnes 
201e7e93795SLois Curfman McInnes    Note:
202e7e93795SLois Curfman McInnes    Use PETSC_DEFAULT to retain the default for any of the parameters.
203e7e93795SLois Curfman McInnes 
204e7e93795SLois Curfman McInnes    Reference:
205e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
206e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
207e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
208e7e93795SLois Curfman McInnes 
209e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
210e7e93795SLois Curfman McInnes 
211e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW()
212e7e93795SLois Curfman McInnes @*/
213e7e93795SLois Curfman McInnes int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0,
214e7e93795SLois Curfman McInnes                              double rtol_max,double gamma2,double alpha,
215e7e93795SLois Curfman McInnes                              double alpha2,double threshold)
216e7e93795SLois Curfman McInnes {
217e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
218e3372554SBarry Smith   if (!kctx) SETERRQ(1,0,"No context");
219e7e93795SLois Curfman McInnes   if (version != PETSC_DEFAULT)   kctx->version = version;
220e7e93795SLois Curfman McInnes   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0 = rtol_0;
221e7e93795SLois Curfman McInnes   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max = rtol_max;
222e7e93795SLois Curfman McInnes   if (gamma2 != PETSC_DEFAULT)    kctx->gamma = gamma2;
223e7e93795SLois Curfman McInnes   if (alpha != PETSC_DEFAULT)     kctx->alpha = alpha;
224e7e93795SLois Curfman McInnes   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2 = alpha2;
225e7e93795SLois Curfman McInnes   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
226e3372554SBarry Smith   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) SETERRQ(1,0,
22763c41f6aSSatish Balay     "0.0 <= rtol_0 < 1.0\n");
228e3372554SBarry Smith   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) SETERRQ(1,0,
22963c41f6aSSatish Balay     "0.0 <= rtol_max < 1.0\n");
230e3372554SBarry Smith   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) SETERRQ(1,0,
23163c41f6aSSatish Balay     "0.0 < threshold < 1.0\n");
232e3372554SBarry Smith   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) SETERRQ(1,0,
23363c41f6aSSatish Balay     "0.0 <= alpha <= 1.0\n");
234e3372554SBarry Smith   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) SETERRQ(1,0,
23563c41f6aSSatish Balay     "1.0 < alpha <= 2.0\n");
236e3372554SBarry Smith   if (kctx->version != 1 && kctx->version !=2) SETERRQ(1,0,
23763c41f6aSSatish Balay      "Only versions 1 and 2 are supported");
238e7e93795SLois Curfman McInnes   return 0;
239e7e93795SLois Curfman McInnes }
240e7e93795SLois Curfman McInnes 
2415615d1e5SSatish Balay #undef __FUNC__
2425615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_ComputeRelativeTolerance_Private"
243e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
244e7e93795SLois Curfman McInnes {
245e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
246e7e93795SLois Curfman McInnes   double rtol, stol;
247e7e93795SLois Curfman McInnes   int    ierr;
248e7e93795SLois Curfman McInnes   if (!kctx)
249e3372554SBarry Smith     SETERRQ(1,0,"No context");
250e7e93795SLois Curfman McInnes   if (snes->iter == 1) {
251e7e93795SLois Curfman McInnes     rtol = kctx->rtol_0;
252e7e93795SLois Curfman McInnes   } else {
253e7e93795SLois Curfman McInnes     if (kctx->version == 1) {
254e7e93795SLois Curfman McInnes       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
255e7e93795SLois Curfman McInnes       if (rtol < 0.0) rtol = -rtol;
256e7e93795SLois Curfman McInnes       stol = pow(kctx->rtol_last,kctx->alpha2);
2570452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
258e7e93795SLois Curfman McInnes     } else if (kctx->version == 2) {
259e7e93795SLois Curfman McInnes       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
260e7e93795SLois Curfman McInnes       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
2610452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
262e3372554SBarry Smith     } else SETERRQ(1,0,
26363c41f6aSSatish Balay      "Only versions 1 or 2 are supported");
264e7e93795SLois Curfman McInnes   }
2650452661fSBarry Smith   rtol = PetscMin(rtol,kctx->rtol_max);
266e7e93795SLois Curfman McInnes   kctx->rtol_last = rtol;
26794a424c1SBarry Smith   PLogInfo(snes,
268e7e93795SLois Curfman McInnes     "SNES: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",
269e7e93795SLois Curfman McInnes      snes->iter,kctx->version,rtol);
2703131a8b6SLois Curfman McInnes   ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); CHKERRQ(ierr);
271e7e93795SLois Curfman McInnes   kctx->norm_last = snes->norm;
272e7e93795SLois Curfman McInnes   return 0;
273e7e93795SLois Curfman McInnes }
274e7e93795SLois Curfman McInnes 
2755615d1e5SSatish Balay #undef __FUNC__
2765615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_Converged_Private"
277e7e93795SLois Curfman McInnes int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx)
278e7e93795SLois Curfman McInnes {
279e7e93795SLois Curfman McInnes   SNES                snes = (SNES)ctx;
280e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
281e7e93795SLois Curfman McInnes   int                 convinfo;
282e7e93795SLois Curfman McInnes 
283e3372554SBarry Smith   if (!kctx) SETERRQ(1,0,"No convergence context");
284e7e93795SLois Curfman McInnes   if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);
285e7e93795SLois Curfman McInnes   convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx);
286e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
287e7e93795SLois Curfman McInnes   if (convinfo)
28894a424c1SBarry Smith     PLogInfo(snes,"SNES: KSP iterations=%d, rnorm=%g\n",n,rnorm);
289e7e93795SLois Curfman McInnes   return convinfo;
290e7e93795SLois Curfman McInnes }
291e7e93795SLois Curfman McInnes 
292e7e93795SLois Curfman McInnes 
293