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