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