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