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