173f4d377SMatthew Knepley /*$Id: snesut.c,v 1.66 2001/08/06 21:17:07 bsmith Exp $*/ 2e7e93795SLois Curfman McInnes 3e090d566SSatish Balay #include "src/snes/snesimpl.h" /*I "petscsnes.h" I*/ 4e7e93795SLois Curfman McInnes 54a2ae208SSatish Balay #undef __FUNCT__ 64a2ae208SSatish Balay #define __FUNCT__ "SNESVecViewMonitor" 73f1db9ecSBarry Smith /*@C 836851e7fSLois Curfman McInnes SNESVecViewMonitor - Monitors progress of the SNES solvers by calling 936851e7fSLois Curfman McInnes VecView() for the approximate solution at each iteration. 103f1db9ecSBarry Smith 113f1db9ecSBarry Smith Collective on SNES 123f1db9ecSBarry Smith 133f1db9ecSBarry Smith Input Parameters: 143f1db9ecSBarry Smith + snes - the SNES context 153f1db9ecSBarry Smith . its - iteration number 163f1db9ecSBarry Smith . fgnorm - 2-norm of residual (or gradient) 173f1db9ecSBarry Smith - dummy - either a viewer or PETSC_NULL 183f1db9ecSBarry Smith 1936851e7fSLois Curfman McInnes Level: intermediate 203f1db9ecSBarry Smith 2136851e7fSLois Curfman McInnes .keywords: SNES, nonlinear, vector, monitor, view 223f1db9ecSBarry Smith 2336851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView() 243f1db9ecSBarry Smith @*/ 25329f5518SBarry Smith int SNESVecViewMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 263f1db9ecSBarry Smith { 273f1db9ecSBarry Smith int ierr; 283f1db9ecSBarry Smith Vec x; 29b0a32e0cSBarry Smith PetscViewer viewer = (PetscViewer) dummy; 303f1db9ecSBarry Smith 313f1db9ecSBarry Smith PetscFunctionBegin; 323f1db9ecSBarry Smith ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr); 333f1db9ecSBarry Smith if (!viewer) { 343f1db9ecSBarry Smith MPI_Comm comm; 353f1db9ecSBarry Smith ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 36b0a32e0cSBarry Smith viewer = PETSC_VIEWER_DRAW_(comm); 373f1db9ecSBarry Smith } 383f1db9ecSBarry Smith ierr = VecView(x,viewer);CHKERRQ(ierr); 393f1db9ecSBarry Smith 403f1db9ecSBarry Smith PetscFunctionReturn(0); 413f1db9ecSBarry Smith } 423f1db9ecSBarry Smith 434a2ae208SSatish Balay #undef __FUNCT__ 44*5ed2d596SBarry Smith #define __FUNCT__ "SNESVecViewResidualMonitor" 45*5ed2d596SBarry Smith /*@C 46*5ed2d596SBarry Smith SNESVecViewResidualMonitor - Monitors progress of the SNES solvers by calling 47*5ed2d596SBarry Smith VecView() for the residual at each iteration. 48*5ed2d596SBarry Smith 49*5ed2d596SBarry Smith Collective on SNES 50*5ed2d596SBarry Smith 51*5ed2d596SBarry Smith Input Parameters: 52*5ed2d596SBarry Smith + snes - the SNES context 53*5ed2d596SBarry Smith . its - iteration number 54*5ed2d596SBarry Smith . fgnorm - 2-norm of residual (or gradient) 55*5ed2d596SBarry Smith - dummy - either a viewer or PETSC_NULL 56*5ed2d596SBarry Smith 57*5ed2d596SBarry Smith Level: intermediate 58*5ed2d596SBarry Smith 59*5ed2d596SBarry Smith .keywords: SNES, nonlinear, vector, monitor, view 60*5ed2d596SBarry Smith 61*5ed2d596SBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView() 62*5ed2d596SBarry Smith @*/ 63*5ed2d596SBarry Smith int SNESVecViewResidualMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 64*5ed2d596SBarry Smith { 65*5ed2d596SBarry Smith int ierr; 66*5ed2d596SBarry Smith Vec x; 67*5ed2d596SBarry Smith PetscViewer viewer = (PetscViewer) dummy; 68*5ed2d596SBarry Smith 69*5ed2d596SBarry Smith PetscFunctionBegin; 70*5ed2d596SBarry Smith ierr = SNESGetFunction(snes,&x,0,0);CHKERRQ(ierr); 71*5ed2d596SBarry Smith if (!viewer) { 72*5ed2d596SBarry Smith MPI_Comm comm; 73*5ed2d596SBarry Smith ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 74*5ed2d596SBarry Smith viewer = PETSC_VIEWER_DRAW_(comm); 75*5ed2d596SBarry Smith } 76*5ed2d596SBarry Smith ierr = VecView(x,viewer);CHKERRQ(ierr); 77*5ed2d596SBarry Smith 78*5ed2d596SBarry Smith PetscFunctionReturn(0); 79*5ed2d596SBarry Smith } 80*5ed2d596SBarry Smith 81*5ed2d596SBarry Smith #undef __FUNCT__ 824a2ae208SSatish Balay #define __FUNCT__ "SNESVecViewUpdateMonitor" 83d132466eSBarry Smith /*@C 847c922b88SBarry Smith SNESVecViewUpdateMonitor - Monitors progress of the SNES solvers by calling 85d132466eSBarry Smith VecView() for the UPDATE to the solution at each iteration. 86d132466eSBarry Smith 87d132466eSBarry Smith Collective on SNES 88d132466eSBarry Smith 89d132466eSBarry Smith Input Parameters: 90d132466eSBarry Smith + snes - the SNES context 91d132466eSBarry Smith . its - iteration number 92d132466eSBarry Smith . fgnorm - 2-norm of residual (or gradient) 93d132466eSBarry Smith - dummy - either a viewer or PETSC_NULL 94d132466eSBarry Smith 95d132466eSBarry Smith Level: intermediate 96d132466eSBarry Smith 97d132466eSBarry Smith .keywords: SNES, nonlinear, vector, monitor, view 98d132466eSBarry Smith 99d132466eSBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView() 100d132466eSBarry Smith @*/ 101329f5518SBarry Smith int SNESVecViewUpdateMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 102d132466eSBarry Smith { 103d132466eSBarry Smith int ierr; 104d132466eSBarry Smith Vec x; 105b0a32e0cSBarry Smith PetscViewer viewer = (PetscViewer) dummy; 106d132466eSBarry Smith 107d132466eSBarry Smith PetscFunctionBegin; 108d132466eSBarry Smith ierr = SNESGetSolutionUpdate(snes,&x);CHKERRQ(ierr); 109d132466eSBarry Smith if (!viewer) { 110d132466eSBarry Smith MPI_Comm comm; 111d132466eSBarry Smith ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 112b0a32e0cSBarry Smith viewer = PETSC_VIEWER_DRAW_(comm); 113d132466eSBarry Smith } 114d132466eSBarry Smith ierr = VecView(x,viewer);CHKERRQ(ierr); 115d132466eSBarry Smith 116d132466eSBarry Smith PetscFunctionReturn(0); 117d132466eSBarry Smith } 118d132466eSBarry Smith 1194a2ae208SSatish Balay #undef __FUNCT__ 1204a2ae208SSatish Balay #define __FUNCT__ "SNESDefaultMonitor" 1214b828684SBarry Smith /*@C 122f525115eSLois Curfman McInnes SNESDefaultMonitor - Monitoring progress of the SNES solvers (default). 123e7e93795SLois Curfman McInnes 124c7afd0dbSLois Curfman McInnes Collective on SNES 125c7afd0dbSLois Curfman McInnes 126e7e93795SLois Curfman McInnes Input Parameters: 127c7afd0dbSLois Curfman McInnes + snes - the SNES context 128e7e93795SLois Curfman McInnes . its - iteration number 129e7e93795SLois Curfman McInnes . fgnorm - 2-norm of residual (or gradient) 130c7afd0dbSLois Curfman McInnes - dummy - unused context 131fee21e36SBarry Smith 132e7e93795SLois Curfman McInnes Notes: 133e7e93795SLois Curfman McInnes For SNES_NONLINEAR_EQUATIONS methods the routine prints the 134e7e93795SLois Curfman McInnes residual norm at each iteration. 135e7e93795SLois Curfman McInnes 136e7e93795SLois Curfman McInnes For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the 137e7e93795SLois Curfman McInnes function value and gradient norm at each iteration. 138e7e93795SLois Curfman McInnes 13936851e7fSLois Curfman McInnes Level: intermediate 14036851e7fSLois Curfman McInnes 141e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm 142e7e93795SLois Curfman McInnes 14336851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESVecViewMonitor() 144e7e93795SLois Curfman McInnes @*/ 145329f5518SBarry Smith int SNESDefaultMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 146e7e93795SLois Curfman McInnes { 147d132466eSBarry Smith int ierr; 148b0a32e0cSBarry Smith PetscViewer viewer = (PetscViewer) dummy; 149d132466eSBarry Smith 1503a40ed3dSBarry Smith PetscFunctionBegin; 151b0a32e0cSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(snes->comm); 1527c922b88SBarry Smith 15376be9ce4SBarry Smith if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 154a0e26f09SSatish Balay ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr); 15576be9ce4SBarry Smith } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 156a0e26f09SSatish Balay ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function value %14.12e, Gradient norm %14.12e \n",its,snes->fc,fgnorm);CHKERRQ(ierr); 15729bbc08cSBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown method class"); 1583a40ed3dSBarry Smith PetscFunctionReturn(0); 159e7e93795SLois Curfman McInnes } 1603f1db9ecSBarry Smith 1613a7fca6bSBarry Smith #undef __FUNCT__ 1623a7fca6bSBarry Smith #define __FUNCT__ "SNESRatioMonitor" 1633a7fca6bSBarry Smith /*@C 1643a7fca6bSBarry Smith SNESRatioMonitor - Monitoring progress of the SNES solvers, prints ratio 1653a7fca6bSBarry Smith of residual norm at each iteration to previous 1663a7fca6bSBarry Smith 1673a7fca6bSBarry Smith Collective on SNES 1683a7fca6bSBarry Smith 1693a7fca6bSBarry Smith Input Parameters: 1703a7fca6bSBarry Smith + snes - the SNES context 1713a7fca6bSBarry Smith . its - iteration number 1723a7fca6bSBarry Smith . fgnorm - 2-norm of residual (or gradient) 1733a7fca6bSBarry Smith - dummy - unused context 1743a7fca6bSBarry Smith 1753a7fca6bSBarry Smith Level: intermediate 1763a7fca6bSBarry Smith 1773a7fca6bSBarry Smith .keywords: SNES, nonlinear, monitor, norm 1783a7fca6bSBarry Smith 1793a7fca6bSBarry Smith .seealso: SNESSetMonitor(), SNESVecViewMonitor() 1803a7fca6bSBarry Smith @*/ 1813a7fca6bSBarry Smith int SNESRatioMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 1823a7fca6bSBarry Smith { 1833a7fca6bSBarry Smith int ierr,len; 18487828ca2SBarry Smith PetscReal *history; 1853a7fca6bSBarry Smith PetscViewer viewer; 1863a7fca6bSBarry Smith 1873a7fca6bSBarry Smith PetscFunctionBegin; 1883a7fca6bSBarry Smith viewer = PETSC_VIEWER_STDOUT_(snes->comm); 1893a7fca6bSBarry Smith 1903a7fca6bSBarry Smith ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr); 1913a7fca6bSBarry Smith if (its == 0 || !history || its > len) { 1923a7fca6bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr); 1933a7fca6bSBarry Smith } else { 19487828ca2SBarry Smith PetscReal ratio = fgnorm/history[its-1]; 1953a7fca6bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e %g \n",its,fgnorm,ratio);CHKERRQ(ierr); 1963a7fca6bSBarry Smith } 1973a7fca6bSBarry Smith PetscFunctionReturn(0); 1983a7fca6bSBarry Smith } 1993a7fca6bSBarry Smith 2003a7fca6bSBarry Smith /* 2013a7fca6bSBarry Smith If the we set the history monitor space then we must destroy it 2023a7fca6bSBarry Smith */ 2033a7fca6bSBarry Smith #undef __FUNCT__ 2043a7fca6bSBarry Smith #define __FUNCT__ "SNESRatioMonitorDestroy" 2053a7fca6bSBarry Smith int SNESRatioMonitorDestroy(void *history) 2063a7fca6bSBarry Smith { 2073a7fca6bSBarry Smith int ierr; 2083a7fca6bSBarry Smith 2093a7fca6bSBarry Smith PetscFunctionBegin; 2103a7fca6bSBarry Smith ierr = PetscFree(history);CHKERRQ(ierr); 2113a7fca6bSBarry Smith PetscFunctionReturn(0); 2123a7fca6bSBarry Smith } 2133a7fca6bSBarry Smith 2143a7fca6bSBarry Smith #undef __FUNCT__ 2153a7fca6bSBarry Smith #define __FUNCT__ "SNESSetRatioMonitor" 2163a7fca6bSBarry Smith /*@C 2173a7fca6bSBarry Smith SNESSetRatioMonitor - Sets SNES to use a monitor that prints the 2183a7fca6bSBarry Smith ratio of the function norm at each iteration 2193a7fca6bSBarry Smith 2203a7fca6bSBarry Smith Collective on SNES 2213a7fca6bSBarry Smith 2223a7fca6bSBarry Smith Input Parameters: 2233a7fca6bSBarry Smith . snes - the SNES context 2243a7fca6bSBarry Smith 2253a7fca6bSBarry Smith Level: intermediate 2263a7fca6bSBarry Smith 2273a7fca6bSBarry Smith .keywords: SNES, nonlinear, monitor, norm 2283a7fca6bSBarry Smith 2293a7fca6bSBarry Smith .seealso: SNESSetMonitor(), SNESVecViewMonitor(), SNESDefaultMonitor() 2303a7fca6bSBarry Smith @*/ 2313a7fca6bSBarry Smith int SNESSetRatioMonitor(SNES snes) 2323a7fca6bSBarry Smith { 2333a7fca6bSBarry Smith int ierr; 23487828ca2SBarry Smith PetscReal *history; 2353a7fca6bSBarry Smith 2363a7fca6bSBarry Smith PetscFunctionBegin; 2373a7fca6bSBarry Smith 2383a7fca6bSBarry Smith ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 2393a7fca6bSBarry Smith if (!history) { 2403a7fca6bSBarry Smith ierr = PetscMalloc(100*sizeof(double),&history);CHKERRQ(ierr); 2413a7fca6bSBarry Smith ierr = SNESSetConvergenceHistory(snes,history,0,100,PETSC_TRUE);CHKERRQ(ierr); 2423a7fca6bSBarry Smith ierr = SNESSetMonitor(snes,SNESRatioMonitor,history,SNESRatioMonitorDestroy);CHKERRQ(ierr); 2433a7fca6bSBarry Smith } else { 2443a7fca6bSBarry Smith ierr = SNESSetMonitor(snes,SNESRatioMonitor,0,0);CHKERRQ(ierr); 2453a7fca6bSBarry Smith } 2463a7fca6bSBarry Smith PetscFunctionReturn(0); 2473a7fca6bSBarry Smith } 2483a7fca6bSBarry Smith 249e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */ 2504a2ae208SSatish Balay #undef __FUNCT__ 2514a2ae208SSatish Balay #define __FUNCT__ "SNESDefaultSMonitor" 252be1f7002SBarry Smith /* 253be1f7002SBarry Smith Default (short) SNES Monitor, same as SNESDefaultMonitor() except 254be1f7002SBarry Smith it prints fewer digits of the residual as the residual gets smaller. 255be1f7002SBarry Smith This is because the later digits are meaningless and are often 256be1f7002SBarry Smith different on different machines; by using this routine different 257be1f7002SBarry Smith machines will usually generate the same output. 258be1f7002SBarry Smith */ 259329f5518SBarry Smith int SNESDefaultSMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 260e7e93795SLois Curfman McInnes { 261d132466eSBarry Smith int ierr; 262d132466eSBarry Smith 2633a40ed3dSBarry Smith PetscFunctionBegin; 264e7e93795SLois Curfman McInnes if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 2658f240d10SBarry Smith if (fgnorm > 1.e-9) { 266a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr); 2673a40ed3dSBarry Smith } else if (fgnorm > 1.e-11){ 268a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr); 2693a40ed3dSBarry Smith } else { 270a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); 271e7e93795SLois Curfman McInnes } 272e7e93795SLois Curfman McInnes } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 2738f240d10SBarry Smith if (fgnorm > 1.e-9) { 274a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr); 2753a40ed3dSBarry Smith } else if (fgnorm > 1.e-11) { 276a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);CHKERRQ(ierr); 2773a40ed3dSBarry Smith } else { 278a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);CHKERRQ(ierr); 279e7e93795SLois Curfman McInnes } 28029bbc08cSBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown method class"); 2813a40ed3dSBarry Smith PetscFunctionReturn(0); 282e7e93795SLois Curfman McInnes } 283e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */ 2844a2ae208SSatish Balay #undef __FUNCT__ 2854a2ae208SSatish Balay #define __FUNCT__ "SNESConverged_EQ_LS" 2864b828684SBarry Smith /*@C 287f525115eSLois Curfman McInnes SNESConverged_EQ_LS - Monitors the convergence of the solvers for 288f525115eSLois Curfman McInnes systems of nonlinear equations (default). 289e7e93795SLois Curfman McInnes 290c7afd0dbSLois Curfman McInnes Collective on SNES 291c7afd0dbSLois Curfman McInnes 292e7e93795SLois Curfman McInnes Input Parameters: 293c7afd0dbSLois Curfman McInnes + snes - the SNES context 294e7e93795SLois Curfman McInnes . xnorm - 2-norm of current iterate 295e7e93795SLois Curfman McInnes . pnorm - 2-norm of current step 296e7e93795SLois Curfman McInnes . fnorm - 2-norm of function 297c7afd0dbSLois Curfman McInnes - dummy - unused context 298e7e93795SLois Curfman McInnes 299184914b5SBarry Smith Output Parameter: 300184914b5SBarry Smith . reason - one of 301184914b5SBarry Smith $ SNES_CONVERGED_FNORM_ABS - (fnorm < atol), 3023304466cSBarry Smith $ SNES_CONVERGED_PNORM_RELATIVE - (pnorm < xtol*xnorm), 303184914b5SBarry Smith $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 304184914b5SBarry Smith $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 305184914b5SBarry Smith $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 306184914b5SBarry Smith $ SNES_CONVERGED_ITERATING - (otherwise), 307e7e93795SLois Curfman McInnes 308e7e93795SLois Curfman McInnes where 309c7afd0dbSLois Curfman McInnes + maxf - maximum number of function evaluations, 310c7afd0dbSLois Curfman McInnes set with SNESSetTolerances() 311c7afd0dbSLois Curfman McInnes . nfct - number of function evaluations, 312c7afd0dbSLois Curfman McInnes . atol - absolute function norm tolerance, 313c7afd0dbSLois Curfman McInnes set with SNESSetTolerances() 314c7afd0dbSLois Curfman McInnes - rtol - relative function norm tolerance, set with SNESSetTolerances() 315fee21e36SBarry Smith 31636851e7fSLois Curfman McInnes Level: intermediate 31736851e7fSLois Curfman McInnes 318e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence 319e7e93795SLois Curfman McInnes 320e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged() 321e7e93795SLois Curfman McInnes @*/ 322329f5518SBarry Smith int SNESConverged_EQ_LS(SNES snes,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 323e7e93795SLois Curfman McInnes { 3243a40ed3dSBarry Smith PetscFunctionBegin; 325d252947aSBarry Smith if (snes->method_class != SNES_NONLINEAR_EQUATIONS) { 32629bbc08cSBarry Smith SETERRQ(PETSC_ERR_ARG_WRONG,"For SNES_NONLINEAR_EQUATIONS only"); 327d252947aSBarry Smith } 328184914b5SBarry Smith 329d252947aSBarry Smith if (fnorm != fnorm) { 330b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n"); 331184914b5SBarry Smith *reason = SNES_DIVERGED_FNORM_NAN; 332184914b5SBarry Smith } else if (fnorm <= snes->ttol) { 333b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol); 334184914b5SBarry Smith *reason = SNES_CONVERGED_FNORM_RELATIVE; 335184914b5SBarry Smith } else if (fnorm < snes->atol) { 336b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol); 337184914b5SBarry Smith *reason = SNES_CONVERGED_FNORM_ABS; 3383304466cSBarry Smith } else if (pnorm < snes->xtol*xnorm) { 339b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm); 340184914b5SBarry Smith *reason = SNES_CONVERGED_PNORM_RELATIVE; 341184914b5SBarry Smith } else if (snes->nfuncs > snes->max_funcs) { 342b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs,snes->max_funcs); 343184914b5SBarry Smith *reason = SNES_DIVERGED_FUNCTION_COUNT ; 344184914b5SBarry Smith } else { 345184914b5SBarry Smith *reason = SNES_CONVERGED_ITERATING; 346e7e93795SLois Curfman McInnes } 3473a40ed3dSBarry Smith PetscFunctionReturn(0); 348e7e93795SLois Curfman McInnes } 349e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */ 3504a2ae208SSatish Balay #undef __FUNCT__ 3514a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_SetConvergenceTestEW" 352e7e93795SLois Curfman McInnes /*@ 353f525115eSLois Curfman McInnes SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test 354e7e93795SLois Curfman McInnes for the linear solvers within an inexact Newton method. 355e7e93795SLois Curfman McInnes 356c7afd0dbSLois Curfman McInnes Collective on SNES 357c7afd0dbSLois Curfman McInnes 358e7e93795SLois Curfman McInnes Input Parameter: 359e7e93795SLois Curfman McInnes . snes - SNES context 360e7e93795SLois Curfman McInnes 361e7e93795SLois Curfman McInnes Notes: 362e7e93795SLois Curfman McInnes Currently, the default is to use a constant relative tolerance for 363e7e93795SLois Curfman McInnes the inner linear solvers. Alternatively, one can use the 364e7e93795SLois Curfman McInnes Eisenstat-Walker method, where the relative convergence tolerance 365e7e93795SLois Curfman McInnes is reset at each Newton iteration according progress of the nonlinear 366e7e93795SLois Curfman McInnes solver. 367e7e93795SLois Curfman McInnes 36836851e7fSLois Curfman McInnes Level: advanced 36936851e7fSLois Curfman McInnes 370e7e93795SLois Curfman McInnes Reference: 371e7e93795SLois Curfman McInnes S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 372e30ad881SLois Curfman McInnes inexact Newton method", SISC 17 (1), pp.16-32, 1996. 373e7e93795SLois Curfman McInnes 374e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 375e7e93795SLois Curfman McInnes @*/ 376e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes) 377e7e93795SLois Curfman McInnes { 3783a40ed3dSBarry Smith PetscFunctionBegin; 379186905e3SBarry Smith snes->ksp_ewconv = PETSC_TRUE; 3803a40ed3dSBarry Smith PetscFunctionReturn(0); 381e7e93795SLois Curfman McInnes } 382e7e93795SLois Curfman McInnes 3834a2ae208SSatish Balay #undef __FUNCT__ 3844a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_SetParametersEW" 385e7e93795SLois Curfman McInnes /*@ 386e7e93795SLois Curfman McInnes SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker 387e7e93795SLois Curfman McInnes convergence criteria for the linear solvers within an inexact 388e7e93795SLois Curfman McInnes Newton method. 389e7e93795SLois Curfman McInnes 390c7afd0dbSLois Curfman McInnes Collective on SNES 391c7afd0dbSLois Curfman McInnes 392e7e93795SLois Curfman McInnes Input Parameters: 393c7afd0dbSLois Curfman McInnes + snes - SNES context 394e7e93795SLois Curfman McInnes . version - version 1 or 2 (default is 2) 395c7afd0dbSLois Curfman McInnes . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 396c7afd0dbSLois Curfman McInnes . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 397c7afd0dbSLois Curfman McInnes . alpha - power for version 2 rtol computation (1 < alpha <= 2) 398e7e93795SLois Curfman McInnes . alpha2 - power for safeguard 399e7e93795SLois Curfman McInnes . gamma2 - multiplicative factor for version 2 rtol computation 400c7afd0dbSLois Curfman McInnes (0 <= gamma2 <= 1) 401c7afd0dbSLois Curfman McInnes - threshold - threshold for imposing safeguard (0 < threshold < 1) 402fee21e36SBarry Smith 403e7e93795SLois Curfman McInnes Note: 404e7e93795SLois Curfman McInnes Use PETSC_DEFAULT to retain the default for any of the parameters. 405e7e93795SLois Curfman McInnes 40636851e7fSLois Curfman McInnes Level: advanced 40736851e7fSLois Curfman McInnes 408e7e93795SLois Curfman McInnes Reference: 409e7e93795SLois Curfman McInnes S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 410e7e93795SLois Curfman McInnes inexact Newton method", Utah State University Math. Stat. Dept. Res. 411e7e93795SLois Curfman McInnes Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 412e7e93795SLois Curfman McInnes 413e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 414e7e93795SLois Curfman McInnes 415e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW() 416e7e93795SLois Curfman McInnes @*/ 417329f5518SBarry Smith int SNES_KSP_SetParametersEW(SNES snes,int version,PetscReal rtol_0, 418329f5518SBarry Smith PetscReal rtol_max,PetscReal gamma2,PetscReal alpha, 419329f5518SBarry Smith PetscReal alpha2,PetscReal threshold) 420e7e93795SLois Curfman McInnes { 421e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 4223a40ed3dSBarry Smith 4233a40ed3dSBarry Smith PetscFunctionBegin; 42429bbc08cSBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing"); 425e7e93795SLois Curfman McInnes if (version != PETSC_DEFAULT) kctx->version = version; 426e7e93795SLois Curfman McInnes if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 427e7e93795SLois Curfman McInnes if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 428e7e93795SLois Curfman McInnes if (gamma2 != PETSC_DEFAULT) kctx->gamma = gamma2; 429e7e93795SLois Curfman McInnes if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 430e7e93795SLois Curfman McInnes if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 431e7e93795SLois Curfman McInnes if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 432a8c6a408SBarry Smith if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) { 43329bbc08cSBarry Smith SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0); 434a8c6a408SBarry Smith } 435a8c6a408SBarry Smith if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) { 436091e6287SMatthew Knepley SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%g) < 1.0\n",kctx->rtol_max); 437a8c6a408SBarry Smith } 438a8c6a408SBarry Smith if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) { 439091e6287SMatthew Knepley SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%g) < 1.0\n",kctx->threshold); 440a8c6a408SBarry Smith } 441a8c6a408SBarry Smith if (kctx->gamma < 0.0 || kctx->gamma > 1.0) { 442091e6287SMatthew Knepley SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%g) <= 1.0\n",kctx->gamma); 443a8c6a408SBarry Smith } 444a8c6a408SBarry Smith if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) { 445091e6287SMatthew Knepley SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%g) <= 2.0\n",kctx->alpha); 446a8c6a408SBarry Smith } 447a8c6a408SBarry Smith if (kctx->version != 1 && kctx->version !=2) { 44829bbc08cSBarry Smith SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 and 2 are supported: %d",kctx->version); 449a8c6a408SBarry Smith } 4503a40ed3dSBarry Smith PetscFunctionReturn(0); 451e7e93795SLois Curfman McInnes } 452e7e93795SLois Curfman McInnes 4534a2ae208SSatish Balay #undef __FUNCT__ 4544a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_EW_ComputeRelativeTolerance_Private" 455e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp) 456e7e93795SLois Curfman McInnes { 457e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 458329f5518SBarry Smith PetscReal rtol = 0.0,stol; 459e7e93795SLois Curfman McInnes int ierr; 4603a40ed3dSBarry Smith 4613a40ed3dSBarry Smith PetscFunctionBegin; 46229bbc08cSBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists"); 463c38d4ed2SBarry Smith if (!snes->iter) { /* first time in, so use the original user rtol */ 464e7e93795SLois Curfman McInnes rtol = kctx->rtol_0; 465e7e93795SLois Curfman McInnes } else { 466e7e93795SLois Curfman McInnes if (kctx->version == 1) { 467e7e93795SLois Curfman McInnes rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 468e7e93795SLois Curfman McInnes if (rtol < 0.0) rtol = -rtol; 469e7e93795SLois Curfman McInnes stol = pow(kctx->rtol_last,kctx->alpha2); 4700452661fSBarry Smith if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 471e7e93795SLois Curfman McInnes } else if (kctx->version == 2) { 472e7e93795SLois Curfman McInnes rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha); 473e7e93795SLois Curfman McInnes stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha); 4740452661fSBarry Smith if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 47529bbc08cSBarry Smith } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 or 2 are supported: %d",kctx->version); 476e7e93795SLois Curfman McInnes } 4770452661fSBarry Smith rtol = PetscMin(rtol,kctx->rtol_max); 478e7e93795SLois Curfman McInnes kctx->rtol_last = rtol; 479b0a32e0cSBarry Smith PetscLogInfo(snes,"SNES_KSP_EW_ComputeRelativeTolerance_Private: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol); 4803131a8b6SLois Curfman McInnes ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 481e7e93795SLois Curfman McInnes kctx->norm_last = snes->norm; 4823a40ed3dSBarry Smith PetscFunctionReturn(0); 483e7e93795SLois Curfman McInnes } 484e7e93795SLois Curfman McInnes 4854a2ae208SSatish Balay #undef __FUNCT__ 4864a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_EW_Converged_Private" 487329f5518SBarry Smith int SNES_KSP_EW_Converged_Private(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx) 488e7e93795SLois Curfman McInnes { 489e7e93795SLois Curfman McInnes SNES snes = (SNES)ctx; 490e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 4913acb151aSSatish Balay int ierr; 492e7e93795SLois Curfman McInnes 4933a40ed3dSBarry Smith PetscFunctionBegin; 49429bbc08cSBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context set"); 495184914b5SBarry Smith if (n == 0) {ierr = SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);CHKERRQ(ierr);} 496211a6b7eSSatish Balay ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx);CHKERRQ(ierr); 497e7e93795SLois Curfman McInnes kctx->lresid_last = rnorm; 498211a6b7eSSatish Balay if (*reason) { 499b0a32e0cSBarry Smith PetscLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm); 5003a40ed3dSBarry Smith } 501211a6b7eSSatish Balay PetscFunctionReturn(0); 502e7e93795SLois Curfman McInnes } 503e7e93795SLois Curfman McInnes 504e7e93795SLois Curfman McInnes 505