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