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