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