gsl_root_stef.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_GSL_ROOT_STEF_H
00024 #define O2SCL_GSL_ROOT_STEF_H
00025 
00026 #include <gsl/gsl_math.h>
00027 #include <gsl/gsl_roots.h>
00028 #include <o2scl/root.h>
00029 
00030 #ifndef DOXYGENP
00031 namespace o2scl {
00032 #endif
00033 
00034   /** 
00035       \brief Steffenson equation solver (GSL)
00036 
00037       This class finds a root of a function a derivative. If the
00038       derivative is not analytically specified, it is most likely
00039       preferable to use of the alternatives, gsl_root_brent,
00040       cern_root, or cern_mroot_root. The function solve_de() performs
00041       the solution automatically, and a lower-level GSL-like interface
00042       with set() and iterate() is also provided.
00043 
00044       By default, this solver compares the present value of the root
00045       (\f$ root \f$) to the previous value (\f$ x \f$), and returns
00046       success if \f$ | root - x | < tol \f$, where \f$ tol = tolx +
00047       tolf2 root \f$.
00048 
00049       If \ref test_residual is set to true, then the solver 
00050       additionally requires that the absolute value of the function
00051       is less than \ref root::tolf.
00052 
00053       The original variable \c x_2 has been removed as it was unused
00054       in the original GSL code.
00055       
00056    */
00057   template<class param_t, class func_t, class dfunc_t> class gsl_root_stef : 
00058   public o2scl::root<param_t,func_t,dfunc_t> {
00059       
00060   protected:
00061       
00062     /// Desc
00063     double f;
00064 
00065     /// Desc
00066     double df;
00067 
00068     /// Desc
00069     double x_1;
00070 
00071     /// Desc
00072     double x;
00073 
00074     /// Desc
00075     int count;
00076 
00077     /// The function to solve
00078     func_t *fp;
00079 
00080     /// The derivative
00081     dfunc_t *dfp;
00082       
00083     /// The function parameters
00084     param_t *params;
00085       
00086   public:
00087   
00088     gsl_root_stef() {
00089       this->over_de=true;
00090       test_residual=false;
00091       tolf2=1.0e-12;
00092     }
00093     
00094     /// Return the type, \c "gsl_root_stef".
00095     virtual const char *type() { return "gsl_root_stef"; }
00096 
00097     /// The present solution estimate
00098     double root;
00099 
00100     /** \brief The relative tolerance for subsequent solutions 
00101         (default \f$ 10^{-12} \f$)
00102     */
00103     double tolf2;
00104 
00105     /**
00106        \brief Perform an iteration
00107 
00108        After a successful iteration, \ref root contains the
00109        most recent value of the root. 
00110     */
00111     int iterate() {
00112       
00113       double x_new, f_new, df_new;
00114         
00115       double x_1t = x_1;
00116       double xt = x;
00117         
00118       if (df == 0.0) {
00119         set_err_ret("Derivative is zero in gsl_root_stef::iterate().",
00120                     o2scl::gsl_ezerodiv);
00121       }
00122         
00123       x_new = xt - (f / df);
00124 
00125       // It is important that the derivative be evaluated first here,
00126       // because we want the last function evaluation to be an
00127       // evaluation for the returned root
00128       (*dfp)(x_new,df_new,*params);
00129       (*fp)(x_new,f_new,*params);
00130     
00131       x_1 = xt;
00132       x = x_new;
00133         
00134       f = f_new;
00135       df = df_new;
00136     
00137       if (!finite (f_new)) {
00138         set_err_ret
00139           ("Function not continuous in gsl_root_stef::iterate().",
00140            o2scl::gsl_ebadfunc);
00141       }
00142         
00143       if (count < 3) {
00144         root = x_new;
00145         count++;
00146       } else {
00147         double u = (xt - x_1t);
00148         double v = (x_new - 2 * xt + x_1t);
00149         
00150         if (v == 0) {
00151           root = x_new;  /* avoid division by zero */
00152         } else {
00153           root = x_1t - u * u / v;  /* accelerated value */
00154         }
00155       }
00156       
00157       if (!finite(df_new)) {
00158         set_err_ret
00159           ("Function not differentiable in gsl_root_stef::iterate().",
00160            o2scl::gsl_ebadfunc);
00161       }
00162       
00163       return o2scl::gsl_success;
00164     }
00165 
00166     /** \brief Solve \c func using \c x as an initial
00167         guess using derivatives \c df.
00168     */
00169     virtual int solve_de(double &xx, param_t &pa, func_t &fun, dfunc_t &dfun) {
00170       
00171       int status1, status2=gsl_continue, iter=0;
00172         
00173       status1=set(fun,dfun,xx,pa);
00174         
00175       while (status1==gsl_success && status2==gsl_continue && 
00176              iter<this->ntrial) {
00177         iter++;
00178 
00179         status1=iterate();
00180 
00181         // Compare present value to previous value
00182         status2=gsl_root_test_delta(root,xx,this->tolx,tolf2);
00183 
00184         if (test_residual && status2==gsl_success) {
00185           double y;
00186           fun(root,y,pa);
00187           if (fabs(y)>=this->tolf) status2=gsl_continue;
00188         }
00189 
00190         if (this->verbose>0) {
00191           double fval;
00192           fun(root,fval,pa);
00193           print_iter(root,fval,iter,fabs(root-xx),this->tolx*root,
00194                      "gsl_root_stef");
00195         }
00196         xx=root;
00197       }
00198       
00199       this->last_ntrial=iter;
00200 
00201       if (status1!=gsl_success || status2!=gsl_success) {
00202         int ret=o2scl::err_hnd->get_errno();
00203         return ret;
00204       }
00205       if (iter>=this->ntrial) {
00206         set_err_ret("solve_de() exceeded maximum number of iterations.",
00207                     gsl_emaxiter);
00208       }
00209 
00210       return o2scl::gsl_success;
00211     }
00212     
00213     /// True if we should test the residual also (default false)
00214     bool test_residual;
00215 
00216     /** 
00217         \brief Set the information for the solver
00218 
00219         Set the function, the derivative, the initial guess and
00220         the parameters.
00221     */
00222     int set(func_t &fun, dfunc_t &dfun, double guess, param_t &pa) {
00223     
00224       fp=&fun;
00225       dfp=&dfun;
00226       params=&pa;
00227       root=guess;
00228 
00229       dfun(root,df,pa);
00230       fun(root,f,pa);
00231 
00232       x=root;
00233       x_1=0.0;
00234       count=1;
00235         
00236       return o2scl::gsl_success;
00237         
00238     }
00239 
00240   };
00241   
00242 #ifndef DOXYGENP
00243   template<> int io_tlate<gsl_root_stef<void *,funct<void *>,
00244     funct<void *> > >::input(cinput *co, in_file_format *ins, 
00245                              gsl_root_stef<void *, funct<void *>,
00246                              funct<void *> > *ro);
00247   template<> int io_tlate<gsl_root_stef<void *,funct<void *>,
00248     funct<void *> > >::output(coutput *co, out_file_format *outs, 
00249                               gsl_root_stef<void *, funct<void *>,
00250                               funct<void *> > *ro);
00251   template<> const char *io_tlate<gsl_root_stef<void *,
00252     funct<void *>, funct<void *> > >::type();
00253 #endif
00254   
00255   typedef io_tlate<gsl_root_stef<void *,funct<void *>, funct<void *> > > 
00256     gsl_root_stef_io_type;
00257  
00258 #ifndef DOXYGENP
00259 }
00260 #endif
00261 
00262 #endif
00263 

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page