1 2 #include <petsc/private/snesimpl.h> /*I "petsc/private/snesimpl.h" I*/ 3 #include <petscdm.h> 4 #include <petscsection.h> 5 #include <petscblaslapack.h> 6 7 /*@C 8 SNESMonitorSolution - 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 - a viewer 18 19 Options Database Keys: 20 . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 21 22 Level: intermediate 23 24 .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()` 25 @*/ 26 PetscErrorCode SNESMonitorSolution(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 27 { 28 Vec x; 29 PetscViewer viewer = vf->viewer; 30 31 PetscFunctionBegin; 32 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 33 PetscCall(SNESGetSolution(snes,&x)); 34 PetscCall(PetscViewerPushFormat(viewer,vf->format)); 35 PetscCall(VecView(x,viewer)); 36 PetscCall(PetscViewerPopFormat(viewer)); 37 PetscFunctionReturn(0); 38 } 39 40 /*@C 41 SNESMonitorResidual - Monitors progress of the SNES solvers by calling 42 VecView() for the residual at each iteration. 43 44 Collective on SNES 45 46 Input Parameters: 47 + snes - the SNES context 48 . its - iteration number 49 . fgnorm - 2-norm of residual 50 - dummy - a viewer 51 52 Options Database Keys: 53 . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 54 55 Level: intermediate 56 57 .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()` 58 @*/ 59 PetscErrorCode SNESMonitorResidual(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 60 { 61 Vec x; 62 PetscViewer viewer = vf->viewer; 63 64 PetscFunctionBegin; 65 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 66 PetscCall(SNESGetFunction(snes,&x,NULL,NULL)); 67 PetscCall(PetscViewerPushFormat(viewer,vf->format)); 68 PetscCall(VecView(x,viewer)); 69 PetscCall(PetscViewerPopFormat(viewer)); 70 PetscFunctionReturn(0); 71 } 72 73 /*@C 74 SNESMonitorSolutionUpdate - Monitors progress of the SNES solvers by calling 75 VecView() for the UPDATE to the solution at each iteration. 76 77 Collective on SNES 78 79 Input Parameters: 80 + snes - the SNES context 81 . its - iteration number 82 . fgnorm - 2-norm of residual 83 - dummy - a viewer 84 85 Options Database Keys: 86 . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 87 88 Level: intermediate 89 90 .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()` 91 @*/ 92 PetscErrorCode SNESMonitorSolutionUpdate(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 93 { 94 Vec x; 95 PetscViewer viewer = vf->viewer; 96 97 PetscFunctionBegin; 98 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 99 PetscCall(SNESGetSolutionUpdate(snes,&x)); 100 PetscCall(PetscViewerPushFormat(viewer,vf->format)); 101 PetscCall(VecView(x,viewer)); 102 PetscCall(PetscViewerPopFormat(viewer)); 103 PetscFunctionReturn(0); 104 } 105 106 #include <petscdraw.h> 107 108 /*@C 109 KSPMonitorSNESResidual - Prints the SNES residual norm, as well as the linear residual norm, at each iteration of an iterative solver. 110 111 Collective on ksp 112 113 Input Parameters: 114 + ksp - iterative context 115 . n - iteration number 116 . rnorm - 2-norm (preconditioned) residual value (may be estimated). 117 - vf - The viewer context 118 119 Options Database Key: 120 . -snes_monitor_ksp - Activates KSPMonitorSNESResidual() 121 122 Level: intermediate 123 124 .seealso: `KSPMonitorSet()`, `KSPMonitorResidual(),KSPMonitorTrueResidualMaxNorm()` 125 @*/ 126 PetscErrorCode KSPMonitorSNESResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf) 127 { 128 PetscViewer viewer = vf->viewer; 129 PetscViewerFormat format = vf->format; 130 SNES snes = (SNES) vf->data; 131 Vec snes_solution, work1, work2; 132 PetscReal snorm; 133 PetscInt tablevel; 134 const char *prefix; 135 136 PetscFunctionBegin; 137 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 138 PetscCall(SNESGetSolution(snes, &snes_solution)); 139 PetscCall(VecDuplicate(snes_solution, &work1)); 140 PetscCall(VecDuplicate(snes_solution, &work2)); 141 PetscCall(KSPBuildSolution(ksp, work1, NULL)); 142 PetscCall(VecAYPX(work1, -1.0, snes_solution)); 143 PetscCall(SNESComputeFunction(snes, work1, work2)); 144 PetscCall(VecNorm(work2, NORM_2, &snorm)); 145 PetscCall(VecDestroy(&work1)); 146 PetscCall(VecDestroy(&work2)); 147 148 PetscCall(PetscObjectGetTabLevel((PetscObject) ksp, &tablevel)); 149 PetscCall(PetscObjectGetOptionsPrefix((PetscObject) ksp, &prefix)); 150 PetscCall(PetscViewerPushFormat(viewer, format)); 151 PetscCall(PetscViewerASCIIAddTab(viewer, tablevel)); 152 if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, " Residual norms for %s solve.\n", prefix)); 153 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Residual norm %5.3e KSP Residual norm %5.3e \n", n, (double) snorm, (double) rnorm)); 154 PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel)); 155 PetscCall(PetscViewerPopFormat(viewer)); 156 PetscFunctionReturn(0); 157 } 158 159 /*@C 160 KSPMonitorSNESResidualDrawLG - Plots the linear SNES residual norm at each iteration of an iterative solver. 161 162 Collective on ksp 163 164 Input Parameters: 165 + ksp - iterative context 166 . n - iteration number 167 . rnorm - 2-norm (preconditioned) residual value (may be estimated). 168 - vf - The viewer context 169 170 Options Database Key: 171 . -snes_monitor_ksp draw::draw_lg - Activates KSPMonitorSNESResidualDrawLG() 172 173 Level: intermediate 174 175 .seealso: `KSPMonitorSet()`, `KSPMonitorTrueResidual()` 176 @*/ 177 PetscErrorCode KSPMonitorSNESResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf) 178 { 179 PetscViewer viewer = vf->viewer; 180 PetscViewerFormat format = vf->format; 181 PetscDrawLG lg = vf->lg; 182 SNES snes = (SNES) vf->data; 183 Vec snes_solution, work1, work2; 184 PetscReal snorm; 185 KSPConvergedReason reason; 186 PetscReal x[2], y[2]; 187 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 190 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 4); 191 PetscCall(SNESGetSolution(snes, &snes_solution)); 192 PetscCall(VecDuplicate(snes_solution, &work1)); 193 PetscCall(VecDuplicate(snes_solution, &work2)); 194 PetscCall(KSPBuildSolution(ksp, work1, NULL)); 195 PetscCall(VecAYPX(work1, -1.0, snes_solution)); 196 PetscCall(SNESComputeFunction(snes, work1, work2)); 197 PetscCall(VecNorm(work2, NORM_2, &snorm)); 198 PetscCall(VecDestroy(&work1)); 199 PetscCall(VecDestroy(&work2)); 200 201 PetscCall(PetscViewerPushFormat(viewer, format)); 202 if (!n) PetscCall(PetscDrawLGReset(lg)); 203 x[0] = (PetscReal) n; 204 if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm); 205 else y[0] = -15.0; 206 x[1] = (PetscReal) n; 207 if (snorm > 0.0) y[1] = PetscLog10Real(snorm); 208 else y[1] = -15.0; 209 PetscCall(PetscDrawLGAddPoint(lg, x, y)); 210 PetscCall(KSPGetConvergedReason(ksp, &reason)); 211 if (n <= 20 || !(n % 5) || reason) { 212 PetscCall(PetscDrawLGDraw(lg)); 213 PetscCall(PetscDrawLGSave(lg)); 214 } 215 PetscCall(PetscViewerPopFormat(viewer)); 216 PetscFunctionReturn(0); 217 } 218 219 /*@C 220 KSPMonitorSNESResidualDrawLGCreate - Creates the plotter for the linear SNES residual. 221 222 Collective on ksp 223 224 Input Parameters: 225 + viewer - The PetscViewer 226 . format - The viewer format 227 - ctx - An optional user context 228 229 Output Parameter: 230 . vf - The viewer context 231 232 Level: intermediate 233 234 .seealso: `KSPMonitorSet()`, `KSPMonitorTrueResidual()` 235 @*/ 236 PetscErrorCode KSPMonitorSNESResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf) 237 { 238 const char *names[] = {"linear", "nonlinear"}; 239 240 PetscFunctionBegin; 241 PetscCall(PetscViewerAndFormatCreate(viewer, format, vf)); 242 (*vf)->data = ctx; 243 PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject) viewer), NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg)); 244 PetscFunctionReturn(0); 245 } 246 247 PetscErrorCode SNESMonitorDefaultSetUp(SNES snes, PetscViewerAndFormat *vf) 248 { 249 PetscFunctionBegin; 250 if (vf->format == PETSC_VIEWER_DRAW_LG) { 251 PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject) vf->viewer), NULL, NULL, "Log Residual Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &vf->lg)); 252 } 253 PetscFunctionReturn(0); 254 } 255 256 /*@C 257 SNESMonitorDefault - Monitors progress of the SNES solvers (default). 258 259 Collective on SNES 260 261 Input Parameters: 262 + snes - the SNES context 263 . its - iteration number 264 . fgnorm - 2-norm of residual 265 - vf - viewer and format structure 266 267 Notes: 268 This routine prints the residual norm at each iteration. 269 270 Level: intermediate 271 272 .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()` 273 @*/ 274 PetscErrorCode SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 275 { 276 PetscViewer viewer = vf->viewer; 277 PetscViewerFormat format = vf->format; 278 PetscBool isascii, isdraw; 279 280 PetscFunctionBegin; 281 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 282 PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii)); 283 PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw)); 284 PetscCall(PetscViewerPushFormat(viewer,format)); 285 if (isascii) { 286 PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel)); 287 PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " SNES Function norm %14.12e \n",its,(double)fgnorm)); 288 PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel)); 289 } else if (isdraw) { 290 if (format == PETSC_VIEWER_DRAW_LG) { 291 PetscDrawLG lg = (PetscDrawLG) vf->lg; 292 PetscReal x, y; 293 294 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,4); 295 if (!its) PetscCall(PetscDrawLGReset(lg)); 296 x = (PetscReal) its; 297 if (fgnorm > 0.0) y = PetscLog10Real(fgnorm); 298 else y = -15.0; 299 PetscCall(PetscDrawLGAddPoint(lg,&x,&y)); 300 if (its <= 20 || !(its % 5) || snes->reason) { 301 PetscCall(PetscDrawLGDraw(lg)); 302 PetscCall(PetscDrawLGSave(lg)); 303 } 304 } 305 } 306 PetscCall(PetscViewerPopFormat(viewer)); 307 PetscFunctionReturn(0); 308 } 309 310 /*@C 311 SNESMonitorScaling - Monitors the largest value in each row of the Jacobian. 312 313 Collective on SNES 314 315 Input Parameters: 316 + snes - the SNES context 317 . its - iteration number 318 . fgnorm - 2-norm of residual 319 - vf - viewer and format structure 320 321 Notes: 322 This routine prints the largest value in each row of the Jacobian 323 324 Level: intermediate 325 326 .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()` 327 @*/ 328 PetscErrorCode SNESMonitorScaling(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 329 { 330 PetscViewer viewer = vf->viewer; 331 KSP ksp; 332 Mat J; 333 Vec v; 334 335 PetscFunctionBegin; 336 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 337 PetscCall(SNESGetKSP(snes,&ksp)); 338 PetscCall(KSPGetOperators(ksp,&J,NULL)); 339 PetscCall(MatCreateVecs(J,&v,NULL)); 340 PetscCall(MatGetRowMaxAbs(J,v,NULL)); 341 PetscCall(PetscViewerPushFormat(viewer,vf->format)); 342 PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel)); 343 PetscCall(PetscViewerASCIIPrintf(viewer,"SNES Jacobian maximum row entries\n")); 344 PetscCall(VecView(v,viewer)); 345 PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel)); 346 PetscCall(PetscViewerPopFormat(viewer)); 347 PetscCall(VecDestroy(&v)); 348 PetscFunctionReturn(0); 349 } 350 351 PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes,PetscInt it,PetscReal fnorm,PetscViewerAndFormat *vf) 352 { 353 Vec X; 354 Mat J,dJ,dJdense; 355 PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*); 356 PetscInt n; 357 PetscBLASInt nb = 0,lwork; 358 PetscReal *eigr,*eigi; 359 PetscScalar *work; 360 PetscScalar *a; 361 362 PetscFunctionBegin; 363 if (it == 0) PetscFunctionReturn(0); 364 /* create the difference between the current update and the current jacobian */ 365 PetscCall(SNESGetSolution(snes,&X)); 366 PetscCall(SNESGetJacobian(snes,NULL,&J,&func,NULL)); 367 PetscCall(MatDuplicate(J,MAT_COPY_VALUES,&dJ)); 368 PetscCall(SNESComputeJacobian(snes,X,dJ,dJ)); 369 PetscCall(MatAXPY(dJ,-1.0,J,SAME_NONZERO_PATTERN)); 370 371 /* compute the spectrum directly */ 372 PetscCall(MatConvert(dJ,MATSEQDENSE,MAT_INITIAL_MATRIX,&dJdense)); 373 PetscCall(MatGetSize(dJ,&n,NULL)); 374 PetscCall(PetscBLASIntCast(n,&nb)); 375 lwork = 3*nb; 376 PetscCall(PetscMalloc1(n,&eigr)); 377 PetscCall(PetscMalloc1(n,&eigi)); 378 PetscCall(PetscMalloc1(lwork,&work)); 379 PetscCall(MatDenseGetArray(dJdense,&a)); 380 #if !defined(PETSC_USE_COMPLEX) 381 { 382 PetscBLASInt lierr; 383 PetscInt i; 384 PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 385 PetscStackCallBLAS("LAPACKgeev",LAPACKgeev_("N","N",&nb,a,&nb,eigr,eigi,NULL,&nb,NULL,&nb,work,&lwork,&lierr)); 386 PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"geev() error %" PetscBLASInt_FMT,lierr); 387 PetscCall(PetscFPTrapPop()); 388 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes),"Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n",it,it-1)); 389 for (i=0;i<n;i++) { 390 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes),"%5" PetscInt_FMT ": %20.5g + %20.5gi\n",i,(double)eigr[i],(double)eigi[i])); 391 } 392 } 393 PetscCall(MatDenseRestoreArray(dJdense,&a)); 394 PetscCall(MatDestroy(&dJ)); 395 PetscCall(MatDestroy(&dJdense)); 396 PetscCall(PetscFree(eigr)); 397 PetscCall(PetscFree(eigi)); 398 PetscCall(PetscFree(work)); 399 PetscFunctionReturn(0); 400 #else 401 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded for complex"); 402 #endif 403 } 404 405 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES,PetscInt,PetscReal*); 406 407 PetscErrorCode SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per) 408 { 409 Vec resid; 410 PetscReal rmax,pwork; 411 PetscInt i,n,N; 412 PetscScalar *r; 413 414 PetscFunctionBegin; 415 PetscCall(SNESGetFunction(snes,&resid,NULL,NULL)); 416 PetscCall(VecNorm(resid,NORM_INFINITY,&rmax)); 417 PetscCall(VecGetLocalSize(resid,&n)); 418 PetscCall(VecGetSize(resid,&N)); 419 PetscCall(VecGetArray(resid,&r)); 420 pwork = 0.0; 421 for (i=0; i<n; i++) { 422 pwork += (PetscAbsScalar(r[i]) > .20*rmax); 423 } 424 PetscCall(MPIU_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes))); 425 PetscCall(VecRestoreArray(resid,&r)); 426 *per = *per/N; 427 PetscFunctionReturn(0); 428 } 429 430 /*@C 431 SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value. 432 433 Collective on SNES 434 435 Input Parameters: 436 + snes - iterative context 437 . it - iteration number 438 . rnorm - 2-norm (preconditioned) residual value (may be estimated). 439 - dummy - unused monitor context 440 441 Options Database Key: 442 . -snes_monitor_range - Activates SNESMonitorRange() 443 444 Level: intermediate 445 446 .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()` 447 @*/ 448 PetscErrorCode SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,PetscViewerAndFormat *vf) 449 { 450 PetscReal perc,rel; 451 PetscViewer viewer = vf->viewer; 452 /* should be in a MonitorRangeContext */ 453 static PetscReal prev; 454 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 457 if (!it) prev = rnorm; 458 PetscCall(SNESMonitorRange_Private(snes,it,&perc)); 459 460 rel = (prev - rnorm)/prev; 461 prev = rnorm; 462 PetscCall(PetscViewerPushFormat(viewer,vf->format)); 463 PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel)); 464 PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " SNES preconditioned resid norm %14.12e Percent values above 20 percent of maximum %5.2g relative decrease %5.2e ratio %5.2e \n",it,(double)rnorm,(double)(100.0*perc),(double)rel,(double)(rel/perc))); 465 PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel)); 466 PetscCall(PetscViewerPopFormat(viewer)); 467 PetscFunctionReturn(0); 468 } 469 470 /*@C 471 SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio 472 of residual norm at each iteration to the previous. 473 474 Collective on SNES 475 476 Input Parameters: 477 + snes - the SNES context 478 . its - iteration number 479 . fgnorm - 2-norm of residual (or gradient) 480 - dummy - context of monitor 481 482 Level: intermediate 483 484 Notes: 485 Insure that SNESMonitorRatio() is called when you set this monitor 486 .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRatio()` 487 @*/ 488 PetscErrorCode SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 489 { 490 PetscInt len; 491 PetscReal *history; 492 PetscViewer viewer = vf->viewer; 493 494 PetscFunctionBegin; 495 PetscCall(SNESGetConvergenceHistory(snes,&history,NULL,&len)); 496 PetscCall(PetscViewerPushFormat(viewer,vf->format)); 497 PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel)); 498 if (!its || !history || its > len) { 499 PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " SNES Function norm %14.12e \n",its,(double)fgnorm)); 500 } else { 501 PetscReal ratio = fgnorm/history[its-1]; 502 PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e \n",its,(double)fgnorm,(double)ratio)); 503 } 504 PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel)); 505 PetscCall(PetscViewerPopFormat(viewer)); 506 PetscFunctionReturn(0); 507 } 508 509 /*@C 510 SNESMonitorRatioSetUp - Insures the SNES object is saving its history since this monitor needs access to it 511 512 Collective on SNES 513 514 Input Parameters: 515 + snes - the SNES context 516 - viewer - the PetscViewer object (ignored) 517 518 Level: intermediate 519 520 .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()` 521 @*/ 522 PetscErrorCode SNESMonitorRatioSetUp(SNES snes,PetscViewerAndFormat *vf) 523 { 524 PetscReal *history; 525 526 PetscFunctionBegin; 527 PetscCall(SNESGetConvergenceHistory(snes,&history,NULL,NULL)); 528 if (!history) { 529 PetscCall(SNESSetConvergenceHistory(snes,NULL,NULL,100,PETSC_TRUE)); 530 } 531 PetscFunctionReturn(0); 532 } 533 534 /* ---------------------------------------------------------------- */ 535 /* 536 Default (short) SNES Monitor, same as SNESMonitorDefault() except 537 it prints fewer digits of the residual as the residual gets smaller. 538 This is because the later digits are meaningless and are often 539 different on different machines; by using this routine different 540 machines will usually generate the same output. 541 542 Deprecated: Intentionally has no manual page 543 */ 544 PetscErrorCode SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 545 { 546 PetscViewer viewer = vf->viewer; 547 548 PetscFunctionBegin; 549 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 550 PetscCall(PetscViewerPushFormat(viewer,vf->format)); 551 PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel)); 552 if (fgnorm > 1.e-9) { 553 PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " SNES Function norm %g \n",its,(double)fgnorm)); 554 } else if (fgnorm > 1.e-11) { 555 PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " SNES Function norm %5.3e \n",its,(double)fgnorm)); 556 } else { 557 PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " SNES Function norm < 1.e-11\n",its)); 558 } 559 PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel)); 560 PetscCall(PetscViewerPopFormat(viewer)); 561 PetscFunctionReturn(0); 562 } 563 564 /*@C 565 SNESMonitorDefaultField - Monitors progress of the SNES solvers, separated into fields. 566 567 Collective on SNES 568 569 Input Parameters: 570 + snes - the SNES context 571 . its - iteration number 572 . fgnorm - 2-norm of residual 573 - ctx - the PetscViewer 574 575 Notes: 576 This routine uses the DM attached to the residual vector 577 578 Level: intermediate 579 580 .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()` 581 @*/ 582 PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 583 { 584 PetscViewer viewer = vf->viewer; 585 Vec r; 586 DM dm; 587 PetscReal res[256]; 588 PetscInt tablevel; 589 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 592 PetscCall(SNESGetFunction(snes, &r, NULL, NULL)); 593 PetscCall(VecGetDM(r, &dm)); 594 if (!dm) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf)); 595 else { 596 PetscSection s, gs; 597 PetscInt Nf, f; 598 599 PetscCall(DMGetLocalSection(dm, &s)); 600 PetscCall(DMGetGlobalSection(dm, &gs)); 601 if (!s || !gs) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf)); 602 PetscCall(PetscSectionGetNumFields(s, &Nf)); 603 PetscCheck(Nf <= 256,PetscObjectComm((PetscObject) snes), PETSC_ERR_SUP, "Do not support %" PetscInt_FMT " fields > 256", Nf); 604 PetscCall(PetscSectionVecNorm(s, gs, r, NORM_2, res)); 605 PetscCall(PetscObjectGetTabLevel((PetscObject) snes, &tablevel)); 606 PetscCall(PetscViewerPushFormat(viewer,vf->format)); 607 PetscCall(PetscViewerASCIIAddTab(viewer, tablevel)); 608 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double) fgnorm)); 609 for (f = 0; f < Nf; ++f) { 610 if (f) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 611 PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f])); 612 } 613 PetscCall(PetscViewerASCIIPrintf(viewer, "] \n")); 614 PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel)); 615 PetscCall(PetscViewerPopFormat(viewer)); 616 } 617 PetscFunctionReturn(0); 618 } 619 /* ---------------------------------------------------------------- */ 620 /*@C 621 SNESConvergedDefault - Default onvergence test of the solvers for 622 systems of nonlinear equations. 623 624 Collective on SNES 625 626 Input Parameters: 627 + snes - the SNES context 628 . it - the iteration (0 indicates before any Newton steps) 629 . xnorm - 2-norm of current iterate 630 . snorm - 2-norm of current step 631 . fnorm - 2-norm of function at current iterate 632 - dummy - unused context 633 634 Output Parameter: 635 . reason - one of 636 $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol), 637 $ SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm), 638 $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 639 $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 640 $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 641 $ SNES_CONVERGED_ITERATING - (otherwise), 642 $ SNES_DIVERGED_DTOL - (fnorm > divtol*snes->fnorm0) 643 644 where 645 + maxf - maximum number of function evaluations, set with SNESSetTolerances() 646 . nfct - number of function evaluations, 647 . abstol - absolute function norm tolerance, set with SNESSetTolerances() 648 . rtol - relative function norm tolerance, set with SNESSetTolerances() 649 . divtol - divergence tolerance, set with SNESSetDivergenceTolerance() 650 - fnorm0 - 2-norm of the function at the initial solution (initial guess; zeroth iteration) 651 652 Options Database Keys: 653 + -snes_stol - convergence tolerance in terms of the norm of the change in the solution between steps 654 . -snes_atol <abstol> - absolute tolerance of residual norm 655 . -snes_rtol <rtol> - relative decrease in tolerance norm from the initial 2-norm of the solution 656 . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 657 . -snes_max_funcs <max_funcs> - maximum number of function evaluations 658 . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 659 - -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 660 661 Level: intermediate 662 663 .seealso: `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()` 664 @*/ 665 PetscErrorCode SNESConvergedDefault(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 666 { 667 PetscFunctionBegin; 668 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 669 PetscValidPointer(reason,6); 670 671 *reason = SNES_CONVERGED_ITERATING; 672 673 if (!it) { 674 /* set parameter for default relative tolerance convergence test */ 675 snes->ttol = fnorm*snes->rtol; 676 snes->rnorm0 = fnorm; 677 } 678 if (PetscIsInfOrNanReal(fnorm)) { 679 PetscCall(PetscInfo(snes,"Failed to converged, function norm is NaN\n")); 680 *reason = SNES_DIVERGED_FNORM_NAN; 681 } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) { 682 PetscCall(PetscInfo(snes,"Converged due to function norm %14.12e < %14.12e\n",(double)fnorm,(double)snes->abstol)); 683 *reason = SNES_CONVERGED_FNORM_ABS; 684 } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) { 685 PetscCall(PetscInfo(snes,"Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n",snes->nfuncs,snes->max_funcs)); 686 *reason = SNES_DIVERGED_FUNCTION_COUNT; 687 } 688 689 if (it && !*reason) { 690 if (fnorm <= snes->ttol) { 691 PetscCall(PetscInfo(snes,"Converged due to function norm %14.12e < %14.12e (relative tolerance)\n",(double)fnorm,(double)snes->ttol)); 692 *reason = SNES_CONVERGED_FNORM_RELATIVE; 693 } else if (snorm < snes->stol*xnorm) { 694 PetscCall(PetscInfo(snes,"Converged due to small update length: %14.12e < %14.12e * %14.12e\n",(double)snorm,(double)snes->stol,(double)xnorm)); 695 *reason = SNES_CONVERGED_SNORM_RELATIVE; 696 } else if (snes->divtol > 0 && (fnorm > snes->divtol*snes->rnorm0)) { 697 PetscCall(PetscInfo(snes,"Diverged due to increase in function norm: %14.12e > %14.12e * %14.12e\n",(double)fnorm,(double)snes->divtol,(double)snes->rnorm0)); 698 *reason = SNES_DIVERGED_DTOL; 699 } 700 701 } 702 PetscFunctionReturn(0); 703 } 704 705 /*@C 706 SNESConvergedSkip - Convergence test for SNES that NEVER returns as 707 converged, UNLESS the maximum number of iteration have been reached. 708 709 Logically Collective on SNES 710 711 Input Parameters: 712 + snes - the SNES context 713 . it - the iteration (0 indicates before any Newton steps) 714 . xnorm - 2-norm of current iterate 715 . snorm - 2-norm of current step 716 . fnorm - 2-norm of function at current iterate 717 - dummy - unused context 718 719 Output Parameter: 720 . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 721 722 Notes: 723 Convergence is then declared after a fixed number of iterations have been used. 724 725 Level: advanced 726 727 .seealso: `SNESConvergedDefault()`, `SNESSetConvergenceTest()` 728 @*/ 729 PetscErrorCode SNESConvergedSkip(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 730 { 731 PetscFunctionBegin; 732 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 733 PetscValidPointer(reason,6); 734 735 *reason = SNES_CONVERGED_ITERATING; 736 737 if (fnorm != fnorm) { 738 PetscCall(PetscInfo(snes,"Failed to converged, function norm is NaN\n")); 739 *reason = SNES_DIVERGED_FNORM_NAN; 740 } else if (it == snes->max_its) { 741 *reason = SNES_CONVERGED_ITS; 742 } 743 PetscFunctionReturn(0); 744 } 745 746 /*@C 747 SNESSetWorkVecs - Gets a number of work vectors. 748 749 Input Parameters: 750 + snes - the SNES context 751 - nw - number of work vectors to allocate 752 753 Level: developer 754 755 @*/ 756 PetscErrorCode SNESSetWorkVecs(SNES snes,PetscInt nw) 757 { 758 DM dm; 759 Vec v; 760 761 PetscFunctionBegin; 762 if (snes->work) PetscCall(VecDestroyVecs(snes->nwork,&snes->work)); 763 snes->nwork = nw; 764 765 PetscCall(SNESGetDM(snes, &dm)); 766 PetscCall(DMGetGlobalVector(dm, &v)); 767 PetscCall(VecDuplicateVecs(v,snes->nwork,&snes->work)); 768 PetscCall(DMRestoreGlobalVector(dm, &v)); 769 PetscCall(PetscLogObjectParents(snes,nw,snes->work)); 770 PetscFunctionReturn(0); 771 } 772