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