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.
Project hosting provided by
,
O2scl Sourceforge Project Page