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