00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 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 \future This does not have pure virtual functions, but I'd still 00044 like to prevent the user from directly instantiating a root 00045 object. 00046 */ 00047 template<class param_t, class func_t, class dfunc_t=func_t> 00048 class root { 00049 00050 public: 00051 00052 root() { 00053 ntrial=100; 00054 tolf=1.0e-8; 00055 verbose=0; 00056 tolx=1.0e-12; 00057 bracket_step=1.0e-4; 00058 last_ntrial=0; 00059 } 00060 00061 virtual ~root() {} 00062 00063 /** \brief The maximum value of the functions for success 00064 (default \f$ 10^{-8} \f$ ) 00065 */ 00066 double tolf; 00067 00068 /** \brief The minimum allowable stepsize 00069 (default \f$ 10^{-12} \f$ ) 00070 */ 00071 double tolx; 00072 00073 /// Output control (default 0) 00074 int verbose; 00075 00076 /// Maximum number of iterations (default 100) 00077 int ntrial; 00078 00079 /// Should be true if root_bkt() is overloaded 00080 bool over_bkt; 00081 00082 /// Should be true if root_de() is overloaded 00083 bool over_de; 00084 00085 /** 00086 \brief The stepsize for automatic bracketing 00087 (default \f$ 10^{-4} \f$) 00088 00089 If this is exactly zero, it will be reset to 00090 \f$ 10^{-4} \f$ by solve(). 00091 */ 00092 double bracket_step; 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 if (bracket_step==0.0) bracket_step=1.0e-4; 00142 00143 double x2=0.0, dx, fx, fx2; 00144 int i=0; 00145 bool done=false; 00146 // Use function to try to bracket a root 00147 while(done==false && i<10) { 00148 00149 func(x,fx,pa); 00150 func(x*(1.0+bracket_step),fx2,pa); 00151 00152 dx=(fx2-fx)/(bracket_step*x); 00153 x2=x-2.0*fx/dx; 00154 00155 func(x2,fx2,pa); 00156 00157 if (fx*fx2<0.0) { 00158 done=true; 00159 } else { 00160 x=(x2+x)/2.0; 00161 } 00162 00163 i++; 00164 } 00165 if (done==false) { 00166 set_err_ret("Failed to bracket function in root::solve().", 00167 o2scl::gsl_emaxiter); 00168 } 00169 return solve_bkt(x,x2,pa,func); 00170 } 00171 00172 return 0; 00173 } 00174 00175 /** \brief Solve \c func in region \f$ x_1<x<x_2 \f$ 00176 returning \f$ x_1 \f$ . 00177 */ 00178 virtual int solve_bkt(double &x1, double x2, param_t &pa, 00179 func_t &func) 00180 { 00181 return solve(x1,pa,func); 00182 } 00183 00184 /** \brief Solve \c func using \c x as an initial 00185 guess using derivatives \c df. 00186 */ 00187 virtual int solve_de(double &x, param_t &pa, func_t &func, dfunc_t &df) { 00188 00189 if (over_bkt) { 00190 double x2=0.0, dx, fx, fx2; 00191 int i=0; 00192 bool done=false; 00193 00194 // Use derivative information to try to bracket a root 00195 while(done==false && i<10) { 00196 00197 func(x,fx,pa); 00198 df(x,dx,pa); 00199 00200 x2=x-2.0*fx/dx; 00201 00202 func(x2,fx2,pa); 00203 00204 if (fx*fx2<0.0) { 00205 done=true; 00206 } else { 00207 x=(x2+x)/2.0; 00208 } 00209 i++; 00210 } 00211 00212 if (done==false) { 00213 set_err_ret("Failed to bracket function in root::solve_de().", 00214 o2scl::gsl_efailed); 00215 } 00216 00217 return solve_bkt(x,x2,pa,func); 00218 } 00219 00220 return solve(x,pa,func); 00221 } 00222 00223 }; 00224 00225 #ifndef DOXYGENP 00226 template<> int io_tlate<root<void *,funct<void *> > >::input 00227 (cinput *co, in_file_format *ins, root<void *, funct<void *> > *ro); 00228 template<> int io_tlate<root<void *,funct<void *> > >::output 00229 (coutput *co, out_file_format *outs, root<void *, funct<void *> > *ro); 00230 template<> const char *io_tlate<root<void *,funct<void *> > >::type(); 00231 #endif 00232 00233 typedef io_tlate<root<void *,funct<void *> > > root_io_type; 00234 00235 #ifndef DOXYGENP 00236 } 00237 #endif 00238 00239 #endif 00240
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page