root.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_ROOT_H
00024 #define O2SCL_ROOT_H
00025 
00026 #include <iostream>
00027 #include <cmath>
00028 #include <o2scl/err_hnd.h>
00029 #include <o2scl/collection.h>
00030 #include <o2scl/funct.h>
00031 
00032 #ifndef DOXYGENP
00033 namespace o2scl {
00034 #endif
00035 
00036   /** 
00037       \brief 1-dimensional solver base class
00038 
00039       \note This class does not actually do any solving, it is
00040       present to provide member data and various functions common
00041       to all the 1 dimensional solvers. 
00042 
00043   */
00044   template<class param_t, class func_t, class dfunc_t=func_t> 
00045     class root {
00046 
00047     public:
00048       
00049     root() {
00050       ntrial=100;
00051       tolf=1.0e-8;
00052       verbose=0;
00053       tolx=1.0e-12;
00054       deriv_eps=0.0;
00055       last_ntrial=0;
00056     }
00057 
00058     virtual ~root() {}
00059 
00060     /** \brief The maximum value of the functions for success 
00061         (default \f$ 10^{-8} \f$ )
00062     */
00063     double tolf;
00064       
00065     /** \brief The minimum allowable stepsize 
00066         (default \f$ 10^{-12} \f$ )
00067     */
00068     double tolx;
00069     
00070     /// Output control (default 0)
00071     int verbose;
00072     
00073     /// Maximum number of iterations (default 100)
00074     int ntrial;
00075 
00076     /// Should be true if root_bkt() is overloaded
00077     bool over_bkt;
00078       
00079     /// Should be true if root_de() is overloaded
00080     bool over_de;
00081     
00082     /** 
00083         \brief The stepsize for finite-differencing (default 0)
00084           
00085         If this is zero, then \f$ 10^{-4} \f$  times the argument will
00086         be used.
00087 
00088         \note It seems this variable is left over from an earlier
00089         version of the code. I'm keeping it here for now just in
00090         case.
00091     */
00092     double deriv_eps;
00093  
00094     /// The number of iterations for in the most recent minimization
00095     int last_ntrial;
00096 
00097     /// Return the type, \c "root".
00098     virtual const char *type() { return "root"; }
00099 
00100     /** 
00101         \brief Print out iteration information.
00102          
00103         Depending on the value of the variable verbose, this prints
00104         out the iteration information. If verbose=0, then no
00105         information is printed, while if verbose>1, then after each
00106         iteration, the present values of \c x and \c y are
00107         output to std::cout along with the iteration number. If
00108         verbose>=2 then each iteration waits for a character before
00109         continuing
00110  
00111     */
00112     virtual int print_iter(double x, double y, int iter, double value=0.0,
00113                            double limit=0.0, std::string comment="") {
00114       if (verbose<=0) return gsl_success;
00115         
00116       char ch;
00117         
00118       std::cout << comment << " Iteration: " << iter << std::endl;
00119       if (x<0) std::cout << x << " ";
00120       else std::cout << " " << x << " ";
00121       if (y<0) std::cout << y << " ";
00122       else std::cout << " " << y << " ";
00123       if (value<0) std::cout << value << " ";
00124       else std::cout << " " << value << " ";
00125       if (limit<0) std::cout << limit << std::endl;
00126       else std::cout << " " << limit << std::endl;
00127       if (verbose>1) {
00128         std::cout << "Press a key and type enter to continue. ";
00129         std::cin >> ch;
00130       }
00131  
00132       return gsl_success;
00133     }
00134     
00135     /** 
00136         \brief Solve \c func using \c x as an initial guess
00137     */
00138     virtual int solve(double &x, param_t &pa, func_t &func) {
00139 
00140       if (over_bkt) {
00141         double x2=0.0, dx, fx, fx2;
00142         int i=0;
00143         bool done=false;
00144         // Use function to try to bracket a root
00145         while(done==false && i<10) {
00146           
00147           func(x,fx,pa);
00148           func(x*(1.0+deriv_eps),fx2,pa);
00149             
00150           dx=(fx2-fx)/(deriv_eps*x);
00151           x2=x-2.0*fx/dx;
00152           
00153           func(x2,fx2,pa);
00154           
00155           if (fx*fx2<0.0) {
00156             done=true;
00157           } else {
00158             x=(x2+x)/2.0;
00159           }
00160 
00161           i++;
00162         }
00163         if (done==false) {
00164           set_err_ret("Failed to bracket function in root::solve().",
00165                       o2scl::gsl_emaxiter);
00166         }
00167         return solve_bkt(x,x2,pa,func);
00168       }
00169 
00170       return 0;
00171     }
00172 
00173     /** \brief Solve \c func in region \f$ x_1<x<x_2 \f$  
00174         returning \f$ x_1 \f$ .
00175     */
00176     virtual int solve_bkt(double &x1, double x2, param_t &pa, 
00177                           func_t &func) 
00178     {
00179       return solve(x1,pa,func);
00180     }
00181 
00182     /** \brief Solve \c func using \c x as an initial
00183         guess using derivatives \c df.
00184     */
00185     virtual int solve_de(double &x, param_t &pa, func_t &func, dfunc_t &df) {
00186 
00187       if (over_bkt) {
00188         double x2=0.0, dx, fx, fx2;
00189         int i=0;
00190         bool done=false;
00191         
00192         // Use derivative information to try to bracket a root
00193         while(done==false && i<10) {
00194           
00195           func(x,fx,pa);
00196           df(x,dx,pa);
00197           
00198           x2=x-2.0*fx/dx;
00199           
00200           func(x2,fx2,pa);
00201             
00202           if (fx*fx2<0.0) {
00203             done=true;
00204           } else {
00205             x=(x2+x)/2.0;
00206           }
00207           i++;
00208         }
00209         
00210         if (done==false) {
00211           set_err_ret("Failed to bracket function in root::solve_de().",
00212                       o2scl::gsl_efailed);
00213         }
00214         
00215         return solve_bkt(x,x2,pa,func);
00216       } 
00217         
00218       return solve(x,pa,func);
00219     }
00220       
00221   };
00222 
00223 #ifndef DOXYGENP
00224   template<> int io_tlate<root<void *,funct<void *> > >::input
00225     (cinput *co, in_file_format *ins, root<void *, funct<void *> > *ro);
00226   template<> int io_tlate<root<void *,funct<void *> > >::output
00227     (coutput *co, out_file_format *outs, root<void *, funct<void *> > *ro);
00228   template<> const char *io_tlate<root<void *,funct<void *> > >::type();
00229 #endif
00230   
00231   typedef io_tlate<root<void *,funct<void *> > > root_io_type;
00232  
00233 #ifndef DOXYGENP
00234 }
00235 #endif
00236 
00237 #endif
00238 

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