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