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