xref: /petsc/src/snes/interface/snesut.c (revision d252947ab307443ec0f8cabd384072ff75afeb3e)
1e7e93795SLois Curfman McInnes #ifndef lint
2*d252947aSBarry Smith static char vcid[] = "$Id: snesut.c,v 1.26 1997/01/06 20:29:45 balay 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__
95615d1e5SSatish Balay #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__
425615d1e5SSatish Balay #define __FUNC__ "SNESDefaultSMonitor"
43e7e93795SLois Curfman McInnes int SNESDefaultSMonitor(SNES snes,int its, double fgnorm,void *dummy)
44e7e93795SLois Curfman McInnes {
45e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
468f240d10SBarry Smith     if (fgnorm > 1.e-9) {
47c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm);
48e7e93795SLois Curfman McInnes     }
49e7e93795SLois Curfman McInnes     else if (fgnorm > 1.e-11){
50c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm %5.3e \n",its,fgnorm);
51e7e93795SLois Curfman McInnes     }
52e7e93795SLois Curfman McInnes     else {
53c7ab52efSLois Curfman McInnes       PetscPrintf(snes->comm, "iter = %d, SNES Function norm < 1.e-11\n",its);
54e7e93795SLois Curfman McInnes     }
55e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
568f240d10SBarry Smith     if (fgnorm > 1.e-9) {
5777c4ece6SBarry Smith       PetscPrintf(snes->comm,
58c7ab52efSLois Curfman McInnes        "iter = %d, SNES Function value %g, Gradient norm %g \n",
59e7e93795SLois Curfman McInnes        its,snes->fc,fgnorm);
60e7e93795SLois Curfman McInnes     }
61e7e93795SLois Curfman McInnes     else if (fgnorm > 1.e-11) {
6277c4ece6SBarry Smith       PetscPrintf(snes->comm,
63c7ab52efSLois Curfman McInnes         "iter = %d, SNES Function value %g, Gradient norm %5.3e \n",
64e7e93795SLois Curfman McInnes         its,snes->fc,fgnorm);
65e7e93795SLois Curfman McInnes     }
66e7e93795SLois Curfman McInnes     else {
6777c4ece6SBarry Smith       PetscPrintf(snes->comm,
68c7ab52efSLois Curfman McInnes         "iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",
69e7e93795SLois Curfman McInnes         its,snes->fc);
70e7e93795SLois Curfman McInnes     }
71e3372554SBarry Smith   } else SETERRQ(1,0,"Unknown method class");
72e7e93795SLois Curfman McInnes   return 0;
73e7e93795SLois Curfman McInnes }
74e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
755615d1e5SSatish Balay #undef __FUNC__
765615d1e5SSatish Balay #define __FUNC__ "SNESConverged_EQ_LS"
774b828684SBarry Smith /*@C
78f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
79f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
80e7e93795SLois Curfman McInnes 
81e7e93795SLois Curfman McInnes    Input Parameters:
82e7e93795SLois Curfman McInnes .  snes - the SNES context
83e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
84e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
85e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
86e7e93795SLois Curfman McInnes .  dummy - unused context
87e7e93795SLois Curfman McInnes 
88e7e93795SLois Curfman McInnes    Returns:
89e7e93795SLois Curfman McInnes $  2  if  ( fnorm < atol ),
90e7e93795SLois Curfman McInnes $  3  if  ( pnorm < xtol*xnorm ),
915d2e0e51SBarry Smith $  4  if  ( fnorm < rtol*fnorm0 ),
92e7e93795SLois Curfman McInnes $ -2  if  ( nfct > maxf ),
93e7e93795SLois Curfman McInnes $  0  otherwise,
94e7e93795SLois Curfman McInnes 
95e7e93795SLois Curfman McInnes    where
96e7e93795SLois Curfman McInnes $    maxf - maximum number of function evaluations,
97acd914d5SLois Curfman McInnes $           set with SNESSetTolerances()
98e7e93795SLois Curfman McInnes $    nfct - number of function evaluations,
99e7e93795SLois Curfman McInnes $    atol - absolute function norm tolerance,
100acd914d5SLois Curfman McInnes $           set with SNESSetTolerances()
101d7a720efSLois Curfman McInnes $    rtol - relative function norm tolerance,
102acd914d5SLois Curfman McInnes $           set with SNESSetTolerances()
103e7e93795SLois Curfman McInnes 
104e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
105e7e93795SLois Curfman McInnes 
106e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
107e7e93795SLois Curfman McInnes @*/
10840191667SLois Curfman McInnes int SNESConverged_EQ_LS(SNES snes,double xnorm,double pnorm,double fnorm,void *dummy)
109e7e93795SLois Curfman McInnes {
110*d252947aSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
111*d252947aSBarry Smith      SETERRQ(1,0,"For SNES_NONLINEAR_EQUATIONS only");
112*d252947aSBarry Smith   }
113082acdaeSLois Curfman McInnes   /* Note:  Reserve return code 1, -1 for compatibility with SNESConverged_EQ_TR */
114*d252947aSBarry Smith   if (fnorm != fnorm) {
115*d252947aSBarry Smith     PLogInfo(snes,"SNES:Failed to converged, function norm is NaN\n");
116*d252947aSBarry Smith     return -3;
117*d252947aSBarry Smith   }
1185d2e0e51SBarry Smith   if (fnorm <= snes->ttol) {
11994a424c1SBarry Smith     PLogInfo(snes,
1205d2e0e51SBarry Smith     "SNES:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
1215d2e0e51SBarry Smith     return 4;
1225d2e0e51SBarry Smith   }
1235d2e0e51SBarry Smith 
124e7e93795SLois Curfman McInnes   if (fnorm < snes->atol) {
12594a424c1SBarry Smith     PLogInfo(snes,
1260de55854SLois Curfman McInnes       "SNES: Converged due to function norm %g < %g\n",fnorm,snes->atol);
127e7e93795SLois Curfman McInnes     return 2;
128e7e93795SLois Curfman McInnes   }
129e7e93795SLois Curfman McInnes   if (pnorm < snes->xtol*(xnorm)) {
13094a424c1SBarry Smith     PLogInfo(snes,
131e7e93795SLois Curfman McInnes       "SNES: Converged due to small update length: %g < %g * %g\n",
132e7e93795SLois Curfman McInnes        pnorm,snes->xtol,xnorm);
133e7e93795SLois Curfman McInnes     return 3;
134e7e93795SLois Curfman McInnes   }
135e7e93795SLois Curfman McInnes   if (snes->nfuncs > snes->max_funcs) {
136*d252947aSBarry Smith     PLogInfo(snes,"SNES: Exceeded maximum number of function evaluations: %d > %d\n",
137e7e93795SLois Curfman McInnes       snes->nfuncs, snes->max_funcs );
138e7e93795SLois Curfman McInnes     return -2;
139e7e93795SLois Curfman McInnes   }
140e7e93795SLois Curfman McInnes   return 0;
141e7e93795SLois Curfman McInnes }
142e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
1435615d1e5SSatish Balay #undef __FUNC__
1445615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetConvergenceTestEW"
145e7e93795SLois Curfman McInnes /*@
146f525115eSLois Curfman McInnes    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
147e7e93795SLois Curfman McInnes    for the linear solvers within an inexact Newton method.
148e7e93795SLois Curfman McInnes 
149e7e93795SLois Curfman McInnes    Input Parameter:
150e7e93795SLois Curfman McInnes .  snes - SNES context
151e7e93795SLois Curfman McInnes 
152e7e93795SLois Curfman McInnes    Notes:
153e7e93795SLois Curfman McInnes    Currently, the default is to use a constant relative tolerance for
154e7e93795SLois Curfman McInnes    the inner linear solvers.  Alternatively, one can use the
155e7e93795SLois Curfman McInnes    Eisenstat-Walker method, where the relative convergence tolerance
156e7e93795SLois Curfman McInnes    is reset at each Newton iteration according progress of the nonlinear
157e7e93795SLois Curfman McInnes    solver.
158e7e93795SLois Curfman McInnes 
159e7e93795SLois Curfman McInnes    Reference:
160e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
161e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
162e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
163e7e93795SLois Curfman McInnes 
164e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
165e7e93795SLois Curfman McInnes @*/
166e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes)
167e7e93795SLois Curfman McInnes {
168e7e93795SLois Curfman McInnes   snes->ksp_ewconv = 1;
169e7e93795SLois Curfman McInnes   return 0;
170e7e93795SLois Curfman McInnes }
171e7e93795SLois Curfman McInnes 
1725615d1e5SSatish Balay #undef __FUNC__
1735615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetParametersEW"
174e7e93795SLois Curfman McInnes /*@
175e7e93795SLois Curfman McInnes    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
176e7e93795SLois Curfman McInnes    convergence criteria for the linear solvers within an inexact
177e7e93795SLois Curfman McInnes    Newton method.
178e7e93795SLois Curfman McInnes 
179e7e93795SLois Curfman McInnes    Input Parameters:
180e7e93795SLois Curfman McInnes .  snes - SNES context
181e7e93795SLois Curfman McInnes .  version - version 1 or 2 (default is 2)
182e7e93795SLois Curfman McInnes .  rtol_0 - initial relative tolerance
183e7e93795SLois Curfman McInnes $    (0 <= rtol_0 < 1)
184e7e93795SLois Curfman McInnes .  rtol_max - maximum relative tolerance
185e7e93795SLois Curfman McInnes $    (0 <= rtol_max < 1)
186e7e93795SLois Curfman McInnes .  alpha - power for version 2 rtol computation
187e7e93795SLois Curfman McInnes $    (1 < alpha <= 2)
188e7e93795SLois Curfman McInnes .  alpha2 - power for safeguard
189e7e93795SLois Curfman McInnes .  gamma2 - multiplicative factor for version 2 rtol computation
190e7e93795SLois Curfman McInnes $    (0 <= gamma2 <= 1)
191e7e93795SLois Curfman McInnes .  threshold - threshold for imposing safeguard
192e7e93795SLois Curfman McInnes $    (0 < threshold < 1)
193e7e93795SLois Curfman McInnes 
194e7e93795SLois Curfman McInnes    Note:
195e7e93795SLois Curfman McInnes    Use PETSC_DEFAULT to retain the default for any of the parameters.
196e7e93795SLois Curfman McInnes 
197e7e93795SLois Curfman McInnes    Reference:
198e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
199e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
200e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
201e7e93795SLois Curfman McInnes 
202e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
203e7e93795SLois Curfman McInnes 
204e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW()
205e7e93795SLois Curfman McInnes @*/
206e7e93795SLois Curfman McInnes int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0,
207e7e93795SLois Curfman McInnes                              double rtol_max,double gamma2,double alpha,
208e7e93795SLois Curfman McInnes                              double alpha2,double threshold)
209e7e93795SLois Curfman McInnes {
210e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
211e3372554SBarry Smith   if (!kctx) SETERRQ(1,0,"No context");
212e7e93795SLois Curfman McInnes   if (version != PETSC_DEFAULT)   kctx->version = version;
213e7e93795SLois Curfman McInnes   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0 = rtol_0;
214e7e93795SLois Curfman McInnes   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max = rtol_max;
215e7e93795SLois Curfman McInnes   if (gamma2 != PETSC_DEFAULT)    kctx->gamma = gamma2;
216e7e93795SLois Curfman McInnes   if (alpha != PETSC_DEFAULT)     kctx->alpha = alpha;
217e7e93795SLois Curfman McInnes   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2 = alpha2;
218e7e93795SLois Curfman McInnes   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
219e3372554SBarry Smith   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) SETERRQ(1,0,
22063c41f6aSSatish Balay     "0.0 <= rtol_0 < 1.0\n");
221e3372554SBarry Smith   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) SETERRQ(1,0,
22263c41f6aSSatish Balay     "0.0 <= rtol_max < 1.0\n");
223e3372554SBarry Smith   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) SETERRQ(1,0,
22463c41f6aSSatish Balay     "0.0 < threshold < 1.0\n");
225e3372554SBarry Smith   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) SETERRQ(1,0,
22663c41f6aSSatish Balay     "0.0 <= alpha <= 1.0\n");
227e3372554SBarry Smith   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) SETERRQ(1,0,
22863c41f6aSSatish Balay     "1.0 < alpha <= 2.0\n");
229e3372554SBarry Smith   if (kctx->version != 1 && kctx->version !=2) SETERRQ(1,0,
23063c41f6aSSatish Balay      "Only versions 1 and 2 are supported");
231e7e93795SLois Curfman McInnes   return 0;
232e7e93795SLois Curfman McInnes }
233e7e93795SLois Curfman McInnes 
2345615d1e5SSatish Balay #undef __FUNC__
2355615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_ComputeRelativeTolerance_Private"
236e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
237e7e93795SLois Curfman McInnes {
238e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
239e7e93795SLois Curfman McInnes   double rtol, stol;
240e7e93795SLois Curfman McInnes   int    ierr;
241e7e93795SLois Curfman McInnes   if (!kctx)
242e3372554SBarry Smith     SETERRQ(1,0,"No context");
243e7e93795SLois Curfman McInnes   if (snes->iter == 1) {
244e7e93795SLois Curfman McInnes     rtol = kctx->rtol_0;
245e7e93795SLois Curfman McInnes   } else {
246e7e93795SLois Curfman McInnes     if (kctx->version == 1) {
247e7e93795SLois Curfman McInnes       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
248e7e93795SLois Curfman McInnes       if (rtol < 0.0) rtol = -rtol;
249e7e93795SLois Curfman McInnes       stol = pow(kctx->rtol_last,kctx->alpha2);
2500452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
251e7e93795SLois Curfman McInnes     } else if (kctx->version == 2) {
252e7e93795SLois Curfman McInnes       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
253e7e93795SLois Curfman McInnes       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
2540452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
255e3372554SBarry Smith     } else SETERRQ(1,0,
25663c41f6aSSatish Balay      "Only versions 1 or 2 are supported");
257e7e93795SLois Curfman McInnes   }
2580452661fSBarry Smith   rtol = PetscMin(rtol,kctx->rtol_max);
259e7e93795SLois Curfman McInnes   kctx->rtol_last = rtol;
26094a424c1SBarry Smith   PLogInfo(snes,
261e7e93795SLois Curfman McInnes     "SNES: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",
262e7e93795SLois Curfman McInnes      snes->iter,kctx->version,rtol);
263e7e93795SLois Curfman McInnes   ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
264e7e93795SLois Curfman McInnes   CHKERRQ(ierr);
265e7e93795SLois Curfman McInnes   kctx->norm_last = snes->norm;
266e7e93795SLois Curfman McInnes   return 0;
267e7e93795SLois Curfman McInnes }
268e7e93795SLois Curfman McInnes 
2695615d1e5SSatish Balay #undef __FUNC__
2705615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_Converged_Private"
271e7e93795SLois Curfman McInnes int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx)
272e7e93795SLois Curfman McInnes {
273e7e93795SLois Curfman McInnes   SNES                snes = (SNES)ctx;
274e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
275e7e93795SLois Curfman McInnes   int                 convinfo;
276e7e93795SLois Curfman McInnes 
277e3372554SBarry Smith   if (!kctx) SETERRQ(1,0,"No convergence context");
278e7e93795SLois Curfman McInnes   if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);
279e7e93795SLois Curfman McInnes   convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx);
280e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
281e7e93795SLois Curfman McInnes   if (convinfo)
28294a424c1SBarry Smith     PLogInfo(snes,"SNES: KSP iterations=%d, rnorm=%g\n",n,rnorm);
283e7e93795SLois Curfman McInnes   return convinfo;
284e7e93795SLois Curfman McInnes }
285e7e93795SLois Curfman McInnes 
286e7e93795SLois Curfman McInnes 
287