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