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,MPIU_SUM,((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 Level: intermediate 200 201 .keywords: SNES, default, monitor, residual 202 203 .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate() 204 @*/ 205 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy) 206 { 207 PetscErrorCode ierr; 208 PetscReal perc,rel; 209 PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy; 210 /* should be in a MonitorRangeContext */ 211 static PetscReal prev; 212 213 PetscFunctionBegin; 214 if (!it) prev = rnorm; 215 if (!dummy) {ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);} 216 ierr = SNESMonitorRange_Private(snes,it,&perc);CHKERRQ(ierr); 217 218 rel = (prev - rnorm)/prev; 219 prev = rnorm; 220 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); 221 if (!dummy) {ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr);} 222 PetscFunctionReturn(0); 223 } 224 225 typedef struct { 226 PetscViewerASCIIMonitor viewer; 227 PetscReal *history; 228 } SNESMonitorRatioContext; 229 230 #undef __FUNCT__ 231 #define __FUNCT__ "SNESMonitorRatio" 232 /*@C 233 SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio 234 of residual norm at each iteration to the previous. 235 236 Collective on SNES 237 238 Input Parameters: 239 + snes - the SNES context 240 . its - iteration number 241 . fgnorm - 2-norm of residual (or gradient) 242 - dummy - context of monitor 243 244 Level: intermediate 245 246 .keywords: SNES, nonlinear, monitor, norm 247 248 .seealso: SNESMonitorSet(), SNESMonitorSolution() 249 @*/ 250 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 251 { 252 PetscErrorCode ierr; 253 PetscInt len; 254 PetscReal *history; 255 SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy; 256 257 PetscFunctionBegin; 258 ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr); 259 if (!its || !history || its > len) { 260 ierr = PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr); 261 } else { 262 PetscReal ratio = fgnorm/history[its-1]; 263 ierr = PetscViewerASCIIMonitorPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %G \n",its,fgnorm,ratio);CHKERRQ(ierr); 264 } 265 PetscFunctionReturn(0); 266 } 267 268 /* 269 If the we set the history monitor space then we must destroy it 270 */ 271 #undef __FUNCT__ 272 #define __FUNCT__ "SNESMonitorRatioDestroy" 273 PetscErrorCode SNESMonitorRatioDestroy(void *ct) 274 { 275 PetscErrorCode ierr; 276 SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)ct; 277 278 PetscFunctionBegin; 279 ierr = PetscFree(ctx->history);CHKERRQ(ierr); 280 ierr = PetscViewerASCIIMonitorDestroy(ctx->viewer);CHKERRQ(ierr); 281 ierr = PetscFree(ctx);CHKERRQ(ierr); 282 PetscFunctionReturn(0); 283 } 284 285 #undef __FUNCT__ 286 #define __FUNCT__ "SNESMonitorSetRatio" 287 /*@C 288 SNESMonitorSetRatio - Sets SNES to use a monitor that prints the 289 ratio of the function norm at each iteration. 290 291 Collective on SNES 292 293 Input Parameters: 294 + snes - the SNES context 295 - viewer - ASCII viewer to print output 296 297 Level: intermediate 298 299 .keywords: SNES, nonlinear, monitor, norm 300 301 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault() 302 @*/ 303 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSetRatio(SNES snes,PetscViewerASCIIMonitor viewer) 304 { 305 PetscErrorCode ierr; 306 SNESMonitorRatioContext *ctx; 307 PetscReal *history; 308 309 PetscFunctionBegin; 310 if (!viewer) { 311 ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr); 312 ierr = PetscObjectReference((PetscObject)viewer);CHKERRQ(ierr); 313 } 314 ierr = PetscNewLog(snes,SNESMonitorRatioContext,&ctx); 315 ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 316 if (!history) { 317 ierr = PetscMalloc(100*sizeof(PetscReal),&ctx->history);CHKERRQ(ierr); 318 ierr = SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);CHKERRQ(ierr); 319 } 320 ctx->viewer = viewer; 321 ierr = SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);CHKERRQ(ierr); 322 PetscFunctionReturn(0); 323 } 324 325 /* ---------------------------------------------------------------- */ 326 #undef __FUNCT__ 327 #define __FUNCT__ "SNESMonitorDefaultShort" 328 /* 329 Default (short) SNES Monitor, same as SNESMonitorDefault() except 330 it prints fewer digits of the residual as the residual gets smaller. 331 This is because the later digits are meaningless and are often 332 different on different machines; by using this routine different 333 machines will usually generate the same output. 334 */ 335 PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 336 { 337 PetscErrorCode ierr; 338 PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy; 339 340 PetscFunctionBegin; 341 if (!dummy) { 342 ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr); 343 } 344 if (fgnorm > 1.e-9) { 345 ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %G \n",its,fgnorm);CHKERRQ(ierr); 346 } else if (fgnorm > 1.e-11){ 347 ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr); 348 } else { 349 ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); 350 } 351 if (!dummy) { 352 ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr); 353 } 354 PetscFunctionReturn(0); 355 } 356 /* ---------------------------------------------------------------- */ 357 #undef __FUNCT__ 358 #define __FUNCT__ "SNESDefaultConverged" 359 /*@C 360 SNESDefaultConverged - Convergence test of the solvers for 361 systems of nonlinear equations (default). 362 363 Collective on SNES 364 365 Input Parameters: 366 + snes - the SNES context 367 . it - the iteration (0 indicates before any Newton steps) 368 . xnorm - 2-norm of current iterate 369 . pnorm - 2-norm of current step 370 . fnorm - 2-norm of function at current iterate 371 - dummy - unused context 372 373 Output Parameter: 374 . reason - one of 375 $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol), 376 $ SNES_CONVERGED_PNORM_RELATIVE - (pnorm < xtol*xnorm), 377 $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 378 $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 379 $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 380 $ SNES_CONVERGED_ITERATING - (otherwise), 381 382 where 383 + maxf - maximum number of function evaluations, 384 set with SNESSetTolerances() 385 . nfct - number of function evaluations, 386 . abstol - absolute function norm tolerance, 387 set with SNESSetTolerances() 388 - rtol - relative function norm tolerance, set with SNESSetTolerances() 389 390 Level: intermediate 391 392 .keywords: SNES, nonlinear, default, converged, convergence 393 394 .seealso: SNESSetConvergenceTest() 395 @*/ 396 PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 397 { 398 PetscErrorCode ierr; 399 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 402 PetscValidPointer(reason,6); 403 404 *reason = SNES_CONVERGED_ITERATING; 405 406 if (!it) { 407 /* set parameter for default relative tolerance convergence test */ 408 snes->ttol = fnorm*snes->rtol; 409 } 410 if (fnorm != fnorm) { 411 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 412 *reason = SNES_DIVERGED_FNORM_NAN; 413 } else if (fnorm < snes->abstol) { 414 ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr); 415 *reason = SNES_CONVERGED_FNORM_ABS; 416 } else if (snes->nfuncs >= snes->max_funcs) { 417 ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 418 *reason = SNES_DIVERGED_FUNCTION_COUNT; 419 } 420 421 if (it && !*reason) { 422 if (fnorm <= snes->ttol) { 423 ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr); 424 *reason = SNES_CONVERGED_FNORM_RELATIVE; 425 } else if (pnorm < snes->xtol*xnorm) { 426 ierr = PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes->xtol,xnorm);CHKERRQ(ierr); 427 *reason = SNES_CONVERGED_PNORM_RELATIVE; 428 } 429 } 430 PetscFunctionReturn(0); 431 } 432 433 #undef __FUNCT__ 434 #define __FUNCT__ "SNESSkipConverged" 435 /*@C 436 SNESSkipConverged - Convergence test for SNES that NEVER returns as 437 converged, UNLESS the maximum number of iteration have been reached. 438 439 Logically Collective on SNES 440 441 Input Parameters: 442 + snes - the SNES context 443 . it - the iteration (0 indicates before any Newton steps) 444 . xnorm - 2-norm of current iterate 445 . pnorm - 2-norm of current step 446 . fnorm - 2-norm of function at current iterate 447 - dummy - unused context 448 449 Output Parameter: 450 . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 451 452 Notes: 453 Convergence is then declared after a fixed number of iterations have been used. 454 455 Level: advanced 456 457 .keywords: SNES, nonlinear, skip, converged, convergence 458 459 .seealso: SNESSetConvergenceTest() 460 @*/ 461 PetscErrorCode PETSCSNES_DLLEXPORT SNESSkipConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 462 { 463 PetscErrorCode ierr; 464 465 PetscFunctionBegin; 466 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 467 PetscValidPointer(reason,6); 468 469 *reason = SNES_CONVERGED_ITERATING; 470 471 if (fnorm != fnorm) { 472 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 473 *reason = SNES_DIVERGED_FNORM_NAN; 474 } else if(it == snes->max_its) { 475 *reason = SNES_CONVERGED_ITS; 476 } 477 PetscFunctionReturn(0); 478 } 479 480