1 2 #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/ 3 4 #undef __FUNCT__ 5 #define __FUNCT__ "SNESMonitorSolution" 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 - either a viewer or PETSC_NULL 17 18 Level: intermediate 19 20 .keywords: SNES, nonlinear, vector, monitor, view 21 22 .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView() 23 @*/ 24 PetscErrorCode SNESMonitorSolution(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 25 { 26 PetscErrorCode ierr; 27 Vec x; 28 PetscViewer viewer = (PetscViewer) dummy; 29 30 PetscFunctionBegin; 31 ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr); 32 if (!viewer) { 33 MPI_Comm comm; 34 ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 35 viewer = PETSC_VIEWER_DRAW_(comm); 36 } 37 ierr = VecView(x,viewer);CHKERRQ(ierr); 38 39 PetscFunctionReturn(0); 40 } 41 42 #undef __FUNCT__ 43 #define __FUNCT__ "SNESMonitorResidual" 44 /*@C 45 SNESMonitorResidual - Monitors progress of the SNES solvers by calling 46 VecView() for the residual at each iteration. 47 48 Collective on SNES 49 50 Input Parameters: 51 + snes - the SNES context 52 . its - iteration number 53 . fgnorm - 2-norm of residual 54 - dummy - either a viewer or PETSC_NULL 55 56 Level: intermediate 57 58 .keywords: SNES, nonlinear, vector, monitor, view 59 60 .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView() 61 @*/ 62 PetscErrorCode SNESMonitorResidual(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 63 { 64 PetscErrorCode ierr; 65 Vec x; 66 PetscViewer viewer = (PetscViewer) dummy; 67 68 PetscFunctionBegin; 69 ierr = SNESGetFunction(snes,&x,0,0);CHKERRQ(ierr); 70 if (!viewer) { 71 MPI_Comm comm; 72 ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 73 viewer = PETSC_VIEWER_DRAW_(comm); 74 } 75 ierr = VecView(x,viewer);CHKERRQ(ierr); 76 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 PETSC_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 115 PetscFunctionReturn(0); 116 } 117 118 #undef __FUNCT__ 119 #define __FUNCT__ "SNESMonitorDefault" 120 /*@C 121 SNESMonitorDefault - Monitors progress of the SNES solvers (default). 122 123 Collective on SNES 124 125 Input Parameters: 126 + snes - the SNES context 127 . its - iteration number 128 . fgnorm - 2-norm of residual 129 - dummy - unused context 130 131 Notes: 132 This routine prints the residual norm at each iteration. 133 134 Level: intermediate 135 136 .keywords: SNES, nonlinear, default, monitor, norm 137 138 .seealso: SNESMonitorSet(), SNESMonitorSolution() 139 @*/ 140 PetscErrorCode SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 141 { 142 PetscErrorCode ierr; 143 PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); 144 145 PetscFunctionBegin; 146 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 147 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);CHKERRQ(ierr); 148 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 149 PetscFunctionReturn(0); 150 } 151 152 #undef __FUNCT__ 153 #define __FUNCT__ "SNESMonitorRange_Private" 154 PetscErrorCode SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per) 155 { 156 PetscErrorCode ierr; 157 Vec resid; 158 PetscReal rmax,pwork; 159 PetscInt i,n,N; 160 PetscScalar *r; 161 162 PetscFunctionBegin; 163 ierr = SNESGetFunction(snes,&resid,0,0);CHKERRQ(ierr); 164 ierr = VecNorm(resid,NORM_INFINITY,&rmax);CHKERRQ(ierr); 165 ierr = VecGetLocalSize(resid,&n);CHKERRQ(ierr); 166 ierr = VecGetSize(resid,&N);CHKERRQ(ierr); 167 ierr = VecGetArray(resid,&r);CHKERRQ(ierr); 168 pwork = 0.0; 169 for (i=0; i<n; i++) { 170 pwork += (PetscAbsScalar(r[i]) > .20*rmax); 171 } 172 ierr = MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr); 173 ierr = VecRestoreArray(resid,&r);CHKERRQ(ierr); 174 *per = *per/N; 175 PetscFunctionReturn(0); 176 } 177 178 #undef __FUNCT__ 179 #define __FUNCT__ "SNESMonitorRange" 180 /*@C 181 SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value. 182 183 Collective on SNES 184 185 Input Parameters: 186 + snes - iterative context 187 . it - iteration number 188 . rnorm - 2-norm (preconditioned) residual value (may be estimated). 189 - dummy - unused monitor context 190 191 Options Database Key: 192 . -snes_monitor_range - Activates SNESMonitorRange() 193 194 Level: intermediate 195 196 .keywords: SNES, default, monitor, residual 197 198 .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate() 199 @*/ 200 PetscErrorCode SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy) 201 { 202 PetscErrorCode ierr; 203 PetscReal perc,rel; 204 PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); 205 /* should be in a MonitorRangeContext */ 206 static PetscReal prev; 207 208 PetscFunctionBegin; 209 if (!it) prev = rnorm; 210 ierr = SNESMonitorRange_Private(snes,it,&perc);CHKERRQ(ierr); 211 212 rel = (prev - rnorm)/prev; 213 prev = rnorm; 214 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 215 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); 216 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 217 PetscFunctionReturn(0); 218 } 219 220 typedef struct { 221 PetscViewer viewer; 222 PetscReal *history; 223 } SNESMonitorRatioContext; 224 225 #undef __FUNCT__ 226 #define __FUNCT__ "SNESMonitorRatio" 227 /*@C 228 SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio 229 of residual norm at each iteration to the previous. 230 231 Collective on SNES 232 233 Input Parameters: 234 + snes - the SNES context 235 . its - iteration number 236 . fgnorm - 2-norm of residual (or gradient) 237 - dummy - context of monitor 238 239 Level: intermediate 240 241 .keywords: SNES, nonlinear, monitor, norm 242 243 .seealso: SNESMonitorSet(), SNESMonitorSolution() 244 @*/ 245 PetscErrorCode SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 246 { 247 PetscErrorCode ierr; 248 PetscInt len; 249 PetscReal *history; 250 SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy; 251 252 PetscFunctionBegin; 253 ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr); 254 ierr = PetscViewerASCIIAddTab(ctx->viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 255 if (!its || !history || its > len) { 256 ierr = PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);CHKERRQ(ierr); 257 } else { 258 PetscReal ratio = fgnorm/history[its-1]; 259 ierr = PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %14.12e \n",its,(double)fgnorm,(double)ratio);CHKERRQ(ierr); 260 } 261 ierr = PetscViewerASCIISubtractTab(ctx->viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 262 PetscFunctionReturn(0); 263 } 264 265 /* 266 If the we set the history monitor space then we must destroy it 267 */ 268 #undef __FUNCT__ 269 #define __FUNCT__ "SNESMonitorRatioDestroy" 270 PetscErrorCode SNESMonitorRatioDestroy(void **ct) 271 { 272 PetscErrorCode ierr; 273 SNESMonitorRatioContext *ctx = *(SNESMonitorRatioContext**)ct; 274 275 PetscFunctionBegin; 276 ierr = PetscFree(ctx->history);CHKERRQ(ierr); 277 ierr = PetscViewerDestroy(&ctx->viewer);CHKERRQ(ierr); 278 ierr = PetscFree(ctx);CHKERRQ(ierr); 279 PetscFunctionReturn(0); 280 } 281 282 #undef __FUNCT__ 283 #define __FUNCT__ "SNESMonitorSetRatio" 284 /*@C 285 SNESMonitorSetRatio - Sets SNES to use a monitor that prints the 286 ratio of the function norm at each iteration. 287 288 Collective on SNES 289 290 Input Parameters: 291 + snes - the SNES context 292 - viewer - ASCII viewer to print output 293 294 Level: intermediate 295 296 .keywords: SNES, nonlinear, monitor, norm 297 298 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault() 299 @*/ 300 PetscErrorCode SNESMonitorSetRatio(SNES snes,PetscViewer viewer) 301 { 302 PetscErrorCode ierr; 303 SNESMonitorRatioContext *ctx; 304 PetscReal *history; 305 306 PetscFunctionBegin; 307 if (!viewer) { 308 ierr = PetscViewerASCIIOpen(((PetscObject)snes)->comm,"stdout",&viewer);CHKERRQ(ierr); 309 ierr = PetscObjectReference((PetscObject)viewer);CHKERRQ(ierr); 310 } 311 ierr = PetscNewLog(snes,SNESMonitorRatioContext,&ctx); 312 ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 313 if (!history) { 314 ierr = PetscMalloc(100*sizeof(PetscReal),&ctx->history);CHKERRQ(ierr); 315 ierr = SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);CHKERRQ(ierr); 316 } 317 ctx->viewer = viewer; 318 ierr = SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);CHKERRQ(ierr); 319 PetscFunctionReturn(0); 320 } 321 322 /* ---------------------------------------------------------------- */ 323 #undef __FUNCT__ 324 #define __FUNCT__ "SNESMonitorDefaultShort" 325 /* 326 Default (short) SNES Monitor, same as SNESMonitorDefault() except 327 it prints fewer digits of the residual as the residual gets smaller. 328 This is because the later digits are meaningless and are often 329 different on different machines; by using this routine different 330 machines will usually generate the same output. 331 */ 332 PetscErrorCode SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 333 { 334 PetscErrorCode ierr; 335 PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm); 336 337 PetscFunctionBegin; 338 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 339 if (fgnorm > 1.e-9) { 340 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);CHKERRQ(ierr); 341 } else if (fgnorm > 1.e-11){ 342 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr); 343 } else { 344 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); 345 } 346 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 347 PetscFunctionReturn(0); 348 } 349 /* ---------------------------------------------------------------- */ 350 #undef __FUNCT__ 351 #define __FUNCT__ "SNESDefaultConverged" 352 /*@C 353 SNESDefaultConverged - Convergence test of the solvers for 354 systems of nonlinear equations (default). 355 356 Collective on SNES 357 358 Input Parameters: 359 + snes - the SNES context 360 . it - the iteration (0 indicates before any Newton steps) 361 . xnorm - 2-norm of current iterate 362 . snorm - 2-norm of current step 363 . fnorm - 2-norm of function at current iterate 364 - dummy - unused context 365 366 Output Parameter: 367 . reason - one of 368 $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol), 369 $ SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm), 370 $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 371 $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 372 $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 373 $ SNES_CONVERGED_ITERATING - (otherwise), 374 375 where 376 + maxf - maximum number of function evaluations, 377 set with SNESSetTolerances() 378 . nfct - number of function evaluations, 379 . abstol - absolute function norm tolerance, 380 set with SNESSetTolerances() 381 - rtol - relative function norm tolerance, set with SNESSetTolerances() 382 383 Level: intermediate 384 385 .keywords: SNES, nonlinear, default, converged, convergence 386 387 .seealso: SNESSetConvergenceTest() 388 @*/ 389 PetscErrorCode SNESDefaultConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 390 { 391 PetscErrorCode ierr; 392 393 PetscFunctionBegin; 394 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 395 PetscValidPointer(reason,6); 396 397 *reason = SNES_CONVERGED_ITERATING; 398 399 if (!it) { 400 /* set parameter for default relative tolerance convergence test */ 401 snes->ttol = fnorm*snes->rtol; 402 } 403 if (fnorm != fnorm) { 404 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 405 *reason = SNES_DIVERGED_FNORM_NAN; 406 } else if (fnorm < snes->abstol) { 407 ierr = PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e\n",(double)fnorm,(double)snes->abstol);CHKERRQ(ierr); 408 *reason = SNES_CONVERGED_FNORM_ABS; 409 } else if (snes->nfuncs >= snes->max_funcs) { 410 ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 411 *reason = SNES_DIVERGED_FUNCTION_COUNT; 412 } 413 414 if (it && !*reason) { 415 if (fnorm <= snes->ttol) { 416 ierr = PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e (relative tolerance)\n",(double)fnorm,(double)snes->ttol);CHKERRQ(ierr); 417 *reason = SNES_CONVERGED_FNORM_RELATIVE; 418 } else if (snorm < snes->stol*xnorm) { 419 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); 420 *reason = SNES_CONVERGED_SNORM_RELATIVE; 421 } 422 } 423 PetscFunctionReturn(0); 424 } 425 426 #undef __FUNCT__ 427 #define __FUNCT__ "SNESSkipConverged" 428 /*@C 429 SNESSkipConverged - Convergence test for SNES that NEVER returns as 430 converged, UNLESS the maximum number of iteration have been reached. 431 432 Logically Collective on SNES 433 434 Input Parameters: 435 + snes - the SNES context 436 . it - the iteration (0 indicates before any Newton steps) 437 . xnorm - 2-norm of current iterate 438 . snorm - 2-norm of current step 439 . fnorm - 2-norm of function at current iterate 440 - dummy - unused context 441 442 Output Parameter: 443 . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 444 445 Notes: 446 Convergence is then declared after a fixed number of iterations have been used. 447 448 Level: advanced 449 450 .keywords: SNES, nonlinear, skip, converged, convergence 451 452 .seealso: SNESSetConvergenceTest() 453 @*/ 454 PetscErrorCode SNESSkipConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 455 { 456 PetscErrorCode ierr; 457 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 460 PetscValidPointer(reason,6); 461 462 *reason = SNES_CONVERGED_ITERATING; 463 464 if (fnorm != fnorm) { 465 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 466 *reason = SNES_DIVERGED_FNORM_NAN; 467 } else if(it == snes->max_its) { 468 *reason = SNES_CONVERGED_ITS; 469 } 470 PetscFunctionReturn(0); 471 } 472 473 #undef __FUNCT__ 474 #define __FUNCT__ "SNESDefaultGetWork" 475 /*@ 476 SNESDefaultGetWork - Gets a number of work vectors. 477 478 Input Parameters: 479 . snes - the SNES context 480 . nw - number of work vectors to allocate 481 482 Level: developer 483 484 Notes: 485 Call this only if no work vectors have been allocated 486 @*/ 487 PetscErrorCode SNESDefaultGetWork(SNES snes,PetscInt nw) 488 { 489 PetscErrorCode ierr; 490 491 PetscFunctionBegin; 492 if (snes->work) {ierr = VecDestroyVecs(snes->nwork,&snes->work);CHKERRQ(ierr);} 493 snes->nwork = nw; 494 ierr = VecDuplicateVecs(snes->vec_sol,snes->nwork,&snes->work);CHKERRQ(ierr); 495 ierr = PetscLogObjectParents(snes,nw,snes->work);CHKERRQ(ierr); 496 PetscFunctionReturn(0); 497 } 498