1 /*$Id: snesut.c,v 1.66 2001/08/06 21:17:07 bsmith Exp $*/ 2 3 #include "src/snes/snesimpl.h" /*I "petscsnes.h" I*/ 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "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 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 PetscViewer viewer = (PetscViewer) 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 = PETSC_VIEWER_DRAW_(comm); 37 } 38 ierr = VecView(x,viewer);CHKERRQ(ierr); 39 40 PetscFunctionReturn(0); 41 } 42 43 #undef __FUNCT__ 44 #define __FUNCT__ "SNESVecViewResidualMonitor" 45 /*@C 46 SNESVecViewResidualMonitor - Monitors progress of the SNES solvers by calling 47 VecView() for the residual 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 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 SNESVecViewResidualMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 64 { 65 int ierr; 66 Vec x; 67 PetscViewer viewer = (PetscViewer) dummy; 68 69 PetscFunctionBegin; 70 ierr = SNESGetFunction(snes,&x,0,0);CHKERRQ(ierr); 71 if (!viewer) { 72 MPI_Comm comm; 73 ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 74 viewer = PETSC_VIEWER_DRAW_(comm); 75 } 76 ierr = VecView(x,viewer);CHKERRQ(ierr); 77 78 PetscFunctionReturn(0); 79 } 80 81 #undef __FUNCT__ 82 #define __FUNCT__ "SNESVecViewUpdateMonitor" 83 /*@C 84 SNESVecViewUpdateMonitor - Monitors progress of the SNES solvers by calling 85 VecView() for the UPDATE to the solution at each iteration. 86 87 Collective on SNES 88 89 Input Parameters: 90 + snes - the SNES context 91 . its - iteration number 92 . fgnorm - 2-norm of residual 93 - dummy - either a viewer or PETSC_NULL 94 95 Level: intermediate 96 97 .keywords: SNES, nonlinear, vector, monitor, view 98 99 .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView() 100 @*/ 101 int SNESVecViewUpdateMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 102 { 103 int ierr; 104 Vec x; 105 PetscViewer viewer = (PetscViewer) dummy; 106 107 PetscFunctionBegin; 108 ierr = SNESGetSolutionUpdate(snes,&x);CHKERRQ(ierr); 109 if (!viewer) { 110 MPI_Comm comm; 111 ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 112 viewer = PETSC_VIEWER_DRAW_(comm); 113 } 114 ierr = VecView(x,viewer);CHKERRQ(ierr); 115 116 PetscFunctionReturn(0); 117 } 118 119 #undef __FUNCT__ 120 #define __FUNCT__ "SNESDefaultMonitor" 121 /*@C 122 SNESDefaultMonitor - Monitors progress of the SNES solvers (default). 123 124 Collective on SNES 125 126 Input Parameters: 127 + snes - the SNES context 128 . its - iteration number 129 . fgnorm - 2-norm of residual 130 - dummy - unused context 131 132 Notes: 133 This routine prints the residual norm at each iteration. 134 135 Level: intermediate 136 137 .keywords: SNES, nonlinear, default, monitor, norm 138 139 .seealso: SNESSetMonitor(), SNESVecViewMonitor() 140 @*/ 141 int SNESDefaultMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 142 { 143 int ierr; 144 PetscViewer viewer = (PetscViewer) dummy; 145 146 PetscFunctionBegin; 147 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(snes->comm); 148 ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr); 149 PetscFunctionReturn(0); 150 } 151 152 #undef __FUNCT__ 153 #define __FUNCT__ "SNESRatioMonitor" 154 /*@C 155 SNESRatioMonitor - Monitors progress of the SNES solvers by printing the ratio 156 of residual norm at each iteration to the previous. 157 158 Collective on SNES 159 160 Input Parameters: 161 + snes - the SNES context 162 . its - iteration number 163 . fgnorm - 2-norm of residual (or gradient) 164 - dummy - unused context 165 166 Level: intermediate 167 168 .keywords: SNES, nonlinear, monitor, norm 169 170 .seealso: SNESSetMonitor(), SNESVecViewMonitor() 171 @*/ 172 int SNESRatioMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 173 { 174 int ierr,len; 175 PetscReal *history; 176 PetscViewer viewer; 177 178 PetscFunctionBegin; 179 viewer = PETSC_VIEWER_STDOUT_(snes->comm); 180 181 ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr); 182 if (its == 0 || !history || its > len) { 183 ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr); 184 } else { 185 PetscReal ratio = fgnorm/history[its-1]; 186 ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e %g \n",its,fgnorm,ratio);CHKERRQ(ierr); 187 } 188 PetscFunctionReturn(0); 189 } 190 191 /* 192 If the we set the history monitor space then we must destroy it 193 */ 194 #undef __FUNCT__ 195 #define __FUNCT__ "SNESRatioMonitorDestroy" 196 int SNESRatioMonitorDestroy(void *history) 197 { 198 int ierr; 199 200 PetscFunctionBegin; 201 ierr = PetscFree(history);CHKERRQ(ierr); 202 PetscFunctionReturn(0); 203 } 204 205 #undef __FUNCT__ 206 #define __FUNCT__ "SNESSetRatioMonitor" 207 /*@C 208 SNESSetRatioMonitor - Sets SNES to use a monitor that prints the 209 ratio of the function norm at each iteration. 210 211 Collective on SNES 212 213 Input Parameters: 214 . snes - the SNES context 215 216 Level: intermediate 217 218 .keywords: SNES, nonlinear, monitor, norm 219 220 .seealso: SNESSetMonitor(), SNESVecViewMonitor(), SNESDefaultMonitor() 221 @*/ 222 int SNESSetRatioMonitor(SNES snes) 223 { 224 int ierr; 225 PetscReal *history; 226 227 PetscFunctionBegin; 228 229 ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 230 if (!history) { 231 ierr = PetscMalloc(100*sizeof(double),&history);CHKERRQ(ierr); 232 ierr = SNESSetConvergenceHistory(snes,history,0,100,PETSC_TRUE);CHKERRQ(ierr); 233 ierr = SNESSetMonitor(snes,SNESRatioMonitor,history,SNESRatioMonitorDestroy);CHKERRQ(ierr); 234 } else { 235 ierr = SNESSetMonitor(snes,SNESRatioMonitor,0,0);CHKERRQ(ierr); 236 } 237 PetscFunctionReturn(0); 238 } 239 240 /* ---------------------------------------------------------------- */ 241 #undef __FUNCT__ 242 #define __FUNCT__ "SNESDefaultSMonitor" 243 /* 244 Default (short) SNES Monitor, same as SNESDefaultMonitor() except 245 it prints fewer digits of the residual as the residual gets smaller. 246 This is because the later digits are meaningless and are often 247 different on different machines; by using this routine different 248 machines will usually generate the same output. 249 */ 250 int SNESDefaultSMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 251 { 252 int ierr; 253 254 PetscFunctionBegin; 255 if (fgnorm > 1.e-9) { 256 ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr); 257 } else if (fgnorm > 1.e-11){ 258 ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr); 259 } else { 260 ierr = PetscPrintf(snes->comm,"%3d SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); 261 } 262 PetscFunctionReturn(0); 263 } 264 /* ---------------------------------------------------------------- */ 265 #undef __FUNCT__ 266 #define __FUNCT__ "SNESConverged_LS" 267 /*@C 268 SNESConverged_LS - Monitors the convergence of the solvers for 269 systems of nonlinear equations (default). 270 271 Collective on SNES 272 273 Input Parameters: 274 + snes - the SNES context 275 . xnorm - 2-norm of current iterate 276 . pnorm - 2-norm of current step 277 . fnorm - 2-norm of function 278 - dummy - unused context 279 280 Output Parameter: 281 . reason - one of 282 $ SNES_CONVERGED_FNORM_ABS - (fnorm < atol), 283 $ SNES_CONVERGED_PNORM_RELATIVE - (pnorm < xtol*xnorm), 284 $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 285 $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 286 $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 287 $ SNES_CONVERGED_ITERATING - (otherwise), 288 289 where 290 + maxf - maximum number of function evaluations, 291 set with SNESSetTolerances() 292 . nfct - number of function evaluations, 293 . atol - absolute function norm tolerance, 294 set with SNESSetTolerances() 295 - rtol - relative function norm tolerance, set with SNESSetTolerances() 296 297 Level: intermediate 298 299 .keywords: SNES, nonlinear, default, converged, convergence 300 301 .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged() 302 @*/ 303 int SNESConverged_LS(SNES snes,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 304 { 305 PetscFunctionBegin; 306 if (fnorm != fnorm) { 307 PetscLogInfo(snes,"SNESConverged_LS:Failed to converged, function norm is NaN\n"); 308 *reason = SNES_DIVERGED_FNORM_NAN; 309 } else if (fnorm <= snes->ttol) { 310 PetscLogInfo(snes,"SNESConverged_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol); 311 *reason = SNES_CONVERGED_FNORM_RELATIVE; 312 } else if (fnorm < snes->atol) { 313 PetscLogInfo(snes,"SNESConverged_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol); 314 *reason = SNES_CONVERGED_FNORM_ABS; 315 } else if (pnorm < snes->xtol*xnorm) { 316 PetscLogInfo(snes,"SNESConverged_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm); 317 *reason = SNES_CONVERGED_PNORM_RELATIVE; 318 } else if (snes->nfuncs > snes->max_funcs) { 319 PetscLogInfo(snes,"SNESConverged_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs,snes->max_funcs); 320 *reason = SNES_DIVERGED_FUNCTION_COUNT ; 321 } else { 322 *reason = SNES_CONVERGED_ITERATING; 323 } 324 PetscFunctionReturn(0); 325 } 326 /* ------------------------------------------------------------ */ 327 #undef __FUNCT__ 328 #define __FUNCT__ "SNES_KSP_SetConvergenceTestEW" 329 /*@ 330 SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test 331 for the linear solvers within an inexact Newton method. 332 333 Collective on SNES 334 335 Input Parameter: 336 . snes - SNES context 337 338 Notes: 339 Currently, the default is to use a constant relative tolerance for 340 the inner linear solvers. Alternatively, one can use the 341 Eisenstat-Walker method, where the relative convergence tolerance 342 is reset at each Newton iteration according progress of the nonlinear 343 solver. 344 345 Level: advanced 346 347 Reference: 348 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 349 inexact Newton method", SISC 17 (1), pp.16-32, 1996. 350 351 .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 352 @*/ 353 int SNES_KSP_SetConvergenceTestEW(SNES snes) 354 { 355 PetscFunctionBegin; 356 snes->ksp_ewconv = PETSC_TRUE; 357 PetscFunctionReturn(0); 358 } 359 360 #undef __FUNCT__ 361 #define __FUNCT__ "SNES_KSP_SetParametersEW" 362 /*@ 363 SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker 364 convergence criteria for the linear solvers within an inexact 365 Newton method. 366 367 Collective on SNES 368 369 Input Parameters: 370 + snes - SNES context 371 . version - version 1 or 2 (default is 2) 372 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 373 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 374 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 375 . alpha2 - power for safeguard 376 . gamma2 - multiplicative factor for version 2 rtol computation 377 (0 <= gamma2 <= 1) 378 - threshold - threshold for imposing safeguard (0 < threshold < 1) 379 380 Note: 381 Use PETSC_DEFAULT to retain the default for any of the parameters. 382 383 Level: advanced 384 385 Reference: 386 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 387 inexact Newton method", Utah State University Math. Stat. Dept. Res. 388 Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 389 390 .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 391 392 .seealso: SNES_KSP_SetConvergenceTestEW() 393 @*/ 394 int SNES_KSP_SetParametersEW(SNES snes,int version,PetscReal rtol_0, 395 PetscReal rtol_max,PetscReal gamma2,PetscReal alpha, 396 PetscReal alpha2,PetscReal threshold) 397 { 398 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 399 400 PetscFunctionBegin; 401 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing"); 402 if (version != PETSC_DEFAULT) kctx->version = version; 403 if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 404 if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 405 if (gamma2 != PETSC_DEFAULT) kctx->gamma = gamma2; 406 if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 407 if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 408 if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 409 if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) { 410 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0); 411 } 412 if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) { 413 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%g) < 1.0\n",kctx->rtol_max); 414 } 415 if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) { 416 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%g) < 1.0\n",kctx->threshold); 417 } 418 if (kctx->gamma < 0.0 || kctx->gamma > 1.0) { 419 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%g) <= 1.0\n",kctx->gamma); 420 } 421 if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) { 422 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%g) <= 2.0\n",kctx->alpha); 423 } 424 if (kctx->version != 1 && kctx->version !=2) { 425 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 and 2 are supported: %d",kctx->version); 426 } 427 PetscFunctionReturn(0); 428 } 429 430 #undef __FUNCT__ 431 #define __FUNCT__ "SNES_KSP_EW_ComputeRelativeTolerance_Private" 432 int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp) 433 { 434 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 435 PetscReal rtol = 0.0,stol; 436 int ierr; 437 438 PetscFunctionBegin; 439 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists"); 440 if (!snes->iter) { /* first time in, so use the original user rtol */ 441 rtol = kctx->rtol_0; 442 } else { 443 if (kctx->version == 1) { 444 rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 445 if (rtol < 0.0) rtol = -rtol; 446 stol = pow(kctx->rtol_last,kctx->alpha2); 447 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 448 } else if (kctx->version == 2) { 449 rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha); 450 stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha); 451 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 452 } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 or 2 are supported: %d",kctx->version); 453 } 454 rtol = PetscMin(rtol,kctx->rtol_max); 455 kctx->rtol_last = rtol; 456 PetscLogInfo(snes,"SNES_KSP_EW_ComputeRelativeTolerance_Private: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol); 457 ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 458 kctx->norm_last = snes->norm; 459 PetscFunctionReturn(0); 460 } 461 462 #undef __FUNCT__ 463 #define __FUNCT__ "SNES_KSP_EW_Converged_Private" 464 int SNES_KSP_EW_Converged_Private(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx) 465 { 466 SNES snes = (SNES)ctx; 467 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 468 int ierr; 469 470 PetscFunctionBegin; 471 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context set"); 472 if (n == 0) {ierr = SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);CHKERRQ(ierr);} 473 ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx);CHKERRQ(ierr); 474 kctx->lresid_last = rnorm; 475 if (*reason) { 476 PetscLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm); 477 } 478 PetscFunctionReturn(0); 479 } 480 481 482