1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: snesut.c,v 1.44 1999/02/01 03:22:39 curfman Exp bsmith $"; 3 #endif 4 5 #include "src/snes/snesimpl.h" /*I "snes.h" I*/ 6 7 #undef __FUNC__ 8 #define __FUNC__ "SNESVecViewMonitor" 9 /*@C 10 SNESVecViewMonitor - Monitors progress of the SNES solvers by calling 11 VecView() for the approximate solution at each iteration. 12 13 Collective on SNES 14 15 Input Parameters: 16 + snes - the SNES context 17 . its - iteration number 18 . fgnorm - 2-norm of residual (or gradient) 19 - dummy - either a viewer or PETSC_NULL 20 21 Level: intermediate 22 23 .keywords: SNES, nonlinear, vector, monitor, view 24 25 .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView() 26 @*/ 27 int SNESVecViewMonitor(SNES snes,int its,double fgnorm,void *dummy) 28 { 29 int ierr; 30 Vec x; 31 Viewer viewer = (Viewer) dummy; 32 33 PetscFunctionBegin; 34 ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr); 35 if (!viewer) { 36 MPI_Comm comm; 37 ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 38 viewer = VIEWER_DRAW_(comm); 39 } 40 ierr = VecView(x,viewer);CHKERRQ(ierr); 41 42 PetscFunctionReturn(0); 43 } 44 45 #undef __FUNC__ 46 #define __FUNC__ "SNESDefaultMonitor" 47 /*@C 48 SNESDefaultMonitor - Monitoring progress of the SNES solvers (default). 49 50 Collective on SNES 51 52 Input Parameters: 53 + snes - the SNES context 54 . its - iteration number 55 . fgnorm - 2-norm of residual (or gradient) 56 - dummy - unused context 57 58 Notes: 59 For SNES_NONLINEAR_EQUATIONS methods the routine prints the 60 residual norm at each iteration. 61 62 For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the 63 function value and gradient norm at each iteration. 64 65 Level: intermediate 66 67 .keywords: SNES, nonlinear, default, monitor, norm 68 69 .seealso: SNESSetMonitor(), SNESVecViewMonitor() 70 @*/ 71 int SNESDefaultMonitor(SNES snes,int its,double fgnorm,void *dummy) 72 { 73 PetscFunctionBegin; 74 if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 75 PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm); 76 } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 77 PetscPrintf(snes->comm,"iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm); 78 } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class"); 79 PetscFunctionReturn(0); 80 } 81 82 /* ---------------------------------------------------------------- */ 83 #undef __FUNC__ 84 #define __FUNC__ "SNESDefaultSMonitor" 85 /* 86 Default (short) SNES Monitor, same as SNESDefaultMonitor() except 87 it prints fewer digits of the residual as the residual gets smaller. 88 This is because the later digits are meaningless and are often 89 different on different machines; by using this routine different 90 machines will usually generate the same output. 91 */ 92 int SNESDefaultSMonitor(SNES snes,int its, double fgnorm,void *dummy) 93 { 94 PetscFunctionBegin; 95 if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 96 if (fgnorm > 1.e-9) { 97 PetscPrintf(snes->comm, "iter = %d, SNES Function norm %g \n",its,fgnorm); 98 } else if (fgnorm > 1.e-11){ 99 PetscPrintf(snes->comm, "iter = %d, SNES Function norm %5.3e \n",its,fgnorm); 100 } else { 101 PetscPrintf(snes->comm, "iter = %d, SNES Function norm < 1.e-11\n",its); 102 } 103 } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 104 if (fgnorm > 1.e-9) { 105 PetscPrintf(snes->comm, 106 "iter = %d, SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm); 107 } else if (fgnorm > 1.e-11) { 108 PetscPrintf(snes->comm, 109 "iter = %d, SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm); 110 } else { 111 PetscPrintf(snes->comm, 112 "iter = %d, SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc); 113 } 114 } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown method class"); 115 PetscFunctionReturn(0); 116 } 117 /* ---------------------------------------------------------------- */ 118 #undef __FUNC__ 119 #define __FUNC__ "SNESConverged_EQ_LS" 120 /*@C 121 SNESConverged_EQ_LS - Monitors the convergence of the solvers for 122 systems of nonlinear equations (default). 123 124 Collective on SNES 125 126 Input Parameters: 127 + snes - the SNES context 128 . xnorm - 2-norm of current iterate 129 . pnorm - 2-norm of current step 130 . fnorm - 2-norm of function 131 - dummy - unused context 132 133 Returns: 134 + 2 - if ( fnorm < atol ), 135 . 3 - if ( pnorm < xtol*xnorm ), 136 . 4 - if ( fnorm < rtol*fnorm0 ), 137 . -2 - if ( nfct > maxf ), 138 - 0 - otherwise, 139 140 where 141 + maxf - maximum number of function evaluations, 142 set with SNESSetTolerances() 143 . nfct - number of function evaluations, 144 . atol - absolute function norm tolerance, 145 set with SNESSetTolerances() 146 - rtol - relative function norm tolerance, set with SNESSetTolerances() 147 148 Level: intermediate 149 150 .keywords: SNES, nonlinear, default, converged, convergence 151 152 .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged() 153 @*/ 154 int SNESConverged_EQ_LS(SNES snes,double xnorm,double pnorm,double fnorm,void *dummy) 155 { 156 PetscFunctionBegin; 157 if (snes->method_class != SNES_NONLINEAR_EQUATIONS) { 158 SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only"); 159 } 160 /* Note: Reserve return code 1, -1 for compatibility with SNESConverged_EQ_TR */ 161 if (fnorm != fnorm) { 162 PLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n"); 163 PetscFunctionReturn(-3); 164 } 165 if (fnorm <= snes->ttol) { 166 PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol); 167 PetscFunctionReturn(4); 168 } 169 170 if (fnorm < snes->atol) { 171 PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol); 172 PetscFunctionReturn(2); 173 } 174 if (pnorm < snes->xtol*(xnorm)) { 175 PLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm); 176 PetscFunctionReturn(3); 177 } 178 if (snes->nfuncs > snes->max_funcs) { 179 PLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs, snes->max_funcs); 180 PetscFunctionReturn(-2); 181 } 182 PetscFunctionReturn(0); 183 } 184 /* ------------------------------------------------------------ */ 185 #undef __FUNC__ 186 #define __FUNC__ "SNES_KSP_SetConvergenceTestEW" 187 /*@ 188 SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test 189 for the linear solvers within an inexact Newton method. 190 191 Collective on SNES 192 193 Input Parameter: 194 . snes - SNES context 195 196 Notes: 197 Currently, the default is to use a constant relative tolerance for 198 the inner linear solvers. Alternatively, one can use the 199 Eisenstat-Walker method, where the relative convergence tolerance 200 is reset at each Newton iteration according progress of the nonlinear 201 solver. 202 203 Level: advanced 204 205 Reference: 206 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 207 inexact Newton method", SISC 17 (1), pp.16-32, 1996. 208 209 .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 210 @*/ 211 int SNES_KSP_SetConvergenceTestEW(SNES snes) 212 { 213 PetscFunctionBegin; 214 snes->ksp_ewconv = 1; 215 PetscFunctionReturn(0); 216 } 217 218 #undef __FUNC__ 219 #define __FUNC__ "SNES_KSP_SetParametersEW" 220 /*@ 221 SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker 222 convergence criteria for the linear solvers within an inexact 223 Newton method. 224 225 Collective on SNES 226 227 Input Parameters: 228 + snes - SNES context 229 . version - version 1 or 2 (default is 2) 230 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 231 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 232 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 233 . alpha2 - power for safeguard 234 . gamma2 - multiplicative factor for version 2 rtol computation 235 (0 <= gamma2 <= 1) 236 - threshold - threshold for imposing safeguard (0 < threshold < 1) 237 238 Note: 239 Use PETSC_DEFAULT to retain the default for any of the parameters. 240 241 Level: advanced 242 243 Reference: 244 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 245 inexact Newton method", Utah State University Math. Stat. Dept. Res. 246 Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 247 248 .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 249 250 .seealso: SNES_KSP_SetConvergenceTestEW() 251 @*/ 252 int SNES_KSP_SetParametersEW(SNES snes,int version,double rtol_0, 253 double rtol_max,double gamma2,double alpha, 254 double alpha2,double threshold) 255 { 256 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 257 258 PetscFunctionBegin; 259 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context existing"); 260 if (version != PETSC_DEFAULT) kctx->version = version; 261 if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 262 if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 263 if (gamma2 != PETSC_DEFAULT) kctx->gamma = gamma2; 264 if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 265 if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 266 if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 267 if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) { 268 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0); 269 } 270 if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) { 271 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= rtol_max < 1.0\n",kctx->rtol_max); 272 } 273 if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) { 274 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 < threshold < 1.0\n",kctx->threshold); 275 } 276 if (kctx->gamma < 0.0 || kctx->gamma > 1.0) { 277 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"0.0 <= alpha <= 1.0\n",kctx->gamma); 278 } 279 if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) { 280 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"1.0 < alpha <= 2.0\n",kctx->alpha); 281 } 282 if (kctx->version != 1 && kctx->version !=2) { 283 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 and 2 are supported: %d",kctx->version); 284 } 285 PetscFunctionReturn(0); 286 } 287 288 #undef __FUNC__ 289 #define __FUNC__ "SNES_KSP_EW_ComputeRelativeTolerance_Private" 290 int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp) 291 { 292 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 293 double rtol = 0.0, stol; 294 int ierr; 295 296 PetscFunctionBegin; 297 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context exists"); 298 if (snes->iter == 1) { 299 rtol = kctx->rtol_0; 300 } else { 301 if (kctx->version == 1) { 302 rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 303 if (rtol < 0.0) rtol = -rtol; 304 stol = pow(kctx->rtol_last,kctx->alpha2); 305 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 306 } else if (kctx->version == 2) { 307 rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha); 308 stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha); 309 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 310 } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,0,"Only versions 1 or 2 are supported: %d",kctx->version); 311 } 312 rtol = PetscMin(rtol,kctx->rtol_max); 313 kctx->rtol_last = rtol; 314 PLogInfo(snes,"SNESConverged_EQ_LS: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol); 315 ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); CHKERRQ(ierr); 316 kctx->norm_last = snes->norm; 317 PetscFunctionReturn(0); 318 } 319 320 #undef __FUNC__ 321 #define __FUNC__ "SNES_KSP_EW_Converged_Private" 322 int SNES_KSP_EW_Converged_Private(KSP ksp,int n,double rnorm,void *ctx) 323 { 324 SNES snes = (SNES)ctx; 325 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 326 int convinfo; 327 328 PetscFunctionBegin; 329 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"No Eisenstat-Walker context set"); 330 if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp); 331 convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx); 332 kctx->lresid_last = rnorm; 333 if (convinfo) { 334 PLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm); 335 } 336 PetscFunctionReturn(convinfo); 337 } 338 339 340