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