1*3a7fca6bSBarry Smith /*$Id: snesut.c,v 1.64 2001/04/10 19:36:48 bsmith Exp bsmith $*/ 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__ 444a2ae208SSatish Balay #define __FUNCT__ "SNESVecViewUpdateMonitor" 45d132466eSBarry Smith /*@C 467c922b88SBarry Smith SNESVecViewUpdateMonitor - Monitors progress of the SNES solvers by calling 47d132466eSBarry Smith VecView() for the UPDATE to the solution at each iteration. 48d132466eSBarry Smith 49d132466eSBarry Smith Collective on SNES 50d132466eSBarry Smith 51d132466eSBarry Smith Input Parameters: 52d132466eSBarry Smith + snes - the SNES context 53d132466eSBarry Smith . its - iteration number 54d132466eSBarry Smith . fgnorm - 2-norm of residual (or gradient) 55d132466eSBarry Smith - dummy - either a viewer or PETSC_NULL 56d132466eSBarry Smith 57d132466eSBarry Smith Level: intermediate 58d132466eSBarry Smith 59d132466eSBarry Smith .keywords: SNES, nonlinear, vector, monitor, view 60d132466eSBarry Smith 61d132466eSBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView() 62d132466eSBarry Smith @*/ 63329f5518SBarry Smith int SNESVecViewUpdateMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 64d132466eSBarry Smith { 65d132466eSBarry Smith int ierr; 66d132466eSBarry Smith Vec x; 67b0a32e0cSBarry Smith PetscViewer viewer = (PetscViewer) dummy; 68d132466eSBarry Smith 69d132466eSBarry Smith PetscFunctionBegin; 70d132466eSBarry Smith ierr = SNESGetSolutionUpdate(snes,&x);CHKERRQ(ierr); 71d132466eSBarry Smith if (!viewer) { 72d132466eSBarry Smith MPI_Comm comm; 73d132466eSBarry Smith ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 74b0a32e0cSBarry Smith viewer = PETSC_VIEWER_DRAW_(comm); 75d132466eSBarry Smith } 76d132466eSBarry Smith ierr = VecView(x,viewer);CHKERRQ(ierr); 77d132466eSBarry Smith 78d132466eSBarry Smith PetscFunctionReturn(0); 79d132466eSBarry Smith } 80d132466eSBarry Smith 814a2ae208SSatish Balay #undef __FUNCT__ 824a2ae208SSatish Balay #define __FUNCT__ "SNESDefaultMonitor" 834b828684SBarry Smith /*@C 84f525115eSLois Curfman McInnes SNESDefaultMonitor - Monitoring progress of the SNES solvers (default). 85e7e93795SLois Curfman McInnes 86c7afd0dbSLois Curfman McInnes Collective on SNES 87c7afd0dbSLois Curfman McInnes 88e7e93795SLois Curfman McInnes Input Parameters: 89c7afd0dbSLois Curfman McInnes + snes - the SNES context 90e7e93795SLois Curfman McInnes . its - iteration number 91e7e93795SLois Curfman McInnes . fgnorm - 2-norm of residual (or gradient) 92c7afd0dbSLois Curfman McInnes - dummy - unused context 93fee21e36SBarry Smith 94e7e93795SLois Curfman McInnes Notes: 95e7e93795SLois Curfman McInnes For SNES_NONLINEAR_EQUATIONS methods the routine prints the 96e7e93795SLois Curfman McInnes residual norm at each iteration. 97e7e93795SLois Curfman McInnes 98e7e93795SLois Curfman McInnes For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the 99e7e93795SLois Curfman McInnes function value and gradient norm at each iteration. 100e7e93795SLois Curfman McInnes 10136851e7fSLois Curfman McInnes Level: intermediate 10236851e7fSLois Curfman McInnes 103e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm 104e7e93795SLois Curfman McInnes 10536851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESVecViewMonitor() 106e7e93795SLois Curfman McInnes @*/ 107329f5518SBarry Smith int SNESDefaultMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 108e7e93795SLois Curfman McInnes { 109d132466eSBarry Smith int ierr; 110b0a32e0cSBarry Smith PetscViewer viewer = (PetscViewer) dummy; 111d132466eSBarry Smith 1123a40ed3dSBarry Smith PetscFunctionBegin; 113b0a32e0cSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(snes->comm); 1147c922b88SBarry Smith 11576be9ce4SBarry Smith if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 116a0e26f09SSatish Balay ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr); 11776be9ce4SBarry Smith } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 118a0e26f09SSatish Balay ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function value %14.12e, Gradient norm %14.12e \n",its,snes->fc,fgnorm);CHKERRQ(ierr); 11929bbc08cSBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown method class"); 1203a40ed3dSBarry Smith PetscFunctionReturn(0); 121e7e93795SLois Curfman McInnes } 1223f1db9ecSBarry Smith 123*3a7fca6bSBarry Smith #undef __FUNCT__ 124*3a7fca6bSBarry Smith #define __FUNCT__ "SNESRatioMonitor" 125*3a7fca6bSBarry Smith /*@C 126*3a7fca6bSBarry Smith SNESRatioMonitor - Monitoring progress of the SNES solvers, prints ratio 127*3a7fca6bSBarry Smith of residual norm at each iteration to previous 128*3a7fca6bSBarry Smith 129*3a7fca6bSBarry Smith Collective on SNES 130*3a7fca6bSBarry Smith 131*3a7fca6bSBarry Smith Input Parameters: 132*3a7fca6bSBarry Smith + snes - the SNES context 133*3a7fca6bSBarry Smith . its - iteration number 134*3a7fca6bSBarry Smith . fgnorm - 2-norm of residual (or gradient) 135*3a7fca6bSBarry Smith - dummy - unused context 136*3a7fca6bSBarry Smith 137*3a7fca6bSBarry Smith Level: intermediate 138*3a7fca6bSBarry Smith 139*3a7fca6bSBarry Smith .keywords: SNES, nonlinear, monitor, norm 140*3a7fca6bSBarry Smith 141*3a7fca6bSBarry Smith .seealso: SNESSetMonitor(), SNESVecViewMonitor() 142*3a7fca6bSBarry Smith @*/ 143*3a7fca6bSBarry Smith int SNESRatioMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 144*3a7fca6bSBarry Smith { 145*3a7fca6bSBarry Smith int ierr,len; 146*3a7fca6bSBarry Smith double *history; 147*3a7fca6bSBarry Smith PetscViewer viewer; 148*3a7fca6bSBarry Smith 149*3a7fca6bSBarry Smith PetscFunctionBegin; 150*3a7fca6bSBarry Smith viewer = PETSC_VIEWER_STDOUT_(snes->comm); 151*3a7fca6bSBarry Smith 152*3a7fca6bSBarry Smith ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr); 153*3a7fca6bSBarry Smith if (its == 0 || !history || its > len) { 154*3a7fca6bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr); 155*3a7fca6bSBarry Smith } else { 156*3a7fca6bSBarry Smith double ratio = fgnorm/history[its-1]; 157*3a7fca6bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e %g \n",its,fgnorm,ratio);CHKERRQ(ierr); 158*3a7fca6bSBarry Smith } 159*3a7fca6bSBarry Smith PetscFunctionReturn(0); 160*3a7fca6bSBarry Smith } 161*3a7fca6bSBarry Smith 162*3a7fca6bSBarry Smith /* 163*3a7fca6bSBarry Smith If the we set the history monitor space then we must destroy it 164*3a7fca6bSBarry Smith */ 165*3a7fca6bSBarry Smith #undef __FUNCT__ 166*3a7fca6bSBarry Smith #define __FUNCT__ "SNESRatioMonitorDestroy" 167*3a7fca6bSBarry Smith int SNESRatioMonitorDestroy(void *history) 168*3a7fca6bSBarry Smith { 169*3a7fca6bSBarry Smith int ierr; 170*3a7fca6bSBarry Smith 171*3a7fca6bSBarry Smith PetscFunctionBegin; 172*3a7fca6bSBarry Smith ierr = PetscFree(history);CHKERRQ(ierr); 173*3a7fca6bSBarry Smith PetscFunctionReturn(0); 174*3a7fca6bSBarry Smith } 175*3a7fca6bSBarry Smith 176*3a7fca6bSBarry Smith #undef __FUNCT__ 177*3a7fca6bSBarry Smith #define __FUNCT__ "SNESSetRatioMonitor" 178*3a7fca6bSBarry Smith /*@C 179*3a7fca6bSBarry Smith SNESSetRatioMonitor - Sets SNES to use a monitor that prints the 180*3a7fca6bSBarry Smith ratio of the function norm at each iteration 181*3a7fca6bSBarry Smith 182*3a7fca6bSBarry Smith Collective on SNES 183*3a7fca6bSBarry Smith 184*3a7fca6bSBarry Smith Input Parameters: 185*3a7fca6bSBarry Smith . snes - the SNES context 186*3a7fca6bSBarry Smith 187*3a7fca6bSBarry Smith Level: intermediate 188*3a7fca6bSBarry Smith 189*3a7fca6bSBarry Smith .keywords: SNES, nonlinear, monitor, norm 190*3a7fca6bSBarry Smith 191*3a7fca6bSBarry Smith .seealso: SNESSetMonitor(), SNESVecViewMonitor(), SNESDefaultMonitor() 192*3a7fca6bSBarry Smith @*/ 193*3a7fca6bSBarry Smith int SNESSetRatioMonitor(SNES snes) 194*3a7fca6bSBarry Smith { 195*3a7fca6bSBarry Smith int ierr; 196*3a7fca6bSBarry Smith double *history; 197*3a7fca6bSBarry Smith 198*3a7fca6bSBarry Smith PetscFunctionBegin; 199*3a7fca6bSBarry Smith 200*3a7fca6bSBarry Smith ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 201*3a7fca6bSBarry Smith if (!history) { 202*3a7fca6bSBarry Smith ierr = PetscMalloc(100*sizeof(double),&history);CHKERRQ(ierr); 203*3a7fca6bSBarry Smith ierr = SNESSetConvergenceHistory(snes,history,0,100,PETSC_TRUE);CHKERRQ(ierr); 204*3a7fca6bSBarry Smith ierr = SNESSetMonitor(snes,SNESRatioMonitor,history,SNESRatioMonitorDestroy);CHKERRQ(ierr); 205*3a7fca6bSBarry Smith } else { 206*3a7fca6bSBarry Smith ierr = SNESSetMonitor(snes,SNESRatioMonitor,0,0);CHKERRQ(ierr); 207*3a7fca6bSBarry Smith } 208*3a7fca6bSBarry Smith PetscFunctionReturn(0); 209*3a7fca6bSBarry Smith } 210*3a7fca6bSBarry Smith 211e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */ 2124a2ae208SSatish Balay #undef __FUNCT__ 2134a2ae208SSatish Balay #define __FUNCT__ "SNESDefaultSMonitor" 214be1f7002SBarry Smith /* 215be1f7002SBarry Smith Default (short) SNES Monitor, same as SNESDefaultMonitor() except 216be1f7002SBarry Smith it prints fewer digits of the residual as the residual gets smaller. 217be1f7002SBarry Smith This is because the later digits are meaningless and are often 218be1f7002SBarry Smith different on different machines; by using this routine different 219be1f7002SBarry Smith machines will usually generate the same output. 220be1f7002SBarry Smith */ 221329f5518SBarry Smith int SNESDefaultSMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy) 222e7e93795SLois Curfman McInnes { 223d132466eSBarry Smith int ierr; 224d132466eSBarry Smith 2253a40ed3dSBarry Smith PetscFunctionBegin; 226e7e93795SLois Curfman McInnes if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 2278f240d10SBarry Smith if (fgnorm > 1.e-9) { 228a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr); 2293a40ed3dSBarry Smith } else if (fgnorm > 1.e-11){ 230a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr); 2313a40ed3dSBarry Smith } else { 232a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr); 233e7e93795SLois Curfman McInnes } 234e7e93795SLois Curfman McInnes } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 2358f240d10SBarry Smith if (fgnorm > 1.e-9) { 236a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr); 2373a40ed3dSBarry Smith } else if (fgnorm > 1.e-11) { 238a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);CHKERRQ(ierr); 2393a40ed3dSBarry Smith } else { 240a0e26f09SSatish Balay ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);CHKERRQ(ierr); 241e7e93795SLois Curfman McInnes } 24229bbc08cSBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown method class"); 2433a40ed3dSBarry Smith PetscFunctionReturn(0); 244e7e93795SLois Curfman McInnes } 245e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */ 2464a2ae208SSatish Balay #undef __FUNCT__ 2474a2ae208SSatish Balay #define __FUNCT__ "SNESConverged_EQ_LS" 2484b828684SBarry Smith /*@C 249f525115eSLois Curfman McInnes SNESConverged_EQ_LS - Monitors the convergence of the solvers for 250f525115eSLois Curfman McInnes systems of nonlinear equations (default). 251e7e93795SLois Curfman McInnes 252c7afd0dbSLois Curfman McInnes Collective on SNES 253c7afd0dbSLois Curfman McInnes 254e7e93795SLois Curfman McInnes Input Parameters: 255c7afd0dbSLois Curfman McInnes + snes - the SNES context 256e7e93795SLois Curfman McInnes . xnorm - 2-norm of current iterate 257e7e93795SLois Curfman McInnes . pnorm - 2-norm of current step 258e7e93795SLois Curfman McInnes . fnorm - 2-norm of function 259c7afd0dbSLois Curfman McInnes - dummy - unused context 260e7e93795SLois Curfman McInnes 261184914b5SBarry Smith Output Parameter: 262184914b5SBarry Smith . reason - one of 263184914b5SBarry Smith $ SNES_CONVERGED_FNORM_ABS - (fnorm < atol), 264184914b5SBarry Smith $ SNES_CONVERGED_PNORM_RELATIVE - (pnorm < xtol*xnorm), 265184914b5SBarry Smith $ SNES_CONVERGED_FNORM_RELATIVE - (fnorm < rtol*fnorm0), 266184914b5SBarry Smith $ SNES_DIVERGED_FUNCTION_COUNT - (nfct > maxf), 267184914b5SBarry Smith $ SNES_DIVERGED_FNORM_NAN - (fnorm == NaN), 268184914b5SBarry Smith $ SNES_CONVERGED_ITERATING - (otherwise), 269e7e93795SLois Curfman McInnes 270e7e93795SLois Curfman McInnes where 271c7afd0dbSLois Curfman McInnes + maxf - maximum number of function evaluations, 272c7afd0dbSLois Curfman McInnes set with SNESSetTolerances() 273c7afd0dbSLois Curfman McInnes . nfct - number of function evaluations, 274c7afd0dbSLois Curfman McInnes . atol - absolute function norm tolerance, 275c7afd0dbSLois Curfman McInnes set with SNESSetTolerances() 276c7afd0dbSLois Curfman McInnes - rtol - relative function norm tolerance, set with SNESSetTolerances() 277fee21e36SBarry Smith 27836851e7fSLois Curfman McInnes Level: intermediate 27936851e7fSLois Curfman McInnes 280e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence 281e7e93795SLois Curfman McInnes 282e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged() 283e7e93795SLois Curfman McInnes @*/ 284329f5518SBarry Smith int SNESConverged_EQ_LS(SNES snes,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 285e7e93795SLois Curfman McInnes { 2863a40ed3dSBarry Smith PetscFunctionBegin; 287d252947aSBarry Smith if (snes->method_class != SNES_NONLINEAR_EQUATIONS) { 28829bbc08cSBarry Smith SETERRQ(PETSC_ERR_ARG_WRONG,"For SNES_NONLINEAR_EQUATIONS only"); 289d252947aSBarry Smith } 290184914b5SBarry Smith 291d252947aSBarry Smith if (fnorm != fnorm) { 292b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n"); 293184914b5SBarry Smith *reason = SNES_DIVERGED_FNORM_NAN; 294184914b5SBarry Smith } else if (fnorm <= snes->ttol) { 295b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol); 296184914b5SBarry Smith *reason = SNES_CONVERGED_FNORM_RELATIVE; 297184914b5SBarry Smith } else if (fnorm < snes->atol) { 298b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol); 299184914b5SBarry Smith *reason = SNES_CONVERGED_FNORM_ABS; 300184914b5SBarry Smith } else if (pnorm < snes->xtol*(xnorm)) { 301b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm); 302184914b5SBarry Smith *reason = SNES_CONVERGED_PNORM_RELATIVE; 303184914b5SBarry Smith } else if (snes->nfuncs > snes->max_funcs) { 304b0a32e0cSBarry Smith PetscLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs,snes->max_funcs); 305184914b5SBarry Smith *reason = SNES_DIVERGED_FUNCTION_COUNT ; 306184914b5SBarry Smith } else { 307184914b5SBarry Smith *reason = SNES_CONVERGED_ITERATING; 308e7e93795SLois Curfman McInnes } 3093a40ed3dSBarry Smith PetscFunctionReturn(0); 310e7e93795SLois Curfman McInnes } 311e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */ 3124a2ae208SSatish Balay #undef __FUNCT__ 3134a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_SetConvergenceTestEW" 314e7e93795SLois Curfman McInnes /*@ 315f525115eSLois Curfman McInnes SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test 316e7e93795SLois Curfman McInnes for the linear solvers within an inexact Newton method. 317e7e93795SLois Curfman McInnes 318c7afd0dbSLois Curfman McInnes Collective on SNES 319c7afd0dbSLois Curfman McInnes 320e7e93795SLois Curfman McInnes Input Parameter: 321e7e93795SLois Curfman McInnes . snes - SNES context 322e7e93795SLois Curfman McInnes 323e7e93795SLois Curfman McInnes Notes: 324e7e93795SLois Curfman McInnes Currently, the default is to use a constant relative tolerance for 325e7e93795SLois Curfman McInnes the inner linear solvers. Alternatively, one can use the 326e7e93795SLois Curfman McInnes Eisenstat-Walker method, where the relative convergence tolerance 327e7e93795SLois Curfman McInnes is reset at each Newton iteration according progress of the nonlinear 328e7e93795SLois Curfman McInnes solver. 329e7e93795SLois Curfman McInnes 33036851e7fSLois Curfman McInnes Level: advanced 33136851e7fSLois Curfman McInnes 332e7e93795SLois Curfman McInnes Reference: 333e7e93795SLois Curfman McInnes S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 334e30ad881SLois Curfman McInnes inexact Newton method", SISC 17 (1), pp.16-32, 1996. 335e7e93795SLois Curfman McInnes 336e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 337e7e93795SLois Curfman McInnes @*/ 338e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes) 339e7e93795SLois Curfman McInnes { 3403a40ed3dSBarry Smith PetscFunctionBegin; 341186905e3SBarry Smith snes->ksp_ewconv = PETSC_TRUE; 3423a40ed3dSBarry Smith PetscFunctionReturn(0); 343e7e93795SLois Curfman McInnes } 344e7e93795SLois Curfman McInnes 3454a2ae208SSatish Balay #undef __FUNCT__ 3464a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_SetParametersEW" 347e7e93795SLois Curfman McInnes /*@ 348e7e93795SLois Curfman McInnes SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker 349e7e93795SLois Curfman McInnes convergence criteria for the linear solvers within an inexact 350e7e93795SLois Curfman McInnes Newton method. 351e7e93795SLois Curfman McInnes 352c7afd0dbSLois Curfman McInnes Collective on SNES 353c7afd0dbSLois Curfman McInnes 354e7e93795SLois Curfman McInnes Input Parameters: 355c7afd0dbSLois Curfman McInnes + snes - SNES context 356e7e93795SLois Curfman McInnes . version - version 1 or 2 (default is 2) 357c7afd0dbSLois Curfman McInnes . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 358c7afd0dbSLois Curfman McInnes . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 359c7afd0dbSLois Curfman McInnes . alpha - power for version 2 rtol computation (1 < alpha <= 2) 360e7e93795SLois Curfman McInnes . alpha2 - power for safeguard 361e7e93795SLois Curfman McInnes . gamma2 - multiplicative factor for version 2 rtol computation 362c7afd0dbSLois Curfman McInnes (0 <= gamma2 <= 1) 363c7afd0dbSLois Curfman McInnes - threshold - threshold for imposing safeguard (0 < threshold < 1) 364fee21e36SBarry Smith 365e7e93795SLois Curfman McInnes Note: 366e7e93795SLois Curfman McInnes Use PETSC_DEFAULT to retain the default for any of the parameters. 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 372e7e93795SLois Curfman McInnes inexact Newton method", Utah State University Math. Stat. Dept. Res. 373e7e93795SLois Curfman McInnes Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 374e7e93795SLois Curfman McInnes 375e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 376e7e93795SLois Curfman McInnes 377e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW() 378e7e93795SLois Curfman McInnes @*/ 379329f5518SBarry Smith int SNES_KSP_SetParametersEW(SNES snes,int version,PetscReal rtol_0, 380329f5518SBarry Smith PetscReal rtol_max,PetscReal gamma2,PetscReal alpha, 381329f5518SBarry Smith PetscReal alpha2,PetscReal threshold) 382e7e93795SLois Curfman McInnes { 383e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 3843a40ed3dSBarry Smith 3853a40ed3dSBarry Smith PetscFunctionBegin; 38629bbc08cSBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing"); 387e7e93795SLois Curfman McInnes if (version != PETSC_DEFAULT) kctx->version = version; 388e7e93795SLois Curfman McInnes if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 389e7e93795SLois Curfman McInnes if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 390e7e93795SLois Curfman McInnes if (gamma2 != PETSC_DEFAULT) kctx->gamma = gamma2; 391e7e93795SLois Curfman McInnes if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 392e7e93795SLois Curfman McInnes if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 393e7e93795SLois Curfman McInnes if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 394a8c6a408SBarry Smith if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) { 39529bbc08cSBarry Smith SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0); 396a8c6a408SBarry Smith } 397a8c6a408SBarry Smith if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) { 39829bbc08cSBarry Smith SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max < 1.0\n",kctx->rtol_max); 399a8c6a408SBarry Smith } 400a8c6a408SBarry Smith if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) { 40129bbc08cSBarry Smith SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold < 1.0\n",kctx->threshold); 402a8c6a408SBarry Smith } 403a8c6a408SBarry Smith if (kctx->gamma < 0.0 || kctx->gamma > 1.0) { 40429bbc08cSBarry Smith SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= alpha <= 1.0\n",kctx->gamma); 405a8c6a408SBarry Smith } 406a8c6a408SBarry Smith if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) { 40729bbc08cSBarry Smith SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha <= 2.0\n",kctx->alpha); 408a8c6a408SBarry Smith } 409a8c6a408SBarry Smith if (kctx->version != 1 && kctx->version !=2) { 41029bbc08cSBarry Smith SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 and 2 are supported: %d",kctx->version); 411a8c6a408SBarry Smith } 4123a40ed3dSBarry Smith PetscFunctionReturn(0); 413e7e93795SLois Curfman McInnes } 414e7e93795SLois Curfman McInnes 4154a2ae208SSatish Balay #undef __FUNCT__ 4164a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_EW_ComputeRelativeTolerance_Private" 417e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp) 418e7e93795SLois Curfman McInnes { 419e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 420329f5518SBarry Smith PetscReal rtol = 0.0,stol; 421e7e93795SLois Curfman McInnes int ierr; 4223a40ed3dSBarry Smith 4233a40ed3dSBarry Smith PetscFunctionBegin; 42429bbc08cSBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists"); 425c38d4ed2SBarry Smith if (!snes->iter) { /* first time in, so use the original user rtol */ 426e7e93795SLois Curfman McInnes rtol = kctx->rtol_0; 427e7e93795SLois Curfman McInnes } else { 428e7e93795SLois Curfman McInnes if (kctx->version == 1) { 429e7e93795SLois Curfman McInnes rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 430e7e93795SLois Curfman McInnes if (rtol < 0.0) rtol = -rtol; 431e7e93795SLois Curfman McInnes stol = pow(kctx->rtol_last,kctx->alpha2); 4320452661fSBarry Smith if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 433e7e93795SLois Curfman McInnes } else if (kctx->version == 2) { 434e7e93795SLois Curfman McInnes rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha); 435e7e93795SLois Curfman McInnes stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha); 4360452661fSBarry Smith if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 43729bbc08cSBarry Smith } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 or 2 are supported: %d",kctx->version); 438e7e93795SLois Curfman McInnes } 4390452661fSBarry Smith rtol = PetscMin(rtol,kctx->rtol_max); 440e7e93795SLois Curfman McInnes kctx->rtol_last = rtol; 441b0a32e0cSBarry Smith PetscLogInfo(snes,"SNES_KSP_EW_ComputeRelativeTolerance_Private: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol); 4423131a8b6SLois Curfman McInnes ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 443e7e93795SLois Curfman McInnes kctx->norm_last = snes->norm; 4443a40ed3dSBarry Smith PetscFunctionReturn(0); 445e7e93795SLois Curfman McInnes } 446e7e93795SLois Curfman McInnes 4474a2ae208SSatish Balay #undef __FUNCT__ 4484a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_EW_Converged_Private" 449329f5518SBarry Smith int SNES_KSP_EW_Converged_Private(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx) 450e7e93795SLois Curfman McInnes { 451e7e93795SLois Curfman McInnes SNES snes = (SNES)ctx; 452e7e93795SLois Curfman McInnes SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx; 4533acb151aSSatish Balay int ierr; 454e7e93795SLois Curfman McInnes 4553a40ed3dSBarry Smith PetscFunctionBegin; 45629bbc08cSBarry Smith if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context set"); 457184914b5SBarry Smith if (n == 0) {ierr = SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);CHKERRQ(ierr);} 458211a6b7eSSatish Balay ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx);CHKERRQ(ierr); 459e7e93795SLois Curfman McInnes kctx->lresid_last = rnorm; 460211a6b7eSSatish Balay if (*reason) { 461b0a32e0cSBarry Smith PetscLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm); 4623a40ed3dSBarry Smith } 463211a6b7eSSatish Balay PetscFunctionReturn(0); 464e7e93795SLois Curfman McInnes } 465e7e93795SLois Curfman McInnes 466e7e93795SLois Curfman McInnes 467