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