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: 495 Insure that SNESMonitorRatio() is called when you set this monitor 496 .keywords: SNES, nonlinear, monitor, norm 497 498 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorRatio() 499 @*/ 500 PetscErrorCode SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 501 { 502 PetscErrorCode ierr; 503 PetscInt len; 504 PetscReal *history; 505 PetscViewer viewer = vf->viewer; 506 507 PetscFunctionBegin; 508 ierr = SNESGetConvergenceHistory(snes,&history,NULL,&len);CHKERRQ(ierr); 509 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 510 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 511 if (!its || !history || its > len) { 512 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);CHKERRQ(ierr); 513 } else { 514 PetscReal ratio = fgnorm/history[its-1]; 515 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e %14.12e \n",its,(double)fgnorm,(double)ratio);CHKERRQ(ierr); 516 } 517 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 518 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 519 PetscFunctionReturn(0); 520 } 521 522 /*@C 523 SNESMonitorRatioSetUp - Insures the SNES object is saving its history since this monitor needs access to it 524 525 Collective on SNES 526 527 Input Parameters: 528 + snes - the SNES context 529 - viewer - the PetscViewer object (ignored) 530 531 Level: intermediate 532 533 .keywords: SNES, nonlinear, monitor, norm 534 535 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault(), SNESMonitorRatio() 536 @*/ 537 PetscErrorCode SNESMonitorRatioSetUp(SNES snes,PetscViewerAndFormat *vf) 538 { 539 PetscErrorCode ierr; 540 PetscReal *history; 541 542 PetscFunctionBegin; 543 ierr = SNESGetConvergenceHistory(snes,&history,NULL,NULL);CHKERRQ(ierr); 544 if (!history) { 545 ierr = SNESSetConvergenceHistory(snes,NULL,NULL,100,PETSC_TRUE);CHKERRQ(ierr); 546 } 547 PetscFunctionReturn(0); 548 } 549 550 /* ---------------------------------------------------------------- */ 551 /* 552 Default (short) SNES Monitor, same as SNESMonitorDefault() except 553 it prints fewer digits of the residual as the residual gets smaller. 554 This is because the later digits are meaningless and are often 555 different on different machines; by using this routine different 556 machines will usually generate the same output. 557 558 Deprecated: Intentionally has no manual page 559 */ 560 PetscErrorCode SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *vf) 561 { 562 PetscErrorCode ierr; 563 PetscViewer viewer = vf->viewer; 564 565 PetscFunctionBegin; 566 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 567 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 568 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 569 if (fgnorm > 1.e-9) { 570 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %g \n",its,(double)fgnorm);CHKERRQ(ierr); 571 } else if (fgnorm > 1.e-11) { 572 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,(double)fgnorm);CHKERRQ(ierr); 573 } else { 574 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); 575 } 576 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 577 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 578 PetscFunctionReturn(0); 579 } 580 581 /*@C 582 SNESMonitorDefaultField - Monitors progress of the SNES solvers, separated into fields. 583 584 Collective on SNES 585 586 Input Parameters: 587 + snes - the SNES context 588 . its - iteration number 589 . fgnorm - 2-norm of residual 590 - ctx - the PetscViewer 591 592 Notes: 593 This routine uses the DM attached to the residual vector 594 595 Level: intermediate 596 597 .keywords: SNES, nonlinear, field, monitor, norm 598 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault() 599 @*/ 600 PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 601 { 602 PetscViewer viewer = vf->viewer; 603 Vec r; 604 DM dm; 605 PetscReal res[256]; 606 PetscInt tablevel; 607 PetscErrorCode ierr; 608 609 PetscFunctionBegin; 610 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 611 ierr = SNESGetFunction(snes, &r, NULL, NULL);CHKERRQ(ierr); 612 ierr = VecGetDM(r, &dm);CHKERRQ(ierr); 613 if (!dm) {ierr = SNESMonitorDefault(snes, its, fgnorm, vf);CHKERRQ(ierr);} 614 else { 615 PetscSection s, gs; 616 PetscInt Nf, f; 617 618 ierr = DMGetSection(dm, &s);CHKERRQ(ierr); 619 ierr = DMGetGlobalSection(dm, &gs);CHKERRQ(ierr); 620 if (!s || !gs) {ierr = SNESMonitorDefault(snes, its, fgnorm, vf);CHKERRQ(ierr);} 621 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 622 if (Nf > 256) SETERRQ1(PetscObjectComm((PetscObject) snes), PETSC_ERR_SUP, "Do not support %d fields > 256", Nf); 623 ierr = PetscSectionVecNorm(s, gs, r, NORM_2, res);CHKERRQ(ierr); 624 ierr = PetscObjectGetTabLevel((PetscObject) snes, &tablevel);CHKERRQ(ierr); 625 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 626 ierr = PetscViewerASCIIAddTab(viewer, tablevel);CHKERRQ(ierr); 627 ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr); 628 for (f = 0; f < Nf; ++f) { 629 if (f) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 630 ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", res[f]);CHKERRQ(ierr); 631 } 632 ierr = PetscViewerASCIIPrintf(viewer, "] \n");CHKERRQ(ierr); 633 ierr = PetscViewerASCIISubtractTab(viewer, tablevel);CHKERRQ(ierr); 634 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 635 } 636 PetscFunctionReturn(0); 637 } 638 /* ---------------------------------------------------------------- */ 639 /*@C 640 SNESConvergedDefault - Convergence test of the solvers for 641 systems of nonlinear equations (default). 642 643 Collective on SNES 644 645 Input Parameters: 646 + snes - the SNES context 647 . it - the iteration (0 indicates before any Newton steps) 648 . xnorm - 2-norm of current iterate 649 . snorm - 2-norm of current step 650 . fnorm - 2-norm of function at current iterate 651 - dummy - unused context 652 653 Output Parameter: 654 . reason - one of 655 $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol), 656 $ SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm), 657 $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 658 $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 659 $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 660 $ SNES_CONVERGED_ITERATING - (otherwise), 661 662 where 663 + maxf - maximum number of function evaluations, 664 set with SNESSetTolerances() 665 . nfct - number of function evaluations, 666 . abstol - absolute function norm tolerance, 667 set with SNESSetTolerances() 668 - rtol - relative function norm tolerance, set with SNESSetTolerances() 669 670 Level: intermediate 671 672 .keywords: SNES, nonlinear, default, converged, convergence 673 674 .seealso: SNESSetConvergenceTest() 675 @*/ 676 PetscErrorCode SNESConvergedDefault(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 677 { 678 PetscErrorCode ierr; 679 680 PetscFunctionBegin; 681 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 682 PetscValidPointer(reason,6); 683 684 *reason = SNES_CONVERGED_ITERATING; 685 686 if (!it) { 687 /* set parameter for default relative tolerance convergence test */ 688 snes->ttol = fnorm*snes->rtol; 689 snes->rnorm0 = fnorm; 690 } 691 if (PetscIsInfOrNanReal(fnorm)) { 692 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 693 *reason = SNES_DIVERGED_FNORM_NAN; 694 } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) { 695 ierr = PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e\n",(double)fnorm,(double)snes->abstol);CHKERRQ(ierr); 696 *reason = SNES_CONVERGED_FNORM_ABS; 697 } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) { 698 ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 699 *reason = SNES_DIVERGED_FUNCTION_COUNT; 700 } 701 702 if (it && !*reason) { 703 if (fnorm <= snes->ttol) { 704 ierr = PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e (relative tolerance)\n",(double)fnorm,(double)snes->ttol);CHKERRQ(ierr); 705 *reason = SNES_CONVERGED_FNORM_RELATIVE; 706 } else if (snorm < snes->stol*xnorm) { 707 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); 708 *reason = SNES_CONVERGED_SNORM_RELATIVE; 709 } else if (snes->divtol > 0 && (fnorm > snes->divtol*snes->rnorm0)) { 710 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); 711 *reason = SNES_DIVERGED_DTOL; 712 } 713 714 } 715 PetscFunctionReturn(0); 716 } 717 718 /*@C 719 SNESConvergedSkip - Convergence test for SNES that NEVER returns as 720 converged, UNLESS the maximum number of iteration have been reached. 721 722 Logically Collective on SNES 723 724 Input Parameters: 725 + snes - the SNES context 726 . it - the iteration (0 indicates before any Newton steps) 727 . xnorm - 2-norm of current iterate 728 . snorm - 2-norm of current step 729 . fnorm - 2-norm of function at current iterate 730 - dummy - unused context 731 732 Output Parameter: 733 . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 734 735 Notes: 736 Convergence is then declared after a fixed number of iterations have been used. 737 738 Level: advanced 739 740 .keywords: SNES, nonlinear, skip, converged, convergence 741 742 .seealso: SNESSetConvergenceTest() 743 @*/ 744 PetscErrorCode SNESConvergedSkip(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 745 { 746 PetscErrorCode ierr; 747 748 PetscFunctionBegin; 749 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 750 PetscValidPointer(reason,6); 751 752 *reason = SNES_CONVERGED_ITERATING; 753 754 if (fnorm != fnorm) { 755 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 756 *reason = SNES_DIVERGED_FNORM_NAN; 757 } else if (it == snes->max_its) { 758 *reason = SNES_CONVERGED_ITS; 759 } 760 PetscFunctionReturn(0); 761 } 762 763 /*@C 764 SNESSetWorkVecs - Gets a number of work vectors. 765 766 Input Parameters: 767 . snes - the SNES context 768 . nw - number of work vectors to allocate 769 770 Level: developer 771 772 @*/ 773 PetscErrorCode SNESSetWorkVecs(SNES snes,PetscInt nw) 774 { 775 DM dm; 776 Vec v; 777 PetscErrorCode ierr; 778 779 PetscFunctionBegin; 780 if (snes->work) {ierr = VecDestroyVecs(snes->nwork,&snes->work);CHKERRQ(ierr);} 781 snes->nwork = nw; 782 783 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 784 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 785 ierr = VecDuplicateVecs(v,snes->nwork,&snes->work);CHKERRQ(ierr); 786 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 787 ierr = PetscLogObjectParents(snes,nw,snes->work);CHKERRQ(ierr); 788 PetscFunctionReturn(0); 789 } 790