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