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_GSL_ROOT_STEF_H 00024 #define O2SCL_GSL_ROOT_STEF_H 00025 00026 #include <gsl/gsl_math.h> 00027 #include <gsl/gsl_roots.h> 00028 #include <o2scl/root.h> 00029 00030 #ifndef DOXYGENP 00031 namespace o2scl { 00032 #endif 00033 00034 /** 00035 \brief Steffenson equation solver (GSL) 00036 00037 This class finds a root of a function a derivative. If the 00038 derivative is not analytically specified, it is most likely 00039 preferable to use of the alternatives, gsl_root_brent, 00040 cern_root, or cern_mroot_root. The function solve_de() performs 00041 the solution automatically, and a lower-level GSL-like interface 00042 with set() and iterate() is also provided. 00043 00044 By default, this solver compares the present value of the root 00045 (\f$ root \f$) to the previous value (\f$ x \f$), and returns 00046 success if \f$ | root - x | < tol \f$, where \f$ tol = tolx + 00047 tolf2 root \f$. 00048 00049 If \ref test_residual is set to true, then the solver 00050 additionally requires that the absolute value of the function 00051 is less than \ref root::tolf. 00052 00053 The original variable \c x_2 has been removed as it was unused 00054 in the original GSL code. 00055 00056 */ 00057 template<class param_t, class func_t, class dfunc_t> class gsl_root_stef : 00058 public o2scl::root<param_t,func_t,dfunc_t> { 00059 00060 protected: 00061 00062 /// Desc 00063 double f; 00064 00065 /// Desc 00066 double df; 00067 00068 /// Desc 00069 double x_1; 00070 00071 /// Desc 00072 double x; 00073 00074 /// Desc 00075 int count; 00076 00077 /// The function to solve 00078 func_t *fp; 00079 00080 /// The derivative 00081 dfunc_t *dfp; 00082 00083 /// The function parameters 00084 param_t *params; 00085 00086 public: 00087 00088 gsl_root_stef() { 00089 this->over_de=true; 00090 test_residual=false; 00091 tolf2=1.0e-12; 00092 } 00093 00094 /// Return the type, \c "gsl_root_stef". 00095 virtual const char *type() { return "gsl_root_stef"; } 00096 00097 /// The present solution estimate 00098 double root; 00099 00100 /** \brief The relative tolerance for subsequent solutions 00101 (default \f$ 10^{-12} \f$) 00102 */ 00103 double tolf2; 00104 00105 /** 00106 \brief Perform an iteration 00107 00108 After a successful iteration, \ref root contains the 00109 most recent value of the root. 00110 */ 00111 int iterate() { 00112 00113 double x_new, f_new, df_new; 00114 00115 double x_1t = x_1; 00116 double xt = x; 00117 00118 if (df == 0.0) { 00119 set_err_ret("Derivative is zero in gsl_root_stef::iterate().", 00120 o2scl::gsl_ezerodiv); 00121 } 00122 00123 x_new = xt - (f / df); 00124 00125 // It is important that the derivative be evaluated first here, 00126 // because we want the last function evaluation to be an 00127 // evaluation for the returned root 00128 (*dfp)(x_new,df_new,*params); 00129 (*fp)(x_new,f_new,*params); 00130 00131 x_1 = xt; 00132 x = x_new; 00133 00134 f = f_new; 00135 df = df_new; 00136 00137 if (!finite (f_new)) { 00138 set_err_ret 00139 ("Function not continuous in gsl_root_stef::iterate().", 00140 o2scl::gsl_ebadfunc); 00141 } 00142 00143 if (count < 3) { 00144 root = x_new; 00145 count++; 00146 } else { 00147 double u = (xt - x_1t); 00148 double v = (x_new - 2 * xt + x_1t); 00149 00150 if (v == 0) { 00151 root = x_new; /* avoid division by zero */ 00152 } else { 00153 root = x_1t - u * u / v; /* accelerated value */ 00154 } 00155 } 00156 00157 if (!finite(df_new)) { 00158 set_err_ret 00159 ("Function not differentiable in gsl_root_stef::iterate().", 00160 o2scl::gsl_ebadfunc); 00161 } 00162 00163 return o2scl::gsl_success; 00164 } 00165 00166 /** \brief Solve \c func using \c x as an initial 00167 guess using derivatives \c df. 00168 */ 00169 virtual int solve_de(double &xx, param_t &pa, func_t &fun, dfunc_t &dfun) { 00170 00171 int status1, status2=gsl_continue, iter=0; 00172 00173 status1=set(fun,dfun,xx,pa); 00174 00175 while (status1==gsl_success && status2==gsl_continue && 00176 iter<this->ntrial) { 00177 iter++; 00178 00179 status1=iterate(); 00180 00181 // Compare present value to previous value 00182 status2=gsl_root_test_delta(root,xx,this->tolx,tolf2); 00183 00184 if (test_residual && status2==gsl_success) { 00185 double y; 00186 fun(root,y,pa); 00187 if (fabs(y)>=this->tolf) status2=gsl_continue; 00188 } 00189 00190 if (this->verbose>0) { 00191 double fval; 00192 fun(root,fval,pa); 00193 print_iter(root,fval,iter,fabs(root-xx),this->tolx*root, 00194 "gsl_root_stef"); 00195 } 00196 xx=root; 00197 } 00198 00199 this->last_ntrial=iter; 00200 00201 if (status1!=gsl_success || status2!=gsl_success) { 00202 int ret=o2scl::err_hnd->get_errno(); 00203 return ret; 00204 } 00205 if (iter>=this->ntrial) { 00206 set_err_ret("solve_de() exceeded maximum number of iterations.", 00207 gsl_emaxiter); 00208 } 00209 00210 return o2scl::gsl_success; 00211 } 00212 00213 /// True if we should test the residual also (default false) 00214 bool test_residual; 00215 00216 /** 00217 \brief Set the information for the solver 00218 00219 Set the function, the derivative, the initial guess and 00220 the parameters. 00221 */ 00222 int set(func_t &fun, dfunc_t &dfun, double guess, param_t &pa) { 00223 00224 fp=&fun; 00225 dfp=&dfun; 00226 params=&pa; 00227 root=guess; 00228 00229 dfun(root,df,pa); 00230 fun(root,f,pa); 00231 00232 x=root; 00233 x_1=0.0; 00234 count=1; 00235 00236 return o2scl::gsl_success; 00237 00238 } 00239 00240 }; 00241 00242 #ifndef DOXYGENP 00243 template<> int io_tlate<gsl_root_stef<void *,funct<void *>, 00244 funct<void *> > >::input(cinput *co, in_file_format *ins, 00245 gsl_root_stef<void *, funct<void *>, 00246 funct<void *> > *ro); 00247 template<> int io_tlate<gsl_root_stef<void *,funct<void *>, 00248 funct<void *> > >::output(coutput *co, out_file_format *outs, 00249 gsl_root_stef<void *, funct<void *>, 00250 funct<void *> > *ro); 00251 template<> const char *io_tlate<gsl_root_stef<void *, 00252 funct<void *>, funct<void *> > >::type(); 00253 #endif 00254 00255 typedef io_tlate<gsl_root_stef<void *,funct<void *>, funct<void *> > > 00256 gsl_root_stef_io_type; 00257 00258 #ifndef DOXYGENP 00259 } 00260 #endif 00261 00262 #endif 00263
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