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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_snes), `KSP`, `SNES`, `PetscViewerFormat`, `PetscViewerAndFormat`, `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: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorFunction()`, `SNESMonitorSolution()`, `SNESMonitorResidual()`, 296 `SNESMonitorSolutionUpdate()`, `SNESMonitorDefault()`, `SNESMonitorScaling()`, `SNESMonitorRange()`, `SNESMonitorRatio()`, 297 `SNESMonitorDefaultField()`, `PetscViewerFormat`, `PetscViewerAndFormat` 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: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `SNESMonitorJacUpdateSpectrum()`, 375 `PetscViewerFormat`, `PetscViewerAndFormat` 376 @*/ 377 PetscErrorCode SNESMonitorScaling(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 378 { 379 PetscViewer viewer = vf->viewer; 380 KSP ksp; 381 Mat J; 382 Vec v; 383 384 PetscFunctionBegin; 385 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 386 PetscCall(SNESGetKSP(snes, &ksp)); 387 PetscCall(KSPGetOperators(ksp, &J, NULL)); 388 PetscCall(MatCreateVecs(J, &v, NULL)); 389 PetscCall(MatGetRowMaxAbs(J, v, NULL)); 390 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 391 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 392 PetscCall(PetscViewerASCIIPrintf(viewer, "SNES Jacobian maximum row entries\n")); 393 PetscCall(VecView(v, viewer)); 394 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 395 PetscCall(PetscViewerPopFormat(viewer)); 396 PetscCall(VecDestroy(&v)); 397 PetscFunctionReturn(PETSC_SUCCESS); 398 } 399 400 /*@C 401 SNESMonitorJacUpdateSpectrum - Monitors the spectrun of the change in the Jacobian from the last Jacobian evaluation 402 403 Collective 404 405 Input Parameters: 406 + snes - the `SNES` context 407 . its - iteration number 408 . fgnorm - 2-norm of residual 409 - vf - viewer and format structure 410 411 Options Database Key: 412 . -snes_monitor_jacupdate_spectrum - activates this monitor 413 414 Level: intermediate 415 416 Notes: 417 This routine prints the eigenvalues of the difference in the Jacobians 418 419 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 420 to be used during the `SNES` solve. 421 422 .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `PetscViewerFormat`, `PetscViewerAndFormat` 423 @*/ 424 PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes, PetscInt it, PetscReal fnorm, PetscViewerAndFormat *vf) 425 { 426 Vec X; 427 Mat J, dJ, dJdense; 428 PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *); 429 PetscInt n; 430 PetscBLASInt nb = 0, lwork; 431 PetscReal *eigr, *eigi; 432 PetscScalar *work; 433 PetscScalar *a; 434 435 PetscFunctionBegin; 436 if (it == 0) PetscFunctionReturn(PETSC_SUCCESS); 437 /* create the difference between the current update and the current Jacobian */ 438 PetscCall(SNESGetSolution(snes, &X)); 439 PetscCall(SNESGetJacobian(snes, NULL, &J, &func, NULL)); 440 PetscCall(MatDuplicate(J, MAT_COPY_VALUES, &dJ)); 441 PetscCall(SNESComputeJacobian(snes, X, dJ, dJ)); 442 PetscCall(MatAXPY(dJ, -1.0, J, SAME_NONZERO_PATTERN)); 443 444 /* compute the spectrum directly */ 445 PetscCall(MatConvert(dJ, MATSEQDENSE, MAT_INITIAL_MATRIX, &dJdense)); 446 PetscCall(MatGetSize(dJ, &n, NULL)); 447 PetscCall(PetscBLASIntCast(n, &nb)); 448 lwork = 3 * nb; 449 PetscCall(PetscMalloc1(n, &eigr)); 450 PetscCall(PetscMalloc1(n, &eigi)); 451 PetscCall(PetscMalloc1(lwork, &work)); 452 PetscCall(MatDenseGetArray(dJdense, &a)); 453 #if !defined(PETSC_USE_COMPLEX) 454 { 455 PetscBLASInt lierr; 456 PetscInt i; 457 PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 458 PetscCallBLAS("LAPACKgeev", LAPACKgeev_("N", "N", &nb, a, &nb, eigr, eigi, NULL, &nb, NULL, &nb, work, &lwork, &lierr)); 459 PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "geev() error %" PetscBLASInt_FMT, lierr); 460 PetscCall(PetscFPTrapPop()); 461 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n", it, it - 1)); 462 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])); 463 } 464 PetscCall(MatDenseRestoreArray(dJdense, &a)); 465 PetscCall(MatDestroy(&dJ)); 466 PetscCall(MatDestroy(&dJdense)); 467 PetscCall(PetscFree(eigr)); 468 PetscCall(PetscFree(eigi)); 469 PetscCall(PetscFree(work)); 470 PetscFunctionReturn(PETSC_SUCCESS); 471 #else 472 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded for complex"); 473 #endif 474 } 475 476 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 477 478 PetscErrorCode SNESMonitorRange_Private(SNES snes, PetscInt it, PetscReal *per) 479 { 480 Vec resid; 481 PetscReal rmax, pwork; 482 PetscInt i, n, N; 483 PetscScalar *r; 484 485 PetscFunctionBegin; 486 PetscCall(SNESGetFunction(snes, &resid, NULL, NULL)); 487 PetscCall(VecNorm(resid, NORM_INFINITY, &rmax)); 488 PetscCall(VecGetLocalSize(resid, &n)); 489 PetscCall(VecGetSize(resid, &N)); 490 PetscCall(VecGetArray(resid, &r)); 491 pwork = 0.0; 492 for (i = 0; i < n; i++) pwork += (PetscAbsScalar(r[i]) > .20 * rmax); 493 PetscCall(MPIU_Allreduce(&pwork, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)snes))); 494 PetscCall(VecRestoreArray(resid, &r)); 495 *per = *per / N; 496 PetscFunctionReturn(PETSC_SUCCESS); 497 } 498 499 /*@C 500 SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum entry in the residual 501 502 Collective 503 504 Input Parameters: 505 + snes - iterative context 506 . it - iteration number 507 . rnorm - 2-norm (preconditioned) residual value (may be estimated). 508 - dummy - unused monitor context 509 510 Options Database Key: 511 . -snes_monitor_range - Activates `SNESMonitorRange()` 512 513 Level: intermediate 514 515 Note: 516 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 517 to be used during the `SNES` solve. 518 519 .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()`, `SNESMonitorScaling()`, `PetscViewerFormat`, `PetscViewerAndFormat` 520 @*/ 521 PetscErrorCode SNESMonitorRange(SNES snes, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf) 522 { 523 PetscReal perc, rel; 524 PetscViewer viewer = vf->viewer; 525 /* should be in a MonitorRangeContext */ 526 static PetscReal prev; 527 528 PetscFunctionBegin; 529 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 530 if (!it) prev = rnorm; 531 PetscCall(SNESMonitorRange_Private(snes, it, &perc)); 532 533 rel = (prev - rnorm) / prev; 534 prev = rnorm; 535 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 536 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 537 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))); 538 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 539 PetscCall(PetscViewerPopFormat(viewer)); 540 PetscFunctionReturn(PETSC_SUCCESS); 541 } 542 543 /*@C 544 SNESMonitorRatio - Monitors progress of the `SNES` solvers by printing the ratio 545 of residual norm at each iteration to the previous. 546 547 Collective 548 549 Input Parameters: 550 + snes - the `SNES` context 551 . its - iteration number 552 . fgnorm - 2-norm of residual (or gradient) 553 - dummy - context of monitor 554 555 Options Database Key: 556 . -snes_monitor_ratio - activate this monitor 557 558 Level: intermediate 559 560 Notes: 561 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 562 to be used during the `SNES` solve. 563 564 Be sure to call `SNESMonitorRationSetUp()` before using this monitor. 565 566 .seealso: [](ch_snes), `SNESMonitorRationSetUp()`, `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `PetscViewerFormat`, `PetscViewerAndFormat` 567 @*/ 568 PetscErrorCode SNESMonitorRatio(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 569 { 570 PetscInt len; 571 PetscReal *history; 572 PetscViewer viewer = vf->viewer; 573 574 PetscFunctionBegin; 575 PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, &len)); 576 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 577 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 578 if (!its || !history || its > len) { 579 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm)); 580 } else { 581 PetscReal ratio = fgnorm / history[its - 1]; 582 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e \n", its, (double)fgnorm, (double)ratio)); 583 } 584 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 585 PetscCall(PetscViewerPopFormat(viewer)); 586 PetscFunctionReturn(PETSC_SUCCESS); 587 } 588 589 /*@C 590 SNESMonitorRatioSetUp - Insures the `SNES` object is saving its history since this monitor needs access to it 591 592 Collective 593 594 Input Parameters: 595 + snes - the `SNES` context 596 - viewer - the `PetscViewer` object (ignored) 597 598 Level: intermediate 599 600 .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()`, `PetscViewerFormat`, `PetscViewerAndFormat` 601 @*/ 602 PetscErrorCode SNESMonitorRatioSetUp(SNES snes, PetscViewerAndFormat *vf) 603 { 604 PetscReal *history; 605 606 PetscFunctionBegin; 607 PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, NULL)); 608 if (!history) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, 100, PETSC_TRUE)); 609 PetscFunctionReturn(PETSC_SUCCESS); 610 } 611 612 /* 613 Default (short) SNES Monitor, same as SNESMonitorDefault() except 614 it prints fewer digits of the residual as the residual gets smaller. 615 This is because the later digits are meaningless and are often 616 different on different machines; by using this routine different 617 machines will usually generate the same output. 618 619 Deprecated: Intentionally has no manual page 620 */ 621 PetscErrorCode SNESMonitorDefaultShort(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 622 { 623 PetscViewer viewer = vf->viewer; 624 625 PetscFunctionBegin; 626 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 627 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 628 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 629 if (fgnorm > 1.e-9) { 630 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %g \n", its, (double)fgnorm)); 631 } else if (fgnorm > 1.e-11) { 632 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %5.3e \n", its, (double)fgnorm)); 633 } else { 634 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm < 1.e-11\n", its)); 635 } 636 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 637 PetscCall(PetscViewerPopFormat(viewer)); 638 PetscFunctionReturn(PETSC_SUCCESS); 639 } 640 641 /*@C 642 SNESMonitorDefaultField - Monitors progress of the `SNES` solvers, separated into fields. 643 644 Collective 645 646 Input Parameters: 647 + snes - the `SNES` context 648 . its - iteration number 649 . fgnorm - 2-norm of residual 650 - ctx - the PetscViewer 651 652 Options Database Key: 653 . -snes_monitor_field - activate this monitor 654 655 Level: intermediate 656 657 Notes: 658 This routine uses the `DM` attached to the residual vector to define the fields. 659 660 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 661 to be used during the `SNES` solve. 662 663 .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `PetscViewerFormat`, `PetscViewerAndFormat` 664 @*/ 665 PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 666 { 667 PetscViewer viewer = vf->viewer; 668 Vec r; 669 DM dm; 670 PetscReal res[256]; 671 PetscInt tablevel; 672 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 675 PetscCall(SNESGetFunction(snes, &r, NULL, NULL)); 676 PetscCall(VecGetDM(r, &dm)); 677 if (!dm) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf)); 678 else { 679 PetscSection s, gs; 680 PetscInt Nf, f; 681 682 PetscCall(DMGetLocalSection(dm, &s)); 683 PetscCall(DMGetGlobalSection(dm, &gs)); 684 if (!s || !gs) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf)); 685 PetscCall(PetscSectionGetNumFields(s, &Nf)); 686 PetscCheck(Nf <= 256, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Do not support %" PetscInt_FMT " fields > 256", Nf); 687 PetscCall(PetscSectionVecNorm(s, gs, r, NORM_2, res)); 688 PetscCall(PetscObjectGetTabLevel((PetscObject)snes, &tablevel)); 689 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 690 PetscCall(PetscViewerASCIIAddTab(viewer, tablevel)); 691 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double)fgnorm)); 692 for (f = 0; f < Nf; ++f) { 693 if (f) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 694 PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f])); 695 } 696 PetscCall(PetscViewerASCIIPrintf(viewer, "] \n")); 697 PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel)); 698 PetscCall(PetscViewerPopFormat(viewer)); 699 } 700 PetscFunctionReturn(PETSC_SUCCESS); 701 } 702 703 /*@C 704 SNESConvergedDefault - Default onvergence test of the solvers for 705 systems of nonlinear equations. 706 707 Collective 708 709 Input Parameters: 710 + snes - the `SNES` context 711 . it - the iteration (0 indicates before any Newton steps) 712 . xnorm - 2-norm of current iterate 713 . snorm - 2-norm of current step 714 . fnorm - 2-norm of function at current iterate 715 - dummy - unused context 716 717 Output Parameter: 718 . reason - one of 719 .vb 720 SNES_CONVERGED_FNORM_ABS - (fnorm < abstol), 721 SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm), 722 SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 723 SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 724 SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 725 SNES_CONVERGED_ITERATING - (otherwise), 726 SNES_DIVERGED_DTOL - (fnorm > divtol*snes->fnorm0) 727 .ve 728 729 where 730 + maxf - maximum number of function evaluations, set with `SNESSetTolerances()` 731 . nfct - number of function evaluations, 732 . abstol - absolute function norm tolerance, set with `SNESSetTolerances()` 733 . rtol - relative function norm tolerance, set with `SNESSetTolerances()` 734 . divtol - divergence tolerance, set with `SNESSetDivergenceTolerance()` 735 - fnorm0 - 2-norm of the function at the initial solution (initial guess; zeroth iteration) 736 737 Options Database Keys: 738 + -snes_convergence_test default - see `SNESSetFromOptions()` 739 . -snes_stol - convergence tolerance in terms of the norm of the change in the solution between steps 740 . -snes_atol <abstol> - absolute tolerance of residual norm 741 . -snes_rtol <rtol> - relative decrease in tolerance norm from the initial 2-norm of the solution 742 . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 743 . -snes_max_funcs <max_funcs> - maximum number of function evaluations 744 . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 745 - -snes_max_linear_solve_fail - number of linear solver failures before `SNESSolve()` stops 746 747 Level: intermediate 748 749 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()`, 750 `SNESConvergedReason` 751 @*/ 752 PetscErrorCode SNESConvergedDefault(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy) 753 { 754 PetscFunctionBegin; 755 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 756 PetscValidPointer(reason, 6); 757 758 *reason = SNES_CONVERGED_ITERATING; 759 if (!it) { 760 /* set parameter for default relative tolerance convergence test */ 761 snes->ttol = fnorm * snes->rtol; 762 snes->rnorm0 = fnorm; 763 } 764 if (PetscIsInfOrNanReal(fnorm)) { 765 PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n")); 766 *reason = SNES_DIVERGED_FNORM_NAN; 767 } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) { 768 PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e\n", (double)fnorm, (double)snes->abstol)); 769 *reason = SNES_CONVERGED_FNORM_ABS; 770 } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) { 771 PetscCall(PetscInfo(snes, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", snes->nfuncs, snes->max_funcs)); 772 *reason = SNES_DIVERGED_FUNCTION_COUNT; 773 } 774 775 if (it && !*reason) { 776 if (fnorm <= snes->ttol) { 777 PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e (relative tolerance)\n", (double)fnorm, (double)snes->ttol)); 778 *reason = SNES_CONVERGED_FNORM_RELATIVE; 779 } else if (snorm < snes->stol * xnorm) { 780 PetscCall(PetscInfo(snes, "Converged due to small update length: %14.12e < %14.12e * %14.12e\n", (double)snorm, (double)snes->stol, (double)xnorm)); 781 *reason = SNES_CONVERGED_SNORM_RELATIVE; 782 } else if (snes->divtol > 0 && (fnorm > snes->divtol * snes->rnorm0)) { 783 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)); 784 *reason = SNES_DIVERGED_DTOL; 785 } 786 } 787 PetscFunctionReturn(PETSC_SUCCESS); 788 } 789 790 /*@C 791 SNESConvergedSkip - Convergence test for `SNES` that NEVER returns as 792 converged, UNLESS the maximum number of iteration have been reached. 793 794 Logically Collective 795 796 Input Parameters: 797 + snes - the `SNES` context 798 . it - the iteration (0 indicates before any Newton steps) 799 . xnorm - 2-norm of current iterate 800 . snorm - 2-norm of current step 801 . fnorm - 2-norm of function at current iterate 802 - dummy - unused context 803 804 Output Parameter: 805 . reason - `SNES_CONVERGED_ITERATING`, `SNES_CONVERGED_ITS`, or `SNES_DIVERGED_FNORM_NAN` 806 807 Options Database Key: 808 . -snes_convergence_test skip - see `SNESSetFromOptions()` 809 810 Level: advanced 811 812 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedDefault()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 813 @*/ 814 PetscErrorCode SNESConvergedSkip(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy) 815 { 816 PetscFunctionBegin; 817 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 818 PetscValidPointer(reason, 6); 819 820 *reason = SNES_CONVERGED_ITERATING; 821 822 if (fnorm != fnorm) { 823 PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n")); 824 *reason = SNES_DIVERGED_FNORM_NAN; 825 } else if (it == snes->max_its) { 826 *reason = SNES_CONVERGED_ITS; 827 } 828 PetscFunctionReturn(PETSC_SUCCESS); 829 } 830 831 /*@C 832 SNESSetWorkVecs - Gets a number of work vectors to be used internally by `SNES` solvers 833 834 Input Parameters: 835 + snes - the `SNES` context 836 - nw - number of work vectors to allocate 837 838 Level: developer 839 840 .seealso: [](ch_snes), `SNES` 841 @*/ 842 PetscErrorCode SNESSetWorkVecs(SNES snes, PetscInt nw) 843 { 844 DM dm; 845 Vec v; 846 847 PetscFunctionBegin; 848 if (snes->work) PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 849 snes->nwork = nw; 850 851 PetscCall(SNESGetDM(snes, &dm)); 852 PetscCall(DMGetGlobalVector(dm, &v)); 853 PetscCall(VecDuplicateVecs(v, snes->nwork, &snes->work)); 854 PetscCall(DMRestoreGlobalVector(dm, &v)); 855 PetscFunctionReturn(PETSC_SUCCESS); 856 } 857