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