1 #define PETSCSNES_DLL 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 PetscErrorCode PETSCSNES_DLLEXPORT SNESVecViewMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 26 { 27 PetscErrorCode 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 PetscErrorCode PETSCSNES_DLLEXPORT SNESVecViewResidualMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 64 { 65 PetscErrorCode 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 PetscErrorCode PETSCSNES_DLLEXPORT SNESVecViewUpdateMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 102 { 103 PetscErrorCode 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 PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 142 { 143 PetscErrorCode 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 typedef struct { 153 PetscViewer viewer; 154 PetscReal *history; 155 } SNESRatioMonitorContext; 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "SNESRatioMonitor" 159 /*@C 160 SNESRatioMonitor - Monitors progress of the SNES solvers by printing the ratio 161 of residual norm at each iteration to the previous. 162 163 Collective on SNES 164 165 Input Parameters: 166 + snes - the SNES context 167 . its - iteration number 168 . fgnorm - 2-norm of residual (or gradient) 169 - dummy - context of monitor 170 171 Level: intermediate 172 173 .keywords: SNES, nonlinear, monitor, norm 174 175 .seealso: SNESSetMonitor(), SNESVecViewMonitor() 176 @*/ 177 PetscErrorCode PETSCSNES_DLLEXPORT SNESRatioMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 178 { 179 PetscErrorCode ierr; 180 PetscInt len; 181 PetscReal *history; 182 SNESRatioMonitorContext *ctx = (SNESRatioMonitorContext*)dummy; 183 184 PetscFunctionBegin; 185 ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr); 186 if (!its || !history || its > len) { 187 ierr = PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr); 188 } else { 189 PetscReal ratio = fgnorm/history[its-1]; 190 ierr = PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %G \n",its,fgnorm,ratio);CHKERRQ(ierr); 191 } 192 PetscFunctionReturn(0); 193 } 194 195 /* 196 If the we set the history monitor space then we must destroy it 197 */ 198 #undef __FUNCT__ 199 #define __FUNCT__ "SNESRatioMonitorDestroy" 200 PetscErrorCode SNESRatioMonitorDestroy(void *ct) 201 { 202 PetscErrorCode ierr; 203 SNESRatioMonitorContext *ctx = (SNESRatioMonitorContext*)ct; 204 205 PetscFunctionBegin; 206 ierr = PetscFree(ctx->history);CHKERRQ(ierr); 207 ierr = PetscViewerDestroy(ctx->viewer);CHKERRQ(ierr); 208 ierr = PetscFree(ctx);CHKERRQ(ierr); 209 PetscFunctionReturn(0); 210 } 211 212 #undef __FUNCT__ 213 #define __FUNCT__ "SNESSetRatioMonitor" 214 /*@C 215 SNESSetRatioMonitor - Sets SNES to use a monitor that prints the 216 ratio of the function norm at each iteration. 217 218 Collective on SNES 219 220 Input Parameters: 221 + snes - the SNES context 222 - viewer - ASCII viewer to print output 223 224 Level: intermediate 225 226 .keywords: SNES, nonlinear, monitor, norm 227 228 .seealso: SNESSetMonitor(), SNESVecViewMonitor(), SNESDefaultMonitor() 229 @*/ 230 PetscErrorCode PETSCSNES_DLLEXPORT SNESSetRatioMonitor(SNES snes,PetscViewer viewer) 231 { 232 PetscErrorCode ierr; 233 SNESRatioMonitorContext *ctx; 234 PetscReal *history; 235 236 PetscFunctionBegin; 237 if (!viewer) { 238 viewer = PETSC_VIEWER_STDOUT_(snes->comm); 239 ierr = PetscObjectReference((PetscObject)viewer);CHKERRQ(ierr); 240 } 241 ierr = PetscNew(SNESRatioMonitorContext,&ctx); 242 ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 243 if (!history) { 244 ierr = PetscMalloc(100*sizeof(PetscReal),&ctx->history);CHKERRQ(ierr); 245 ierr = SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);CHKERRQ(ierr); 246 } 247 ctx->viewer = viewer; 248 ierr = SNESSetMonitor(snes,SNESRatioMonitor,ctx,SNESRatioMonitorDestroy);CHKERRQ(ierr); 249 PetscFunctionReturn(0); 250 } 251 252 /* ---------------------------------------------------------------- */ 253 #undef __FUNCT__ 254 #define __FUNCT__ "SNESDefaultSMonitor" 255 /* 256 Default (short) SNES Monitor, same as SNESDefaultMonitor() except 257 it prints fewer digits of the residual as the residual gets smaller. 258 This is because the later digits are meaningless and are often 259 different on different machines; by using this routine different 260 machines will usually generate the same output. 261 */ 262 PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultSMonitor(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 263 { 264 PetscErrorCode ierr; 265 PetscViewer viewer = (PetscViewer) dummy; 266 267 PetscFunctionBegin; 268 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(snes->comm); 269 if (fgnorm > 1.e-9) { 270 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);CHKERRQ(ierr); 271 } else if (fgnorm > 1.e-11){ 272 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr); 273 } else { 274 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); 275 } 276 PetscFunctionReturn(0); 277 } 278 /* ---------------------------------------------------------------- */ 279 #undef __FUNCT__ 280 #define __FUNCT__ "SNESConverged_LS" 281 /*@C 282 SNESConverged_LS - Monitors the convergence of the solvers for 283 systems of nonlinear equations (default). 284 285 Collective on SNES 286 287 Input Parameters: 288 + snes - the SNES context 289 . it - the iteration (0 indicates before any Newton steps) 290 . xnorm - 2-norm of current iterate 291 . pnorm - 2-norm of current step 292 . fnorm - 2-norm of function at current iterate 293 - dummy - unused context 294 295 Output Parameter: 296 . reason - one of 297 $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol), 298 $ SNES_CONVERGED_PNORM_RELATIVE - (pnorm < xtol*xnorm), 299 $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 300 $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 301 $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 302 $ SNES_CONVERGED_ITERATING - (otherwise), 303 304 where 305 + maxf - maximum number of function evaluations, 306 set with SNESSetTolerances() 307 . nfct - number of function evaluations, 308 . abstol - absolute function norm tolerance, 309 set with SNESSetTolerances() 310 - rtol - relative function norm tolerance, set with SNESSetTolerances() 311 312 Level: intermediate 313 314 .keywords: SNES, nonlinear, default, converged, convergence 315 316 .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged() 317 @*/ 318 PetscErrorCode PETSCSNES_DLLEXPORT SNESConverged_LS(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 319 { 320 PetscErrorCode ierr; 321 322 PetscFunctionBegin; 323 *reason = SNES_CONVERGED_ITERATING; 324 325 if (!it) { 326 /* set parameter for default relative tolerance convergence test */ 327 snes->ttol = fnorm*snes->rtol; 328 } 329 if (fnorm != fnorm) { 330 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 331 *reason = SNES_DIVERGED_FNORM_NAN; 332 } else if (fnorm < snes->abstol) { 333 ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 334 *reason = SNES_CONVERGED_FNORM_ABS; 335 } else if (snes->nfuncs >= snes->max_funcs) { 336 ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 337 *reason = SNES_DIVERGED_FUNCTION_COUNT; 338 } 339 340 if (it && !*reason) { 341 if (fnorm <= snes->ttol) { 342 ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 343 *reason = SNES_CONVERGED_FNORM_RELATIVE; 344 } else if (pnorm < snes->xtol*xnorm) { 345 ierr = PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes->xtol,xnorm);CHKERRQ(ierr); 346 *reason = SNES_CONVERGED_PNORM_RELATIVE; 347 } 348 } 349 PetscFunctionReturn(0); 350 } 351 /* ------------------------------------------------------------ */ 352 #undef __FUNCT__ 353 #define __FUNCT__ "SNES_KSP_SetConvergenceTestEW" 354 /*@ 355 SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test 356 for the linear solvers within an inexact Newton method. 357 358 Collective on SNES 359 360 Input Parameter: 361 . snes - SNES context 362 363 Notes: 364 Currently, the default is to use a constant relative tolerance for 365 the inner linear solvers. Alternatively, one can use the 366 Eisenstat-Walker method, where the relative convergence tolerance 367 is reset at each Newton iteration according progress of the nonlinear 368 solver. 369 370 Level: advanced 371 372 Reference: 373 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 374 inexact Newton method", SISC 17 (1), pp.16-32, 1996. 375 376 .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 377 @*/ 378 PetscErrorCode PETSCSNES_DLLEXPORT SNES_KSP_SetConvergenceTestEW(SNES snes) 379 { 380 PetscFunctionBegin; 381 snes->ksp_ewconv = PETSC_TRUE; 382 PetscFunctionReturn(0); 383 } 384 385 #undef __FUNCT__ 386 #define __FUNCT__ "SNES_KSP_SetParametersEW" 387 /*@ 388 SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker 389 convergence criteria for the linear solvers within an inexact 390 Newton method. 391 392 Collective on SNES 393 394 Input Parameters: 395 + snes - SNES context 396 . version - version 1, 2 (default is 2) or 3 397 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 398 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 399 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 400 . alpha2 - power for safeguard 401 . gamma2 - multiplicative factor for version 2 rtol computation 402 (0 <= gamma2 <= 1) 403 - threshold - threshold for imposing safeguard (0 < threshold < 1) 404 405 Note: 406 Version 3 was contributed by ..... 407 408 Use PETSC_DEFAULT to retain the default for any of the parameters. 409 410 Level: advanced 411 412 Reference: 413 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 414 inexact Newton method", Utah State University Math. Stat. Dept. Res. 415 Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 416 417 .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 418 419 .seealso: SNES_KSP_SetConvergenceTestEW() 420 @*/ 421 PetscErrorCode PETSCSNES_DLLEXPORT SNES_KSP_SetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,PetscReal gamma2,PetscReal alpha, 422 PetscReal alpha2,PetscReal threshold) 423 { 424 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 425 426 PetscFunctionBegin; 427 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing"); 428 if (version != PETSC_DEFAULT) kctx->version = version; 429 if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 430 if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 431 if (gamma2 != PETSC_DEFAULT) kctx->gamma = gamma2; 432 if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 433 if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 434 if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 435 if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) { 436 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %G",kctx->rtol_0); 437 } 438 if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) { 439 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%G) < 1.0\n",kctx->rtol_max); 440 } 441 if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) { 442 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%G) < 1.0\n",kctx->threshold); 443 } 444 if (kctx->gamma < 0.0 || kctx->gamma > 1.0) { 445 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%G) <= 1.0\n",kctx->gamma); 446 } 447 if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) { 448 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%G) <= 2.0\n",kctx->alpha); 449 } 450 if (kctx->version != 1 && kctx->version !=2) { 451 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 and 2 are supported: %D",kctx->version); 452 } 453 PetscFunctionReturn(0); 454 } 455 456 #undef __FUNCT__ 457 #define __FUNCT__ "SNES_KSP_EW_ComputeRelativeTolerance_Private" 458 PetscErrorCode SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp) 459 { 460 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 461 PetscReal rtol = 0.0,stol; 462 PetscErrorCode ierr; 463 464 PetscFunctionBegin; 465 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists"); 466 if (!snes->iter) { /* first time in, so use the original user rtol */ 467 rtol = kctx->rtol_0; 468 } else { 469 if (kctx->version == 1) { 470 rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 471 if (rtol < 0.0) rtol = -rtol; 472 stol = pow(kctx->rtol_last,kctx->alpha2); 473 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 474 } else if (kctx->version == 2) { 475 rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha); 476 stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha); 477 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 478 } else if (kctx->version == 3) { 479 rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha); 480 /* safeguard: avoid sharp decrease of rtol */ 481 rtol = PetscMin(kctx->rtol_0,PetscMax(rtol,kctx->gamma*pow(kctx->rtol_last,kctx->alpha))); 482 /* safeguard: avoid oversolving */ 483 rtol = PetscMin(kctx->rtol_0,PetscMax(rtol,kctx->gamma*(snes->ttol)/snes->norm)); 484 485 } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 or 3 are supported: %D",kctx->version); 486 } 487 rtol = PetscMin(rtol,kctx->rtol_max); 488 kctx->rtol_last = rtol; 489 ierr = PetscInfo3(snes,"iter %D, Eisenstat-Walker (version %D) KSP rtol = %G\n",snes->iter,kctx->version,rtol);CHKERRQ(ierr); 490 ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 491 kctx->norm_last = snes->norm; 492 PetscFunctionReturn(0); 493 } 494 495 #undef __FUNCT__ 496 #define __FUNCT__ "SNES_KSP_EW_Converged_Private" 497 PetscErrorCode SNES_KSP_EW_Converged_Private(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx) 498 { 499 SNES snes = (SNES)ctx; 500 SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 501 PetscErrorCode ierr; 502 503 PetscFunctionBegin; 504 if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context set"); 505 if (!n) {ierr = SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);CHKERRQ(ierr);} 506 ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx);CHKERRQ(ierr); 507 kctx->lresid_last = rnorm; 508 if (*reason) { 509 ierr = PetscInfo2(snes,"KSP iterations=%D, rnorm=%G\n",n,rnorm);CHKERRQ(ierr); 510 } 511 PetscFunctionReturn(0); 512 } 513 514 515