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