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