1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 2*c7afd0dbSLois Curfman McInnes static char vcid[] = "$Id: snesut.c,v 1.38 1998/04/13 17:55:33 bsmith Exp curfman $"; 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__ 9d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultMonitor" 104b828684SBarry Smith /*@C 11f525115eSLois Curfman McInnes SNESDefaultMonitor - Monitoring progress of the SNES solvers (default). 12e7e93795SLois Curfman McInnes 13*c7afd0dbSLois Curfman McInnes Collective on SNES 14*c7afd0dbSLois Curfman McInnes 15e7e93795SLois Curfman McInnes Input Parameters: 16*c7afd0dbSLois Curfman McInnes + snes - the SNES context 17e7e93795SLois Curfman McInnes . its - iteration number 18e7e93795SLois Curfman McInnes . fgnorm - 2-norm of residual (or gradient) 19*c7afd0dbSLois Curfman McInnes - dummy - unused context 20fee21e36SBarry Smith 21e7e93795SLois Curfman McInnes Notes: 22e7e93795SLois Curfman McInnes For SNES_NONLINEAR_EQUATIONS methods the routine prints the 23e7e93795SLois Curfman McInnes residual norm at each iteration. 24e7e93795SLois Curfman McInnes 25e7e93795SLois Curfman McInnes For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the 26e7e93795SLois Curfman McInnes function value and gradient norm at each iteration. 27e7e93795SLois Curfman McInnes 28e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm 29e7e93795SLois Curfman McInnes 30e7e93795SLois Curfman McInnes .seealso: SNESSetMonitor() 31e7e93795SLois Curfman McInnes @*/ 32e7e93795SLois Curfman McInnes int SNESDefaultMonitor(SNES snes,int its,double fgnorm,void *dummy) 33e7e93795SLois Curfman McInnes { 343a40ed3dSBarry Smith PetscFunctionBegin; 3576be9ce4SBarry Smith if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 3677c4ece6SBarry Smith PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm); 3776be9ce4SBarry Smith } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 383a40ed3dSBarry Smith PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm); 3976be9ce4SBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class"); 403a40ed3dSBarry Smith PetscFunctionReturn(0); 41e7e93795SLois Curfman McInnes } 42e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */ 435615d1e5SSatish Balay #undef __FUNC__ 44d4bb536fSBarry Smith #define __FUNC__ "SNESDefaultSMonitor" 45be1f7002SBarry Smith /* 46be1f7002SBarry Smith Default (short) SNES Monitor, same as SNESDefaultMonitor() except 47be1f7002SBarry Smith it prints fewer digits of the residual as the residual gets smaller. 48be1f7002SBarry Smith This is because the later digits are meaningless and are often 49be1f7002SBarry Smith different on different machines; by using this routine different 50be1f7002SBarry Smith machines will usually generate the same output. 51be1f7002SBarry Smith */ 52e7e93795SLois Curfman McInnes int SNESDefaultSMonitor(SNES snes,int its, double fgnorm,void *dummy) 53e7e93795SLois Curfman McInnes { 543a40ed3dSBarry Smith PetscFunctionBegin; 55e7e93795SLois Curfman McInnes if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 568f240d10SBarry Smith if (fgnorm > 1.e-9) { 57c7ab52efSLois Curfman McInnes PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm); 583a40ed3dSBarry Smith } else if (fgnorm > 1.e-11){ 59c7ab52efSLois Curfman McInnes PetscPrintf(snes->comm, "iter = %d, SNES Function norm %5.3e \n",its,fgnorm); 603a40ed3dSBarry Smith } else { 61c7ab52efSLois Curfman McInnes PetscPrintf(snes->comm, "iter = %d, SNES Function norm < 1.e-11\n",its); 62e7e93795SLois Curfman McInnes } 63e7e93795SLois Curfman McInnes } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 648f240d10SBarry Smith if (fgnorm > 1.e-9) { 6577c4ece6SBarry Smith PetscPrintf(snes->comm, 663a40ed3dSBarry Smith "iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm); 673a40ed3dSBarry Smith } else if (fgnorm > 1.e-11) { 6877c4ece6SBarry Smith PetscPrintf(snes->comm, 693a40ed3dSBarry Smith "iter = %d, SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm); 703a40ed3dSBarry Smith } else { 7177c4ece6SBarry Smith PetscPrintf(snes->comm, 723a40ed3dSBarry Smith "iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc); 73e7e93795SLois Curfman McInnes } 74a8c6a408SBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class"); 753a40ed3dSBarry Smith PetscFunctionReturn(0); 76e7e93795SLois Curfman McInnes } 77e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */ 785615d1e5SSatish Balay #undef __FUNC__ 795615d1e5SSatish Balay #define __FUNC__ "SNESConverged_EQ_LS" 804b828684SBarry Smith /*@C 81f525115eSLois Curfman McInnes SNESConverged_EQ_LS - Monitors the convergence of the solvers for 82f525115eSLois Curfman McInnes systems of nonlinear equations (default). 83e7e93795SLois Curfman McInnes 84*c7afd0dbSLois Curfman McInnes Collective on SNES 85*c7afd0dbSLois Curfman McInnes 86e7e93795SLois Curfman McInnes Input Parameters: 87*c7afd0dbSLois Curfman McInnes + snes - the SNES context 88e7e93795SLois Curfman McInnes . xnorm - 2-norm of current iterate 89e7e93795SLois Curfman McInnes . pnorm - 2-norm of current step 90e7e93795SLois Curfman McInnes . fnorm - 2-norm of function 91*c7afd0dbSLois Curfman McInnes - dummy - unused context 92e7e93795SLois Curfman McInnes 93e7e93795SLois Curfman McInnes Returns: 94*c7afd0dbSLois Curfman McInnes + 2 - if ( fnorm < atol ), 95*c7afd0dbSLois Curfman McInnes . 3 - if ( pnorm < xtol*xnorm ), 96*c7afd0dbSLois Curfman McInnes . 4 - if ( fnorm < rtol*fnorm0 ), 97*c7afd0dbSLois Curfman McInnes . -2 - if ( nfct > maxf ), 98*c7afd0dbSLois Curfman McInnes - 0 - otherwise, 99e7e93795SLois Curfman McInnes 100e7e93795SLois Curfman McInnes where 101*c7afd0dbSLois Curfman McInnes + maxf - maximum number of function evaluations, 102*c7afd0dbSLois Curfman McInnes set with SNESSetTolerances() 103*c7afd0dbSLois Curfman McInnes . nfct - number of function evaluations, 104*c7afd0dbSLois Curfman McInnes . atol - absolute function norm tolerance, 105*c7afd0dbSLois Curfman McInnes set with SNESSetTolerances() 106*c7afd0dbSLois Curfman McInnes - rtol - relative function norm tolerance, set with SNESSetTolerances() 107fee21e36SBarry Smith 108e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence 109e7e93795SLois Curfman McInnes 110e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged() 111e7e93795SLois Curfman McInnes @*/ 11240191667SLois Curfman McInnes int SNESConverged_EQ_LS(SNES snes,double xnorm,double pnorm,double fnorm,void *dummy) 113e7e93795SLois Curfman McInnes { 1143a40ed3dSBarry Smith PetscFunctionBegin; 115d252947aSBarry Smith if (snes->method_class != SNES_NONLINEAR_EQUATIONS) { 116a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only"); 117d252947aSBarry Smith } 118082acdaeSLois Curfman McInnes /* Note: Reserve return code 1, -1 for compatibility with SNESConverged_EQ_TR */ 119d252947aSBarry Smith if (fnorm != fnorm) { 120981c4779SBarry Smith PLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n"); 1213a40ed3dSBarry Smith PetscFunctionReturn(-3); 122d252947aSBarry Smith } 1235d2e0e51SBarry Smith if (fnorm <= snes->ttol) { 12494a424c1SBarry Smith PLogInfo(snes, 125981c4779SBarry Smith "SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol); 1263a40ed3dSBarry Smith PetscFunctionReturn(4); 1275d2e0e51SBarry Smith } 1285d2e0e51SBarry Smith 129e7e93795SLois Curfman McInnes if (fnorm < snes->atol) { 13094a424c1SBarry Smith PLogInfo(snes, 131981c4779SBarry Smith "SNESConverged_EQ_LS: Converged due to function norm %g < %g\n",fnorm,snes->atol); 1323a40ed3dSBarry Smith PetscFunctionReturn(2); 133e7e93795SLois Curfman McInnes } 134e7e93795SLois Curfman McInnes if (pnorm < snes->xtol*(xnorm)) { 13594a424c1SBarry Smith PLogInfo(snes, 136981c4779SBarry Smith "SNESConverged_EQ_LS: Converged due to small update length: %g < %g * %g\n", 137e7e93795SLois Curfman McInnes pnorm,snes->xtol,xnorm); 1383a40ed3dSBarry Smith PetscFunctionReturn(3); 139e7e93795SLois Curfman McInnes } 140e7e93795SLois Curfman McInnes if (snes->nfuncs > snes->max_funcs) { 141981c4779SBarry Smith PLogInfo(snes,"SNESConverged_EQ_LS: Exceeded maximum number of function evaluations: %d > %d\n", 142e7e93795SLois Curfman McInnes snes->nfuncs, snes->max_funcs ); 1433a40ed3dSBarry Smith PetscFunctionReturn(-2); 144e7e93795SLois Curfman McInnes } 1453a40ed3dSBarry Smith PetscFunctionReturn(0); 146e7e93795SLois Curfman McInnes } 147e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */ 1485615d1e5SSatish Balay #undef __FUNC__ 1495615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_SetConvergenceTestEW" 150e7e93795SLois Curfman McInnes /*@ 151f525115eSLois Curfman McInnes SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test 152e7e93795SLois Curfman McInnes for the linear solvers within an inexact Newton method. 153e7e93795SLois Curfman McInnes 154*c7afd0dbSLois Curfman McInnes Collective on SNES 155*c7afd0dbSLois 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 168e30ad881SLois Curfman McInnes inexact Newton method", SISC 17 (1), pp.16-32, 1996. 169e7e93795SLois Curfman McInnes 170e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 171e7e93795SLois Curfman McInnes @*/ 172e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes) 173e7e93795SLois Curfman McInnes { 1743a40ed3dSBarry Smith PetscFunctionBegin; 175e7e93795SLois Curfman McInnes snes->ksp_ewconv = 1; 1763a40ed3dSBarry Smith PetscFunctionReturn(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 186*c7afd0dbSLois Curfman McInnes Collective on SNES 187*c7afd0dbSLois Curfman McInnes 188e7e93795SLois Curfman McInnes Input Parameters: 189*c7afd0dbSLois Curfman McInnes + snes - SNES context 190e7e93795SLois Curfman McInnes . version - version 1 or 2 (default is 2) 191*c7afd0dbSLois Curfman McInnes . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 192*c7afd0dbSLois Curfman McInnes . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 193*c7afd0dbSLois Curfman McInnes . alpha - power for version 2 rtol computation (1 < alpha <= 2) 194e7e93795SLois Curfman McInnes . alpha2 - power for safeguard 195e7e93795SLois Curfman McInnes . gamma2 - multiplicative factor for version 2 rtol computation 196*c7afd0dbSLois Curfman McInnes (0 <= gamma2 <= 1) 197*c7afd0dbSLois Curfman McInnes - threshold - threshold for imposing safeguard (0 < threshold < 1) 198fee21e36SBarry Smith 199e7e93795SLois Curfman McInnes Note: 200e7e93795SLois Curfman McInnes Use PETSC_DEFAULT to retain the default for any of the parameters. 201e7e93795SLois Curfman McInnes 202e7e93795SLois Curfman McInnes Reference: 203e7e93795SLois Curfman McInnes S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 204e7e93795SLois Curfman McInnes inexact Newton method", Utah State University Math. Stat. Dept. Res. 205e7e93795SLois Curfman McInnes Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 206e7e93795SLois Curfman McInnes 207e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 208e7e93795SLois Curfman McInnes 209e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW() 210e7e93795SLois Curfman McInnes @*/ 211e7e93795SLois Curfman McInnes int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0, 212e7e93795SLois Curfman McInnes double rtol_max,double gamma2,double alpha, 213e7e93795SLois Curfman McInnes double alpha2,double threshold) 214e7e93795SLois Curfman McInnes { 215e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 2163a40ed3dSBarry Smith 2173a40ed3dSBarry Smith PetscFunctionBegin; 218a8c6a408SBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context existing"); 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; 226a8c6a408SBarry Smith if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) { 227a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_0 < 1.0\n"); 228a8c6a408SBarry Smith } 229a8c6a408SBarry Smith if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) { 230a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_max < 1.0\n"); 231a8c6a408SBarry Smith } 232a8c6a408SBarry Smith if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) { 233a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 < threshold < 1.0\n"); 234a8c6a408SBarry Smith } 235a8c6a408SBarry Smith if (kctx->gamma < 0.0 || kctx->gamma > 1.0) { 236a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= alpha <= 1.0\n"); 237a8c6a408SBarry Smith } 238a8c6a408SBarry Smith if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) { 239a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"1.0 < alpha <= 2.0\n"); 240a8c6a408SBarry Smith } 241a8c6a408SBarry Smith if (kctx->version != 1 && kctx->version !=2) { 242a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 and 2 are supported"); 243a8c6a408SBarry Smith } 2443a40ed3dSBarry Smith PetscFunctionReturn(0); 245e7e93795SLois Curfman McInnes } 246e7e93795SLois Curfman McInnes 2475615d1e5SSatish Balay #undef __FUNC__ 2485615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_ComputeRelativeTolerance_Private" 249e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp) 250e7e93795SLois Curfman McInnes { 251e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 252e7e93795SLois Curfman McInnes double rtol, stol; 253e7e93795SLois Curfman McInnes int ierr; 2543a40ed3dSBarry Smith 2553a40ed3dSBarry Smith PetscFunctionBegin; 256a8c6a408SBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context exists"); 257e7e93795SLois Curfman McInnes if (snes->iter == 1) { 258e7e93795SLois Curfman McInnes rtol = kctx->rtol_0; 259e7e93795SLois Curfman McInnes } else { 260e7e93795SLois Curfman McInnes if (kctx->version == 1) { 261e7e93795SLois Curfman McInnes rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 262e7e93795SLois Curfman McInnes if (rtol < 0.0) rtol = -rtol; 263e7e93795SLois Curfman McInnes stol = pow(kctx->rtol_last,kctx->alpha2); 2640452661fSBarry Smith if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 265e7e93795SLois Curfman McInnes } else if (kctx->version == 2) { 266e7e93795SLois Curfman McInnes rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha); 267e7e93795SLois Curfman McInnes stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha); 2680452661fSBarry Smith if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 269a8c6a408SBarry Smith } else SETERRQ( PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 or 2 are supported"); 270e7e93795SLois Curfman McInnes } 2710452661fSBarry Smith rtol = PetscMin(rtol,kctx->rtol_max); 272e7e93795SLois Curfman McInnes kctx->rtol_last = rtol; 273981c4779SBarry Smith PLogInfo(snes,"SNESConverged_EQ_LS: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n", 274e7e93795SLois Curfman McInnes snes->iter,kctx->version,rtol); 2753131a8b6SLois Curfman McInnes ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); CHKERRQ(ierr); 276e7e93795SLois Curfman McInnes kctx->norm_last = snes->norm; 2773a40ed3dSBarry Smith PetscFunctionReturn(0); 278e7e93795SLois Curfman McInnes } 279e7e93795SLois Curfman McInnes 2805615d1e5SSatish Balay #undef __FUNC__ 2815615d1e5SSatish Balay #define __FUNC__ "SNES_KSP_EW_Converged_Private" 282e7e93795SLois Curfman McInnes int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx) 283e7e93795SLois Curfman McInnes { 284e7e93795SLois Curfman McInnes SNES snes = (SNES)ctx; 285e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 286e7e93795SLois Curfman McInnes int convinfo; 287e7e93795SLois Curfman McInnes 2883a40ed3dSBarry Smith PetscFunctionBegin; 289a8c6a408SBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context set"); 290e7e93795SLois Curfman McInnes if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp); 291e7e93795SLois Curfman McInnes convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx); 292e7e93795SLois Curfman McInnes kctx->lresid_last = rnorm; 2933a40ed3dSBarry Smith if (convinfo) { 294981c4779SBarry Smith PLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm); 2953a40ed3dSBarry Smith } 2963a40ed3dSBarry Smith PetscFunctionReturn(convinfo); 297e7e93795SLois Curfman McInnes } 298e7e93795SLois Curfman McInnes 299e7e93795SLois Curfman McInnes 300