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__ "SNESMonitorDefault" 119 /*@C 120 SNESMonitorDefault - Monitors progress of the SNES solvers (default). 121 122 Collective on SNES 123 124 Input Parameters: 125 + snes - the SNES context 126 . its - iteration number 127 . fgnorm - 2-norm of residual 128 - dummy - unused context 129 130 Notes: 131 This routine prints the residual norm at each iteration. 132 133 Level: intermediate 134 135 .keywords: SNES, nonlinear, default, monitor, norm 136 137 .seealso: SNESMonitorSet(), SNESMonitorSolution() 138 @*/ 139 PetscErrorCode SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 140 { 141 PetscErrorCode ierr; 142 PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 143 144 PetscFunctionBegin; 145 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 146 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);CHKERRQ(ierr); 147 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 148 PetscFunctionReturn(0); 149 } 150 151 #undef __FUNCT__ 152 #define __FUNCT__ "SNESMonitorJacUpdateSpectrum" 153 PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes,PetscInt it,PetscReal fnorm,void *ctx) 154 { 155 #if defined(PETSC_MISSING_LAPACK_GEEV) 156 SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - Lapack routine is unavailable\nNot able to provide eigen values."); 157 #elif defined(PETSC_HAVE_ESSL) 158 SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - No support for ESSL Lapack Routines"); 159 #else 160 Vec X; 161 Mat J,dJ,dJdense; 162 PetscErrorCode ierr; 163 PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*); 164 PetscInt n,i; 165 PetscBLASInt nb,lwork; 166 PetscReal *eigr,*eigi; 167 PetscScalar *work; 168 PetscScalar *a; 169 170 PetscFunctionBegin; 171 if (it == 0) PetscFunctionReturn(0); 172 /* create the difference between the current update and the current jacobian */ 173 ierr = SNESGetSolution(snes,&X);CHKERRQ(ierr); 174 ierr = SNESGetJacobian(snes,NULL,&J,&func,NULL);CHKERRQ(ierr); 175 ierr = MatDuplicate(J,MAT_COPY_VALUES,&dJ);CHKERRQ(ierr); 176 ierr = SNESComputeJacobian(snes,X,dJ,dJ);CHKERRQ(ierr); 177 ierr = MatAXPY(dJ,-1.0,J,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 178 179 /* compute the spectrum directly */ 180 ierr = MatConvert(dJ,MATSEQDENSE,MAT_INITIAL_MATRIX,&dJdense);CHKERRQ(ierr); 181 ierr = MatGetSize(dJ,&n,NULL);CHKERRQ(ierr); 182 ierr = PetscBLASIntCast(n,&nb);CHKERRQ(ierr); 183 lwork = 3*nb; 184 ierr = PetscMalloc1(n,&eigr);CHKERRQ(ierr); 185 ierr = PetscMalloc1(n,&eigi);CHKERRQ(ierr); 186 ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr); 187 ierr = MatDenseGetArray(dJdense,&a);CHKERRQ(ierr); 188 #if !defined(PETSC_USE_COMPLEX) 189 { 190 PetscBLASInt lierr; 191 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 192 PetscStackCallBLAS("LAPACKgeev",LAPACKgeev_("N","N",&nb,a,&nb,eigr,eigi,NULL,&nb,NULL,&nb,work,&lwork,&lierr)); 193 if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"geev() error %d",lierr); 194 ierr = PetscFPTrapPop();CHKERRQ(ierr); 195 } 196 #else 197 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded for complex"); 198 #endif 199 PetscPrintf(PetscObjectComm((PetscObject)snes),"Eigenvalues of J_%d - J_%d:\n",it,it-1);CHKERRQ(ierr); 200 for (i=0;i<n;i++) { 201 PetscPrintf(PetscObjectComm((PetscObject)snes),"%5d: %20.5g + %20.5gi\n",i,(double)eigr[i],(double)eigi[i]);CHKERRQ(ierr); 202 } 203 ierr = MatDenseRestoreArray(dJdense,&a);CHKERRQ(ierr); 204 ierr = MatDestroy(&dJ);CHKERRQ(ierr); 205 ierr = MatDestroy(&dJdense);CHKERRQ(ierr); 206 ierr = PetscFree(eigr);CHKERRQ(ierr); 207 ierr = PetscFree(eigi);CHKERRQ(ierr); 208 ierr = PetscFree(work);CHKERRQ(ierr); 209 PetscFunctionReturn(0); 210 #endif 211 } 212 213 #undef __FUNCT__ 214 #define __FUNCT__ "SNESMonitorRange_Private" 215 PetscErrorCode SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per) 216 { 217 PetscErrorCode ierr; 218 Vec resid; 219 PetscReal rmax,pwork; 220 PetscInt i,n,N; 221 PetscScalar *r; 222 223 PetscFunctionBegin; 224 ierr = SNESGetFunction(snes,&resid,0,0);CHKERRQ(ierr); 225 ierr = VecNorm(resid,NORM_INFINITY,&rmax);CHKERRQ(ierr); 226 ierr = VecGetLocalSize(resid,&n);CHKERRQ(ierr); 227 ierr = VecGetSize(resid,&N);CHKERRQ(ierr); 228 ierr = VecGetArray(resid,&r);CHKERRQ(ierr); 229 pwork = 0.0; 230 for (i=0; i<n; i++) { 231 pwork += (PetscAbsScalar(r[i]) > .20*rmax); 232 } 233 ierr = MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 234 ierr = VecRestoreArray(resid,&r);CHKERRQ(ierr); 235 *per = *per/N; 236 PetscFunctionReturn(0); 237 } 238 239 #undef __FUNCT__ 240 #define __FUNCT__ "SNESMonitorRange" 241 /*@C 242 SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value. 243 244 Collective on SNES 245 246 Input Parameters: 247 + snes - iterative context 248 . it - iteration number 249 . rnorm - 2-norm (preconditioned) residual value (may be estimated). 250 - dummy - unused monitor context 251 252 Options Database Key: 253 . -snes_monitor_range - Activates SNESMonitorRange() 254 255 Level: intermediate 256 257 .keywords: SNES, default, monitor, residual 258 259 .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate() 260 @*/ 261 PetscErrorCode SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy) 262 { 263 PetscErrorCode ierr; 264 PetscReal perc,rel; 265 PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 266 /* should be in a MonitorRangeContext */ 267 static PetscReal prev; 268 269 PetscFunctionBegin; 270 if (!it) prev = rnorm; 271 ierr = SNESMonitorRange_Private(snes,it,&perc);CHKERRQ(ierr); 272 273 rel = (prev - rnorm)/prev; 274 prev = rnorm; 275 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 276 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); 277 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 278 PetscFunctionReturn(0); 279 } 280 281 typedef struct { 282 PetscViewer viewer; 283 PetscReal *history; 284 } SNESMonitorRatioContext; 285 286 #undef __FUNCT__ 287 #define __FUNCT__ "SNESMonitorRatio" 288 /*@C 289 SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio 290 of residual norm at each iteration to the previous. 291 292 Collective on SNES 293 294 Input Parameters: 295 + snes - the SNES context 296 . its - iteration number 297 . fgnorm - 2-norm of residual (or gradient) 298 - dummy - context of monitor 299 300 Level: intermediate 301 302 .keywords: SNES, nonlinear, monitor, norm 303 304 .seealso: SNESMonitorSet(), SNESMonitorSolution() 305 @*/ 306 PetscErrorCode SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 307 { 308 PetscErrorCode ierr; 309 PetscInt len; 310 PetscReal *history; 311 SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy; 312 313 PetscFunctionBegin; 314 ierr = SNESGetConvergenceHistory(snes,&history,NULL,&len);CHKERRQ(ierr); 315 ierr = PetscViewerASCIIAddTab(ctx->viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 316 if (!its || !history || its > len) { 317 ierr = PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);CHKERRQ(ierr); 318 } else { 319 PetscReal ratio = fgnorm/history[its-1]; 320 ierr = PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %14.12e \n",its,(double)fgnorm,(double)ratio);CHKERRQ(ierr); 321 } 322 ierr = PetscViewerASCIISubtractTab(ctx->viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 323 PetscFunctionReturn(0); 324 } 325 326 /* 327 If the we set the history monitor space then we must destroy it 328 */ 329 #undef __FUNCT__ 330 #define __FUNCT__ "SNESMonitorRatioDestroy" 331 PetscErrorCode SNESMonitorRatioDestroy(void **ct) 332 { 333 PetscErrorCode ierr; 334 SNESMonitorRatioContext *ctx = *(SNESMonitorRatioContext**)ct; 335 336 PetscFunctionBegin; 337 ierr = PetscFree(ctx->history);CHKERRQ(ierr); 338 ierr = PetscViewerDestroy(&ctx->viewer);CHKERRQ(ierr); 339 ierr = PetscFree(ctx);CHKERRQ(ierr); 340 PetscFunctionReturn(0); 341 } 342 343 #undef __FUNCT__ 344 #define __FUNCT__ "SNESMonitorSetRatio" 345 /*@C 346 SNESMonitorSetRatio - Sets SNES to use a monitor that prints the 347 ratio of the function norm at each iteration. 348 349 Collective on SNES 350 351 Input Parameters: 352 + snes - the SNES context 353 - viewer - ASCII viewer to print output 354 355 Level: intermediate 356 357 .keywords: SNES, nonlinear, monitor, norm 358 359 .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault() 360 @*/ 361 PetscErrorCode SNESMonitorSetRatio(SNES snes,PetscViewer viewer) 362 { 363 PetscErrorCode ierr; 364 SNESMonitorRatioContext *ctx; 365 PetscReal *history; 366 367 PetscFunctionBegin; 368 if (!viewer) { 369 ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)snes),"stdout",&viewer);CHKERRQ(ierr); 370 ierr = PetscObjectReference((PetscObject)viewer);CHKERRQ(ierr); 371 } 372 ierr = PetscNewLog(snes,&ctx);CHKERRQ(ierr); 373 ierr = SNESGetConvergenceHistory(snes,&history,NULL,NULL);CHKERRQ(ierr); 374 if (!history) { 375 ierr = PetscMalloc1(100,&ctx->history);CHKERRQ(ierr); 376 ierr = SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);CHKERRQ(ierr); 377 } 378 ctx->viewer = viewer; 379 380 ierr = SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);CHKERRQ(ierr); 381 PetscFunctionReturn(0); 382 } 383 384 /* ---------------------------------------------------------------- */ 385 #undef __FUNCT__ 386 #define __FUNCT__ "SNESMonitorDefaultShort" 387 /* 388 Default (short) SNES Monitor, same as SNESMonitorDefault() except 389 it prints fewer digits of the residual as the residual gets smaller. 390 This is because the later digits are meaningless and are often 391 different on different machines; by using this routine different 392 machines will usually generate the same output. 393 */ 394 PetscErrorCode SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 395 { 396 PetscErrorCode ierr; 397 PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 398 399 PetscFunctionBegin; 400 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 401 if (fgnorm > 1.e-9) { 402 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %g \n",its,(double)fgnorm);CHKERRQ(ierr); 403 } else if (fgnorm > 1.e-11) { 404 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,(double)fgnorm);CHKERRQ(ierr); 405 } else { 406 ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); 407 } 408 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 409 PetscFunctionReturn(0); 410 } 411 /* ---------------------------------------------------------------- */ 412 #undef __FUNCT__ 413 #define __FUNCT__ "SNESConvergedDefault" 414 /*@C 415 SNESConvergedDefault - Convergence test of the solvers for 416 systems of nonlinear equations (default). 417 418 Collective on SNES 419 420 Input Parameters: 421 + snes - the SNES context 422 . it - the iteration (0 indicates before any Newton steps) 423 . xnorm - 2-norm of current iterate 424 . snorm - 2-norm of current step 425 . fnorm - 2-norm of function at current iterate 426 - dummy - unused context 427 428 Output Parameter: 429 . reason - one of 430 $ SNES_CONVERGED_FNORM_ABS - (fnorm < abstol), 431 $ SNES_CONVERGED_SNORM_RELATIVE - (snorm < stol*xnorm), 432 $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 433 $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 434 $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 435 $ SNES_CONVERGED_ITERATING - (otherwise), 436 437 where 438 + maxf - maximum number of function evaluations, 439 set with SNESSetTolerances() 440 . nfct - number of function evaluations, 441 . abstol - absolute function norm tolerance, 442 set with SNESSetTolerances() 443 - rtol - relative function norm tolerance, set with SNESSetTolerances() 444 445 Level: intermediate 446 447 .keywords: SNES, nonlinear, default, converged, convergence 448 449 .seealso: SNESSetConvergenceTest() 450 @*/ 451 PetscErrorCode SNESConvergedDefault(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 452 { 453 PetscErrorCode ierr; 454 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 457 PetscValidPointer(reason,6); 458 459 *reason = SNES_CONVERGED_ITERATING; 460 461 if (!it) { 462 /* set parameter for default relative tolerance convergence test */ 463 snes->ttol = fnorm*snes->rtol; 464 } 465 if (PetscIsInfOrNanReal(fnorm)) { 466 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 467 *reason = SNES_DIVERGED_FNORM_NAN; 468 } else if (fnorm < snes->abstol) { 469 ierr = PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e\n",(double)fnorm,(double)snes->abstol);CHKERRQ(ierr); 470 *reason = SNES_CONVERGED_FNORM_ABS; 471 } else if (snes->nfuncs >= snes->max_funcs) { 472 ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 473 *reason = SNES_DIVERGED_FUNCTION_COUNT; 474 } 475 476 if (it && !*reason) { 477 if (fnorm <= snes->ttol) { 478 ierr = PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e (relative tolerance)\n",(double)fnorm,(double)snes->ttol);CHKERRQ(ierr); 479 *reason = SNES_CONVERGED_FNORM_RELATIVE; 480 } else if (snorm < snes->stol*xnorm) { 481 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); 482 *reason = SNES_CONVERGED_SNORM_RELATIVE; 483 } 484 } 485 PetscFunctionReturn(0); 486 } 487 488 #undef __FUNCT__ 489 #define __FUNCT__ "SNESConvergedSkip" 490 /*@C 491 SNESConvergedSkip - Convergence test for SNES that NEVER returns as 492 converged, UNLESS the maximum number of iteration have been reached. 493 494 Logically Collective on SNES 495 496 Input Parameters: 497 + snes - the SNES context 498 . it - the iteration (0 indicates before any Newton steps) 499 . xnorm - 2-norm of current iterate 500 . snorm - 2-norm of current step 501 . fnorm - 2-norm of function at current iterate 502 - dummy - unused context 503 504 Output Parameter: 505 . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 506 507 Notes: 508 Convergence is then declared after a fixed number of iterations have been used. 509 510 Level: advanced 511 512 .keywords: SNES, nonlinear, skip, converged, convergence 513 514 .seealso: SNESSetConvergenceTest() 515 @*/ 516 PetscErrorCode SNESConvergedSkip(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 517 { 518 PetscErrorCode ierr; 519 520 PetscFunctionBegin; 521 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 522 PetscValidPointer(reason,6); 523 524 *reason = SNES_CONVERGED_ITERATING; 525 526 if (fnorm != fnorm) { 527 ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 528 *reason = SNES_DIVERGED_FNORM_NAN; 529 } else if (it == snes->max_its) { 530 *reason = SNES_CONVERGED_ITS; 531 } 532 PetscFunctionReturn(0); 533 } 534 535 #undef __FUNCT__ 536 #define __FUNCT__ "SNESSetWorkVecs" 537 /*@C 538 SNESSetWorkVecs - Gets a number of work vectors. 539 540 Input Parameters: 541 . snes - the SNES context 542 . nw - number of work vectors to allocate 543 544 Level: developer 545 546 Developers Note: This is PETSC_EXTERN because it may be used by user written plugin SNES implementations 547 548 @*/ 549 PetscErrorCode SNESSetWorkVecs(SNES snes,PetscInt nw) 550 { 551 DM dm; 552 Vec v; 553 PetscErrorCode ierr; 554 555 PetscFunctionBegin; 556 if (snes->work) {ierr = VecDestroyVecs(snes->nwork,&snes->work);CHKERRQ(ierr);} 557 snes->nwork = nw; 558 559 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 560 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 561 ierr = VecDuplicateVecs(v,snes->nwork,&snes->work);CHKERRQ(ierr); 562 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 563 ierr = PetscLogObjectParents(snes,nw,snes->work);CHKERRQ(ierr); 564 PetscFunctionReturn(0); 565 } 566