Object-oriented Scientific Computing Library: Version 0.910
root.h
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, 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/funct.h>
00030 
00031 #ifndef DOXYGENP
00032 namespace o2scl {
00033 #endif
00034   
00035   /** \brief One-dimensional solver [abstract base]
00036       
00037       \future Maybe consider allowing the user to specify
00038       the stream to which 'verbose' information is sent.
00039   */
00040   template<class func_t=funct, class dfunc_t=func_t> class root {
00041     
00042   public:
00043   
00044   root() {
00045     ntrial=100;
00046     tol_rel=1.0e-8;
00047     verbose=0;
00048     tol_abs=1.0e-12;
00049     last_ntrial=0;
00050     err_nonconv=true;
00051     last_conv=0;
00052   }
00053 
00054   virtual ~root() {}
00055 
00056   /** \brief The maximum value of the functions for success 
00057       (default \f$ 10^{-8} \f$ )
00058   */
00059   double tol_rel;
00060       
00061   /** \brief The minimum allowable stepsize 
00062       (default \f$ 10^{-12} \f$ )
00063   */
00064   double tol_abs;
00065     
00066   /// Output control (default 0)
00067   int verbose;
00068     
00069   /// Maximum number of iterations (default 100)
00070   int ntrial;
00071 
00072   /// If true, call the error handler if the routine does not "converge"
00073   bool err_nonconv;
00074     
00075   /** \brief Zero if last call to solve(), solve_bkt(), or 
00076       solve_de() converged. 
00077         
00078       This is particularly useful if err_nonconv is false to test
00079       if the last call to solve(), solve_bkt(), or solve_de() 
00080       converged.
00081   */
00082   int last_conv;
00083     
00084   /// The number of iterations for in the most recent minimization
00085   int last_ntrial;
00086 
00087   /// Return the type, \c "root".
00088   virtual const char *type() { return "root"; }
00089 
00090   /** \brief Print out iteration information.
00091          
00092       Depending on the value of the variable verbose, this prints
00093       out the iteration information. If verbose=0, then no
00094       information is printed, while if verbose>1, then after each
00095       iteration, the present values of \c x and \c y are
00096       output to std::cout along with the iteration number. If
00097       verbose>=2 then each iteration waits for a character before
00098       continuing.
00099  
00100   */
00101   virtual int print_iter(double x, double y, int iter, double value=0.0,
00102                          double limit=0.0, std::string comment="") {
00103     if (verbose<=0) return gsl_success;
00104         
00105     char ch;
00106         
00107     std::cout << comment << " Iteration: " << iter << std::endl;
00108     if (x<0) std::cout << x << " ";
00109     else std::cout << " " << x << " ";
00110     if (y<0) std::cout << y << " ";
00111     else std::cout << " " << y << " ";
00112     if (value<0) std::cout << value << " ";
00113     else std::cout << " " << value << " ";
00114     if (limit<0) std::cout << limit << std::endl;
00115     else std::cout << " " << limit << std::endl;
00116     if (verbose>1) {
00117       std::cout << "Press a key and type enter to continue. ";
00118       std::cin >> ch;
00119     }
00120  
00121     return gsl_success;
00122   }
00123     
00124   /** \brief Solve \c func using \c x as an initial guess
00125   */
00126   virtual int solve(double &x, func_t &func)=0;
00127 
00128   /** \brief Solve \c func in region \f$ x_1<x<x_2 \f$  
00129       returning \f$ x_1 \f$ .
00130   */
00131   virtual int solve_bkt(double &x1, double x2, func_t &func) {
00132     return solve(x1,func);
00133   }
00134 
00135   /** \brief Solve \c func using \c x as an initial
00136       guess using derivatives \c df.
00137   */
00138   virtual int solve_de(double &x, func_t &func, dfunc_t &df) {
00139     return solve(x,func);
00140   }
00141 
00142   };
00143 
00144   /** \brief One-dimensional bracketing solver [abstract base]
00145       
00146   */
00147   template<class func_t=funct, class dfunc_t=func_t> class root_bkt :
00148   public root<func_t,dfunc_t> {
00149 
00150   public:
00151 
00152   root_bkt() {
00153     bracket_step=1.0e-4;
00154     bracket_iters=10;
00155   }
00156       
00157   virtual ~root_bkt() {}
00158 
00159   /** \brief The stepsize for automatic bracketing 
00160       (default \f$ 10^{-4} \f$)
00161 
00162       If this is exactly zero, it will be reset to
00163       \f$ 10^{-4} \f$ by solve().
00164   */
00165   double bracket_step;
00166 
00167   /// The number of iterations in attempt to bracket root (default 10)
00168   size_t bracket_iters;
00169  
00170   /// Return the type, \c "root_bkt".
00171   virtual const char *type() { return "root_bkt"; }
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, func_t &func)=0; 
00177     
00178   /** \brief Solve \c func using \c x as an initial guess
00179   */
00180   virtual int solve(double &x, func_t &func) {
00181 
00182     if (bracket_step==0.0) bracket_step=1.0e-4;
00183 
00184     double x2=0.0, dx, fx, fx2;
00185     size_t i=0;
00186     bool done=false;
00187     // Use function to try to bracket a root
00188     while(done==false && i<bracket_iters) {
00189           
00190       fx=func(x);
00191       fx2=func(x*(1.0+bracket_step));
00192             
00193       dx=(fx2-fx)/(bracket_step*x);
00194       x2=x-2.0*fx/dx;
00195           
00196       fx2=func(x2);
00197           
00198       if (fx*fx2<0.0) {
00199         done=true;
00200       } else {
00201         x=(x2+x)/2.0;
00202       }
00203 
00204       i++;
00205     }
00206     if (done==false) {
00207       O2SCL_ERR_RET("Failed to bracket function in root_bkt::solve().",
00208                     o2scl::gsl_emaxiter);
00209     }
00210     return solve_bkt(x,x2,func);
00211 
00212     return 0;
00213   }
00214 
00215   /** \brief Solve \c func using \c x as an initial
00216       guess using derivatives \c df.
00217   */
00218   virtual int solve_de(double &x, func_t &func, dfunc_t &df) {
00219 
00220     double x2=0.0, dx, fx, fx2;
00221     int i=0;
00222     bool done=false;
00223         
00224     // Use derivative information to try to bracket a root
00225     while(done==false && i<10) {
00226           
00227       fx=func(x);
00228       dx=df(x);
00229           
00230       x2=x-2.0*fx/dx;
00231           
00232       fx2=func(x2);
00233             
00234       if (fx*fx2<0.0) {
00235         done=true;
00236       } else {
00237         x=(x2+x)/2.0;
00238       }
00239       i++;
00240     }
00241         
00242     if (done==false) {
00243       O2SCL_ERR_RET("Failed to bracket function in root_bkt::solve_de().",
00244                     o2scl::gsl_efailed);
00245     }
00246     
00247     return solve_bkt(x,x2,func);
00248     
00249   }
00250   
00251   };
00252 
00253   /** \brief One-dimensional with solver with derivatives [abstract base]
00254 
00255       \future At the moment, the functions solve() and solve_bkt() 
00256       are not implemented for derivative solvers.
00257   */
00258   template<class func_t=funct, class dfunc_t=func_t> 
00259     class root_de : public root<func_t> {
00260     
00261   public:
00262   
00263   root_de() {
00264   }
00265   
00266   virtual ~root_de() {}
00267   
00268   /// Return the type, \c "root_de".
00269   virtual const char *type() { return "root_de"; }
00270 
00271   /** \brief Solve \c func in region \f$ x_1<x<x_2 \f$  
00272       returning \f$ x_1 \f$ .
00273   */
00274   virtual int solve_bkt(double &x1, double x2, func_t &func) {
00275     O2SCL_ERR_RET("Function solve_bkt() not implemented.",gsl_eunimpl);
00276   }
00277 
00278   /** \brief Solve \c func using \c x as an initial guess
00279   */
00280   virtual int solve(double &x, func_t &func) {
00281     O2SCL_ERR_RET("Function solve() not implemented.",gsl_eunimpl);
00282   }
00283 
00284   /** \brief Solve \c func using \c x as an initial
00285       guess using derivatives \c df.
00286   */
00287   virtual int solve_de(double &x, func_t &func, dfunc_t &df)=0;
00288 
00289   };
00290   
00291 #ifndef DOXYGENP
00292 }
00293 #endif
00294 
00295 #endif
00296 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.