1e7e93795SLois Curfman McInnes #ifndef lint 2*63c41f6aSSatish Balay static char vcid[] = "$Id: snesut.c,v 1.23 1996/12/16 20:47:45 balay Exp balay $"; 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 8a847f771SSatish Balay #undef __FUNCTION__ 9a847f771SSatish Balay #define __FUNCTION__ "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); 37*63c41f6aSSatish Balay else SETERRQ(1,"Unknown method class"); 38e7e93795SLois Curfman McInnes return 0; 39e7e93795SLois Curfman McInnes } 40e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */ 41a847f771SSatish Balay #undef __FUNCTION__ 42a847f771SSatish Balay #define __FUNCTION__ "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 } 71*63c41f6aSSatish Balay } else SETERRQ(1,"Unknown method class"); 72e7e93795SLois Curfman McInnes return 0; 73e7e93795SLois Curfman McInnes } 74e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */ 75a847f771SSatish Balay #undef __FUNCTION__ 76a847f771SSatish Balay #define __FUNCTION__ "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 { 110e7e93795SLois Curfman McInnes if (snes->method_class != SNES_NONLINEAR_EQUATIONS) SETERRQ(1, 111*63c41f6aSSatish Balay "For SNES_NONLINEAR_EQUATIONS only"); 112082acdaeSLois Curfman McInnes /* Note: Reserve return code 1, -1 for compatibility with SNESConverged_EQ_TR */ 1135d2e0e51SBarry Smith if (fnorm <= snes->ttol) { 11494a424c1SBarry Smith PLogInfo(snes, 1155d2e0e51SBarry Smith "SNES:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol); 1165d2e0e51SBarry Smith return 4; 1175d2e0e51SBarry Smith } 1185d2e0e51SBarry Smith 119e7e93795SLois Curfman McInnes if (fnorm < snes->atol) { 12094a424c1SBarry Smith PLogInfo(snes, 1210de55854SLois Curfman McInnes "SNES: Converged due to function norm %g < %g\n",fnorm,snes->atol); 122e7e93795SLois Curfman McInnes return 2; 123e7e93795SLois Curfman McInnes } 124e7e93795SLois Curfman McInnes if (pnorm < snes->xtol*(xnorm)) { 12594a424c1SBarry Smith PLogInfo(snes, 126e7e93795SLois Curfman McInnes "SNES: Converged due to small update length: %g < %g * %g\n", 127e7e93795SLois Curfman McInnes pnorm,snes->xtol,xnorm); 128e7e93795SLois Curfman McInnes return 3; 129e7e93795SLois Curfman McInnes } 130e7e93795SLois Curfman McInnes if (snes->nfuncs > snes->max_funcs) { 13194a424c1SBarry Smith PLogInfo(snes, 132e7e93795SLois Curfman McInnes "SNES: Exceeded maximum number of function evaluations: %d > %d\n", 133e7e93795SLois Curfman McInnes snes->nfuncs, snes->max_funcs ); 134e7e93795SLois Curfman McInnes return -2; 135e7e93795SLois Curfman McInnes } 136e7e93795SLois Curfman McInnes return 0; 137e7e93795SLois Curfman McInnes } 138e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */ 139a847f771SSatish Balay #undef __FUNCTION__ 140a847f771SSatish Balay #define __FUNCTION__ "SNES_KSP_SetConvergenceTestEW" 141e7e93795SLois Curfman McInnes /*@ 142f525115eSLois Curfman McInnes SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test 143e7e93795SLois Curfman McInnes for the linear solvers within an inexact Newton method. 144e7e93795SLois Curfman McInnes 145e7e93795SLois Curfman McInnes Input Parameter: 146e7e93795SLois Curfman McInnes . snes - SNES context 147e7e93795SLois Curfman McInnes 148e7e93795SLois Curfman McInnes Notes: 149e7e93795SLois Curfman McInnes Currently, the default is to use a constant relative tolerance for 150e7e93795SLois Curfman McInnes the inner linear solvers. Alternatively, one can use the 151e7e93795SLois Curfman McInnes Eisenstat-Walker method, where the relative convergence tolerance 152e7e93795SLois Curfman McInnes is reset at each Newton iteration according progress of the nonlinear 153e7e93795SLois Curfman McInnes solver. 154e7e93795SLois Curfman McInnes 155e7e93795SLois Curfman McInnes Reference: 156e7e93795SLois Curfman McInnes S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 157e7e93795SLois Curfman McInnes inexact Newton method", Utah State University Math. Stat. Dept. Res. 158e7e93795SLois Curfman McInnes Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 159e7e93795SLois Curfman McInnes 160e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 161e7e93795SLois Curfman McInnes @*/ 162e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes) 163e7e93795SLois Curfman McInnes { 164e7e93795SLois Curfman McInnes snes->ksp_ewconv = 1; 165e7e93795SLois Curfman McInnes return 0; 166e7e93795SLois Curfman McInnes } 167e7e93795SLois Curfman McInnes 168a847f771SSatish Balay #undef __FUNCTION__ 169a847f771SSatish Balay #define __FUNCTION__ "SNES_KSP_SetParametersEW" 170e7e93795SLois Curfman McInnes /*@ 171e7e93795SLois Curfman McInnes SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker 172e7e93795SLois Curfman McInnes convergence criteria for the linear solvers within an inexact 173e7e93795SLois Curfman McInnes Newton method. 174e7e93795SLois Curfman McInnes 175e7e93795SLois Curfman McInnes Input Parameters: 176e7e93795SLois Curfman McInnes . snes - SNES context 177e7e93795SLois Curfman McInnes . version - version 1 or 2 (default is 2) 178e7e93795SLois Curfman McInnes . rtol_0 - initial relative tolerance 179e7e93795SLois Curfman McInnes $ (0 <= rtol_0 < 1) 180e7e93795SLois Curfman McInnes . rtol_max - maximum relative tolerance 181e7e93795SLois Curfman McInnes $ (0 <= rtol_max < 1) 182e7e93795SLois Curfman McInnes . alpha - power for version 2 rtol computation 183e7e93795SLois Curfman McInnes $ (1 < alpha <= 2) 184e7e93795SLois Curfman McInnes . alpha2 - power for safeguard 185e7e93795SLois Curfman McInnes . gamma2 - multiplicative factor for version 2 rtol computation 186e7e93795SLois Curfman McInnes $ (0 <= gamma2 <= 1) 187e7e93795SLois Curfman McInnes . threshold - threshold for imposing safeguard 188e7e93795SLois Curfman McInnes $ (0 < threshold < 1) 189e7e93795SLois Curfman McInnes 190e7e93795SLois Curfman McInnes Note: 191e7e93795SLois Curfman McInnes Use PETSC_DEFAULT to retain the default for any of the parameters. 192e7e93795SLois Curfman McInnes 193e7e93795SLois Curfman McInnes Reference: 194e7e93795SLois Curfman McInnes S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 195e7e93795SLois Curfman McInnes inexact Newton method", Utah State University Math. Stat. Dept. Res. 196e7e93795SLois Curfman McInnes Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 197e7e93795SLois Curfman McInnes 198e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 199e7e93795SLois Curfman McInnes 200e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW() 201e7e93795SLois Curfman McInnes @*/ 202e7e93795SLois Curfman McInnes int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0, 203e7e93795SLois Curfman McInnes double rtol_max,double gamma2,double alpha, 204e7e93795SLois Curfman McInnes double alpha2,double threshold) 205e7e93795SLois Curfman McInnes { 206e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 207*63c41f6aSSatish Balay if (!kctx) SETERRQ(1,"No context"); 208e7e93795SLois Curfman McInnes if (version != PETSC_DEFAULT) kctx->version = version; 209e7e93795SLois Curfman McInnes if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 210e7e93795SLois Curfman McInnes if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 211e7e93795SLois Curfman McInnes if (gamma2 != PETSC_DEFAULT) kctx->gamma = gamma2; 212e7e93795SLois Curfman McInnes if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 213e7e93795SLois Curfman McInnes if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 214e7e93795SLois Curfman McInnes if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 215e7e93795SLois Curfman McInnes if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) SETERRQ(1, 216*63c41f6aSSatish Balay "0.0 <= rtol_0 < 1.0\n"); 217e7e93795SLois Curfman McInnes if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) SETERRQ(1, 218*63c41f6aSSatish Balay "0.0 <= rtol_max < 1.0\n"); 219e7e93795SLois Curfman McInnes if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) SETERRQ(1, 220*63c41f6aSSatish Balay "0.0 < threshold < 1.0\n"); 221e7e93795SLois Curfman McInnes if (kctx->gamma < 0.0 || kctx->gamma > 1.0) SETERRQ(1, 222*63c41f6aSSatish Balay "0.0 <= alpha <= 1.0\n"); 223e7e93795SLois Curfman McInnes if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) SETERRQ(1, 224*63c41f6aSSatish Balay "1.0 < alpha <= 2.0\n"); 225e7e93795SLois Curfman McInnes if (kctx->version != 1 && kctx->version !=2) SETERRQ(1, 226*63c41f6aSSatish Balay "Only versions 1 and 2 are supported"); 227e7e93795SLois Curfman McInnes return 0; 228e7e93795SLois Curfman McInnes } 229e7e93795SLois Curfman McInnes 230a847f771SSatish Balay #undef __FUNCTION__ 231a847f771SSatish Balay #define __FUNCTION__ "SNES_KSP_EW_ComputeRelativeTolerance_Private" 232e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp) 233e7e93795SLois Curfman McInnes { 234e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 235e7e93795SLois Curfman McInnes double rtol, stol; 236e7e93795SLois Curfman McInnes int ierr; 237e7e93795SLois Curfman McInnes if (!kctx) 238*63c41f6aSSatish Balay SETERRQ(1,"No context"); 239e7e93795SLois Curfman McInnes if (snes->iter == 1) { 240e7e93795SLois Curfman McInnes rtol = kctx->rtol_0; 241e7e93795SLois Curfman McInnes } else { 242e7e93795SLois Curfman McInnes if (kctx->version == 1) { 243e7e93795SLois Curfman McInnes rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 244e7e93795SLois Curfman McInnes if (rtol < 0.0) rtol = -rtol; 245e7e93795SLois Curfman McInnes stol = pow(kctx->rtol_last,kctx->alpha2); 2460452661fSBarry Smith if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 247e7e93795SLois Curfman McInnes } else if (kctx->version == 2) { 248e7e93795SLois Curfman McInnes rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha); 249e7e93795SLois Curfman McInnes stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha); 2500452661fSBarry Smith if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 251e7e93795SLois Curfman McInnes } else SETERRQ(1, 252*63c41f6aSSatish Balay "Only versions 1 or 2 are supported"); 253e7e93795SLois Curfman McInnes } 2540452661fSBarry Smith rtol = PetscMin(rtol,kctx->rtol_max); 255e7e93795SLois Curfman McInnes kctx->rtol_last = rtol; 25694a424c1SBarry Smith PLogInfo(snes, 257e7e93795SLois Curfman McInnes "SNES: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n", 258e7e93795SLois Curfman McInnes snes->iter,kctx->version,rtol); 259e7e93795SLois Curfman McInnes ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); 260e7e93795SLois Curfman McInnes CHKERRQ(ierr); 261e7e93795SLois Curfman McInnes kctx->norm_last = snes->norm; 262e7e93795SLois Curfman McInnes return 0; 263e7e93795SLois Curfman McInnes } 264e7e93795SLois Curfman McInnes 265a847f771SSatish Balay #undef __FUNCTION__ 266a847f771SSatish Balay #define __FUNCTION__ "SNES_KSP_EW_Converged_Private" 267e7e93795SLois Curfman McInnes int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx) 268e7e93795SLois Curfman McInnes { 269e7e93795SLois Curfman McInnes SNES snes = (SNES)ctx; 270e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 271e7e93795SLois Curfman McInnes int convinfo; 272e7e93795SLois Curfman McInnes 273*63c41f6aSSatish Balay if (!kctx) SETERRQ(1,"No convergence context"); 274e7e93795SLois Curfman McInnes if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp); 275e7e93795SLois Curfman McInnes convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx); 276e7e93795SLois Curfman McInnes kctx->lresid_last = rnorm; 277e7e93795SLois Curfman McInnes if (convinfo) 27894a424c1SBarry Smith PLogInfo(snes,"SNES: KSP iterations=%d, rnorm=%g\n",n,rnorm); 279e7e93795SLois Curfman McInnes return convinfo; 280e7e93795SLois Curfman McInnes } 281e7e93795SLois Curfman McInnes 282e7e93795SLois Curfman McInnes 283