1 2 #include <petsc/private/snesimpl.h> /*I "petsc/private/snesimpl.h" I*/ 3 #include <petscdm.h> 4 #include <petscsection.h> 5 #include <petscblaslapack.h> 6 7 /*@C 8 SNESMonitorSolution - Monitors progress of the SNES solvers by calling 9 VecView() for the approximate solution at each iteration. 10 11 Collective on SNES 12 13 Input Parameters: 14 + snes - the SNES context 15 . its - iteration number 16 . fgnorm - 2-norm of residual 17 - dummy - a viewer 18 19 Options Database Keys: 20 . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 21 22 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 23 to be used during the SNES solve. 24 25 Level: intermediate 26 27 .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()` 28 @*/ 29 PetscErrorCode SNESMonitorSolution(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) { 30 Vec x; 31 PetscViewer viewer = vf->viewer; 32 33 PetscFunctionBegin; 34 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 35 PetscCall(SNESGetSolution(snes, &x)); 36 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 37 PetscCall(VecView(x, viewer)); 38 PetscCall(PetscViewerPopFormat(viewer)); 39 PetscFunctionReturn(0); 40 } 41 42 /*@C 43 SNESMonitorResidual - Monitors progress of the SNES solvers by calling 44 VecView() for the residual at each iteration. 45 46 Collective on SNES 47 48 Input Parameters: 49 + snes - the SNES context 50 . its - iteration number 51 . fgnorm - 2-norm of residual 52 - dummy - a viewer 53 54 Options Database Keys: 55 . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 56 57 Notes: 58 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 59 to be used during the SNES solve. 60 61 Level: intermediate 62 63 .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()` 64 @*/ 65 PetscErrorCode SNESMonitorResidual(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) { 66 Vec x; 67 PetscViewer viewer = vf->viewer; 68 69 PetscFunctionBegin; 70 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 71 PetscCall(SNESGetFunction(snes, &x, NULL, NULL)); 72 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 73 PetscCall(VecView(x, viewer)); 74 PetscCall(PetscViewerPopFormat(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 Keys: 91 . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 92 93 Notes: 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()` 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 linear 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 Notes: 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()` 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 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 180 181 Options Database Key: 182 . -snes_monitor_ksp draw::draw_lg - Activates KSPMonitorSNESResidualDrawLG() 183 184 Notes: 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 SNES solve. 187 188 Level: intermediate 189 190 .seealso: `KSPMonitorSet()`, `KSPMonitorTrueResidual()` 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 plotter for the linear SNES residual. 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: `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()` 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 PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes, PetscInt it, PetscReal fnorm, PetscViewerAndFormat *vf) { 371 Vec X; 372 Mat J, dJ, dJdense; 373 PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *); 374 PetscInt n; 375 PetscBLASInt nb = 0, lwork; 376 PetscReal *eigr, *eigi; 377 PetscScalar *work; 378 PetscScalar *a; 379 380 PetscFunctionBegin; 381 if (it == 0) PetscFunctionReturn(0); 382 /* create the difference between the current update and the current jacobian */ 383 PetscCall(SNESGetSolution(snes, &X)); 384 PetscCall(SNESGetJacobian(snes, NULL, &J, &func, NULL)); 385 PetscCall(MatDuplicate(J, MAT_COPY_VALUES, &dJ)); 386 PetscCall(SNESComputeJacobian(snes, X, dJ, dJ)); 387 PetscCall(MatAXPY(dJ, -1.0, J, SAME_NONZERO_PATTERN)); 388 389 /* compute the spectrum directly */ 390 PetscCall(MatConvert(dJ, MATSEQDENSE, MAT_INITIAL_MATRIX, &dJdense)); 391 PetscCall(MatGetSize(dJ, &n, NULL)); 392 PetscCall(PetscBLASIntCast(n, &nb)); 393 lwork = 3 * nb; 394 PetscCall(PetscMalloc1(n, &eigr)); 395 PetscCall(PetscMalloc1(n, &eigi)); 396 PetscCall(PetscMalloc1(lwork, &work)); 397 PetscCall(MatDenseGetArray(dJdense, &a)); 398 #if !defined(PETSC_USE_COMPLEX) 399 { 400 PetscBLASInt lierr; 401 PetscInt i; 402 PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 403 PetscCallBLAS("LAPACKgeev", LAPACKgeev_("N", "N", &nb, a, &nb, eigr, eigi, NULL, &nb, NULL, &nb, work, &lwork, &lierr)); 404 PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "geev() error %" PetscBLASInt_FMT, lierr); 405 PetscCall(PetscFPTrapPop()); 406 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n", it, it - 1)); 407 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])); 408 } 409 PetscCall(MatDenseRestoreArray(dJdense, &a)); 410 PetscCall(MatDestroy(&dJ)); 411 PetscCall(MatDestroy(&dJdense)); 412 PetscCall(PetscFree(eigr)); 413 PetscCall(PetscFree(eigi)); 414 PetscCall(PetscFree(work)); 415 PetscFunctionReturn(0); 416 #else 417 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded for complex"); 418 #endif 419 } 420 421 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 422 423 PetscErrorCode SNESMonitorRange_Private(SNES snes, PetscInt it, PetscReal *per) { 424 Vec resid; 425 PetscReal rmax, pwork; 426 PetscInt i, n, N; 427 PetscScalar *r; 428 429 PetscFunctionBegin; 430 PetscCall(SNESGetFunction(snes, &resid, NULL, NULL)); 431 PetscCall(VecNorm(resid, NORM_INFINITY, &rmax)); 432 PetscCall(VecGetLocalSize(resid, &n)); 433 PetscCall(VecGetSize(resid, &N)); 434 PetscCall(VecGetArray(resid, &r)); 435 pwork = 0.0; 436 for (i = 0; i < n; i++) pwork += (PetscAbsScalar(r[i]) > .20 * rmax); 437 PetscCall(MPIU_Allreduce(&pwork, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)snes))); 438 PetscCall(VecRestoreArray(resid, &r)); 439 *per = *per / N; 440 PetscFunctionReturn(0); 441 } 442 443 /*@C 444 SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value. 445 446 Collective on SNES 447 448 Input Parameters: 449 + snes - iterative context 450 . it - iteration number 451 . rnorm - 2-norm (preconditioned) residual value (may be estimated). 452 - dummy - unused monitor context 453 454 Options Database Key: 455 . -snes_monitor_range - Activates SNESMonitorRange() 456 457 Notes: 458 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 459 to be used during the SNES solve. 460 461 Level: intermediate 462 463 .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()` 464 @*/ 465 PetscErrorCode SNESMonitorRange(SNES snes, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf) { 466 PetscReal perc, rel; 467 PetscViewer viewer = vf->viewer; 468 /* should be in a MonitorRangeContext */ 469 static PetscReal prev; 470 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 473 if (!it) prev = rnorm; 474 PetscCall(SNESMonitorRange_Private(snes, it, &perc)); 475 476 rel = (prev - rnorm) / prev; 477 prev = rnorm; 478 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 479 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 480 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))); 481 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 482 PetscCall(PetscViewerPopFormat(viewer)); 483 PetscFunctionReturn(0); 484 } 485 486 /*@C 487 SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio 488 of residual norm at each iteration to the previous. 489 490 Collective on SNES 491 492 Input Parameters: 493 + snes - the SNES context 494 . its - iteration number 495 . fgnorm - 2-norm of residual (or gradient) 496 - dummy - context of monitor 497 498 Level: intermediate 499 500 Notes: 501 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 502 to be used during the SNES solve. 503 504 Be sure to call SNESMonitorRationSetUp() before using this monitor. 505 506 .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()` 507 @*/ 508 PetscErrorCode SNESMonitorRatio(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) { 509 PetscInt len; 510 PetscReal *history; 511 PetscViewer viewer = vf->viewer; 512 513 PetscFunctionBegin; 514 PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, &len)); 515 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 516 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 517 if (!its || !history || its > len) { 518 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm)); 519 } else { 520 PetscReal ratio = fgnorm / history[its - 1]; 521 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e \n", its, (double)fgnorm, (double)ratio)); 522 } 523 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 524 PetscCall(PetscViewerPopFormat(viewer)); 525 PetscFunctionReturn(0); 526 } 527 528 /*@C 529 SNESMonitorRatioSetUp - Insures the SNES object is saving its history since this monitor needs access to it 530 531 Collective on SNES 532 533 Input Parameters: 534 + snes - the SNES context 535 - viewer - the PetscViewer object (ignored) 536 537 Level: intermediate 538 539 .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()` 540 @*/ 541 PetscErrorCode SNESMonitorRatioSetUp(SNES snes, PetscViewerAndFormat *vf) { 542 PetscReal *history; 543 544 PetscFunctionBegin; 545 PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, NULL)); 546 if (!history) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, 100, PETSC_TRUE)); 547 PetscFunctionReturn(0); 548 } 549 550 /* ---------------------------------------------------------------- */ 551 /* 552 Default (short) SNES Monitor, same as SNESMonitorDefault() except 553 it prints fewer digits of the residual as the residual gets smaller. 554 This is because the later digits are meaningless and are often 555 different on different machines; by using this routine different 556 machines will usually generate the same output. 557 558 Deprecated: Intentionally has no manual page 559 */ 560 PetscErrorCode SNESMonitorDefaultShort(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) { 561 PetscViewer viewer = vf->viewer; 562 563 PetscFunctionBegin; 564 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 565 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 566 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 567 if (fgnorm > 1.e-9) { 568 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %g \n", its, (double)fgnorm)); 569 } else if (fgnorm > 1.e-11) { 570 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %5.3e \n", its, (double)fgnorm)); 571 } else { 572 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm < 1.e-11\n", its)); 573 } 574 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 575 PetscCall(PetscViewerPopFormat(viewer)); 576 PetscFunctionReturn(0); 577 } 578 579 /*@C 580 SNESMonitorDefaultField - Monitors progress of the SNES solvers, separated into fields. 581 582 Collective on SNES 583 584 Input Parameters: 585 + snes - the SNES context 586 . its - iteration number 587 . fgnorm - 2-norm of residual 588 - ctx - the PetscViewer 589 590 Notes: 591 This routine uses the DM attached to the residual vector to define the fields. 592 593 This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor 594 to be used during the SNES solve. 595 596 Level: intermediate 597 598 .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()` 599 @*/ 600 PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) { 601 PetscViewer viewer = vf->viewer; 602 Vec r; 603 DM dm; 604 PetscReal res[256]; 605 PetscInt tablevel; 606 607 PetscFunctionBegin; 608 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 4); 609 PetscCall(SNESGetFunction(snes, &r, NULL, NULL)); 610 PetscCall(VecGetDM(r, &dm)); 611 if (!dm) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf)); 612 else { 613 PetscSection s, gs; 614 PetscInt Nf, f; 615 616 PetscCall(DMGetLocalSection(dm, &s)); 617 PetscCall(DMGetGlobalSection(dm, &gs)); 618 if (!s || !gs) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf)); 619 PetscCall(PetscSectionGetNumFields(s, &Nf)); 620 PetscCheck(Nf <= 256, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Do not support %" PetscInt_FMT " fields > 256", Nf); 621 PetscCall(PetscSectionVecNorm(s, gs, r, NORM_2, res)); 622 PetscCall(PetscObjectGetTabLevel((PetscObject)snes, &tablevel)); 623 PetscCall(PetscViewerPushFormat(viewer, vf->format)); 624 PetscCall(PetscViewerASCIIAddTab(viewer, tablevel)); 625 PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double)fgnorm)); 626 for (f = 0; f < Nf; ++f) { 627 if (f) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 628 PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f])); 629 } 630 PetscCall(PetscViewerASCIIPrintf(viewer, "] \n")); 631 PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel)); 632 PetscCall(PetscViewerPopFormat(viewer)); 633 } 634 PetscFunctionReturn(0); 635 } 636 /* ---------------------------------------------------------------- */ 637 /*@C 638 SNESConvergedDefault - Default onvergence test of the solvers for 639 systems of nonlinear equations. 640 641 Collective on SNES 642 643 Input Parameters: 644 + snes - the SNES context 645 . it - the iteration (0 indicates before any Newton steps) 646 . xnorm - 2-norm of current iterate 647 . snorm - 2-norm of current step 648 . fnorm - 2-norm of function at current iterate 649 - dummy - unused context 650 651 Output Parameter: 652 . reason - one of 653 $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol), 654 $ SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm), 655 $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 656 $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 657 $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 658 $ SNES_CONVERGED_ITERATING - (otherwise), 659 $ SNES_DIVERGED_DTOL - (fnorm > divtol*snes->fnorm0) 660 661 where 662 + maxf - maximum number of function evaluations, set with SNESSetTolerances() 663 . nfct - number of function evaluations, 664 . abstol - absolute function norm tolerance, set with SNESSetTolerances() 665 . rtol - relative function norm tolerance, set with SNESSetTolerances() 666 . divtol - divergence tolerance, set with SNESSetDivergenceTolerance() 667 - fnorm0 - 2-norm of the function at the initial solution (initial guess; zeroth iteration) 668 669 Options Database Keys: 670 + -snes_convergence_test default - see SNESSetFromOptions() 671 . -snes_stol - convergence tolerance in terms of the norm of the change in the solution between steps 672 . -snes_atol <abstol> - absolute tolerance of residual norm 673 . -snes_rtol <rtol> - relative decrease in tolerance norm from the initial 2-norm of the solution 674 . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 675 . -snes_max_funcs <max_funcs> - maximum number of function evaluations 676 . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 677 - -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 678 679 Level: intermediate 680 681 .seealso: `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()` 682 @*/ 683 PetscErrorCode SNESConvergedDefault(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy) { 684 PetscFunctionBegin; 685 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 686 PetscValidPointer(reason, 6); 687 688 *reason = SNES_CONVERGED_ITERATING; 689 690 if (!it) { 691 /* set parameter for default relative tolerance convergence test */ 692 snes->ttol = fnorm * snes->rtol; 693 snes->rnorm0 = fnorm; 694 } 695 if (PetscIsInfOrNanReal(fnorm)) { 696 PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n")); 697 *reason = SNES_DIVERGED_FNORM_NAN; 698 } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) { 699 PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e\n", (double)fnorm, (double)snes->abstol)); 700 *reason = SNES_CONVERGED_FNORM_ABS; 701 } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) { 702 PetscCall(PetscInfo(snes, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", snes->nfuncs, snes->max_funcs)); 703 *reason = SNES_DIVERGED_FUNCTION_COUNT; 704 } 705 706 if (it && !*reason) { 707 if (fnorm <= snes->ttol) { 708 PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e (relative tolerance)\n", (double)fnorm, (double)snes->ttol)); 709 *reason = SNES_CONVERGED_FNORM_RELATIVE; 710 } else if (snorm < snes->stol * xnorm) { 711 PetscCall(PetscInfo(snes, "Converged due to small update length: %14.12e < %14.12e * %14.12e\n", (double)snorm, (double)snes->stol, (double)xnorm)); 712 *reason = SNES_CONVERGED_SNORM_RELATIVE; 713 } else if (snes->divtol > 0 && (fnorm > snes->divtol * snes->rnorm0)) { 714 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)); 715 *reason = SNES_DIVERGED_DTOL; 716 } 717 } 718 PetscFunctionReturn(0); 719 } 720 721 /*@C 722 SNESConvergedSkip - Convergence test for SNES that NEVER returns as 723 converged, UNLESS the maximum number of iteration have been reached. 724 725 Logically Collective on SNES 726 727 Input Parameters: 728 + snes - the SNES context 729 . it - the iteration (0 indicates before any Newton steps) 730 . xnorm - 2-norm of current iterate 731 . snorm - 2-norm of current step 732 . fnorm - 2-norm of function at current iterate 733 - dummy - unused context 734 735 Output Parameter: 736 . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 737 738 Notes: 739 Convergence is then declared after a fixed number of iterations have been used. 740 741 Options Database Keys: 742 . -snes_convergence_test default - see SNESSetFromOptions() 743 744 Level: advanced 745 746 .seealso: `SNESConvergedDefault()`, `SNESSetConvergenceTest()` 747 @*/ 748 PetscErrorCode SNESConvergedSkip(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy) { 749 PetscFunctionBegin; 750 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 751 PetscValidPointer(reason, 6); 752 753 *reason = SNES_CONVERGED_ITERATING; 754 755 if (fnorm != fnorm) { 756 PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n")); 757 *reason = SNES_DIVERGED_FNORM_NAN; 758 } else if (it == snes->max_its) { 759 *reason = SNES_CONVERGED_ITS; 760 } 761 PetscFunctionReturn(0); 762 } 763 764 /*@C 765 SNESSetWorkVecs - Gets a number of work vectors. 766 767 Input Parameters: 768 + snes - the SNES context 769 - nw - number of work vectors to allocate 770 771 Level: developer 772 773 @*/ 774 PetscErrorCode SNESSetWorkVecs(SNES snes, PetscInt nw) { 775 DM dm; 776 Vec v; 777 778 PetscFunctionBegin; 779 if (snes->work) PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 780 snes->nwork = nw; 781 782 PetscCall(SNESGetDM(snes, &dm)); 783 PetscCall(DMGetGlobalVector(dm, &v)); 784 PetscCall(VecDuplicateVecs(v, snes->nwork, &snes->work)); 785 PetscCall(DMRestoreGlobalVector(dm, &v)); 786 PetscCall(PetscLogObjectParents(snes, nw, snes->work)); 787 PetscFunctionReturn(0); 788 } 789