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