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