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