![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
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 /* ode-initval/evolve.c 00024 * 00025 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman 00026 * 00027 * This program is free software; you can redistribute it and/or modify 00028 * it under the terms of the GNU General Public License as published by 00029 * the Free Software Foundation; either version 3 of the License, or (at 00030 * your option) any later version. 00031 * 00032 * This program is distributed in the hope that it will be useful, but 00033 * WITHOUT ANY WARRANTY; without even the implied warranty of 00034 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00035 * General Public License for more details. 00036 * 00037 * You should have received a copy of the GNU General Public License 00038 * along with this program; if not, write to the Free Software 00039 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00040 * 02110-1301, USA. 00041 */ 00042 #ifndef O2SCL_GSL_ASTEP_OLD_H 00043 #define O2SCL_GSL_ASTEP_OLD_H 00044 00045 #include <string> 00046 00047 #include <gsl/gsl_math.h> 00048 #include <gsl/gsl_odeiv.h> 00049 00050 #include <o2scl/adapt_step.h> 00051 #include <o2scl/gsl_astep.h> 00052 00053 #ifndef DOXYGENP 00054 namespace o2scl { 00055 #endif 00056 00057 /** \brief Adaptive ODE stepper (GSL) 00058 00059 [This is the stepper from \o2 version 0.908 which is 00060 kept around for diagnostic purposes and some legacy code.] 00061 00062 This class performs an adaptive step of a system of ODEs. To 00063 modify the ODE stepper which is used, use the function 00064 \ref adapt_step::set_step(). 00065 00066 There is an example for the usage of this class in 00067 <tt>examples/ex_ode.cpp</tt> documented in the \ref ex_ode_sect 00068 section. 00069 00070 Default template arguments 00071 - \c func_t - \ref ode_funct 00072 - \c vec_t - \ref ovector_base 00073 - \c alloc_vec_t - \ref ovector 00074 - \c alloc_t - \ref ovector_alloc 00075 */ 00076 template<class func_t=ode_funct<>, 00077 class vec_t=ovector_base, class alloc_vec_t=ovector, 00078 class alloc_t=ovector_alloc> class gsl_astep_old : 00079 public adapt_step<func_t,vec_t,alloc_vec_t,alloc_t> { 00080 00081 #ifndef DOXYGEN_INTERNAL 00082 00083 protected: 00084 00085 /// Memory allocator for objects of type \c alloc_vec_t 00086 alloc_t ao; 00087 00088 /// Temporary storage for yout 00089 alloc_vec_t yout; 00090 00091 /// Internal storage for dydx 00092 alloc_vec_t dydx_int; 00093 00094 /// The size of the last step 00095 double last_step; 00096 00097 /// The number of steps 00098 unsigned long int count; 00099 00100 /// The number of failed steps 00101 unsigned long int failed_steps; 00102 00103 /// The size of the allocated vectors 00104 size_t msize; 00105 00106 /// Apply the evolution for the next adaptive step 00107 int evolve_apply(double t0, double &t, double &h, double t1, size_t nvar, 00108 vec_t &y, vec_t &dydx, vec_t &yout2, vec_t &yerr, 00109 vec_t &dydx_out2, func_t &derivs) { 00110 00111 double h0 = h; 00112 int step_status; 00113 int final_step = 0; 00114 /* remaining step size, possibly less than h */ 00115 double dt = t1 - t0; 00116 00117 if ((dt < 0.0 && h0 > 0.0) || (dt > 0.0 && h0 < 0.0)) { 00118 std::string str="Interval direction (t1-t0="+dtos(dt)+ 00119 ") does not match step direction (h="+dtos(h)+ 00120 " in gsl_astep_old::evolve_apply()."; 00121 O2SCL_ERR_RET(str.c_str(),gsl_einval); 00122 } 00123 00124 bool try_step_again=true; 00125 while(try_step_again) { 00126 00127 if ((dt >= 0.0 && h0 > dt) || (dt < 0.0 && h0 < dt)) { 00128 h0 = dt; 00129 final_step = 1; 00130 } else{ 00131 final_step = 0; 00132 } 00133 00134 step_status=this->stepp->step(t0,h0,nvar,y,dydx,yout2,yerr, 00135 dydx_out2,derivs); 00136 00137 /* Check for stepper internal failure */ 00138 if (step_status != gsl_success) { 00139 // Notify user which step-size caused the failure 00140 h=h0; 00141 return step_status; 00142 } 00143 00144 count++; 00145 last_step = h0; 00146 if (final_step) { 00147 t = t1; 00148 } else{ 00149 t = t0 + h0; 00150 } 00151 00152 /* Check error and attempt to adjust the step. */ 00153 const int hadjust_status=con.hadjust(nvar,this->stepp->get_order(), 00154 yout2,yerr,dydx_out2,h0); 00155 00156 if (hadjust_status == GSL_ODEIV_HADJ_DEC) { 00157 00158 /* Step was decreased. Undo and go back to try again. */ 00159 failed_steps++; 00160 try_step_again=true; 00161 } else { 00162 try_step_again=false; 00163 } 00164 00165 } 00166 00167 /* suggest step size for next time-step */ 00168 h = h0; 00169 00170 // This used to be return step_status, but the code never 00171 // reaches this point if step_status is anything other than zero. 00172 return gsl_success; 00173 } 00174 00175 #endif 00176 00177 public: 00178 00179 gsl_astep_old() { 00180 this->verbose=0; 00181 msize=0; 00182 } 00183 00184 virtual ~gsl_astep_old() { 00185 if (msize>0) { 00186 ao.free(yout); 00187 ao.free(dydx_int); 00188 } 00189 } 00190 00191 /// Control specification 00192 gsl_ode_control<vec_t> con; 00193 00194 /** \brief Make an adaptive integration step of the system 00195 \c derivs with derivatives 00196 00197 This attempts to take a step of size \c h from the point \c x 00198 of an \c n-dimensional system \c derivs starting with \c y and 00199 given the initial derivatives \c dydx. On exit, \c x, \c y and 00200 \c dydx contain the new values at the end of the step, \c h 00201 contains the size of the step, \c dydx contains the derivative 00202 at the end of the step, and \c yerr contains the estimated 00203 error at the end of the step. 00204 00205 If the base stepper returns a non-zero value, the step is 00206 aborted and \c y is unmodified. The error handler is never 00207 called. 00208 */ 00209 virtual int astep_derivs(double &x, double xmax, double &h, 00210 size_t n, vec_t &y, vec_t &dydx, 00211 vec_t &yerr, func_t &derivs) { 00212 count=0; 00213 failed_steps=0; 00214 last_step=0.0; 00215 00216 if (n!=msize) { 00217 ao.allocate(yout,n); 00218 ao.allocate(dydx_int,n); 00219 msize=n; 00220 } 00221 00222 int ret=evolve_apply(x,x,h,xmax,n,y,dydx,yout,yerr,dydx_int, 00223 derivs); 00224 00225 if (ret==gsl_success) { 00226 for(size_t i=0;i<n;i++) { 00227 y[i]=yout[i]; 00228 dydx[i]=dydx_int[i]; 00229 } 00230 } 00231 00232 if (this->verbose>0) { 00233 std::cout << x << " "; 00234 for(size_t j=0;j<n;j++) std::cout << y[j] << " "; 00235 std::cout << std::endl; 00236 } 00237 00238 return ret; 00239 } 00240 00241 /** \brief Make an adaptive integration step of the system 00242 \c derivs 00243 00244 This function performs an adaptive integration step with the 00245 \c n-dimensional system \c derivs and parameter \c pa. It 00246 Begins at \c x with initial stepsize \c h, ensuring that the 00247 step goes no farther than \c xmax. At the end of the step, the 00248 size of the step taken is \c h and the new value of \c x is in 00249 \c x_out. Initially, the function values and derivatives 00250 should be specified in \c y and \c dydx. The function values, 00251 derivatives, and the error at the end of the step are given in 00252 \c yout, \c yerr, and \c dydx_out. Unlike in \c ode_step 00253 objects, the objects \c y, \c yout, \c dydx, and \c dydx_out 00254 must all be distinct. 00255 00256 If the base stepper returns a non-zero value, the step is 00257 aborted. The error handler is never called. 00258 00259 This adaptive stepper function is faster than astep() or 00260 astep_derivs() because it does not require any copying of 00261 vectors. 00262 */ 00263 virtual int astep_full(double x, double xmax, double &x_out, double &h, 00264 size_t n, vec_t &y, vec_t &dydx, 00265 vec_t &yout2, vec_t &yerr, vec_t &dydx_out, 00266 func_t &derivs) { 00267 00268 count=0; 00269 failed_steps=0; 00270 last_step=0.0; 00271 00272 int ret=evolve_apply(x,x_out,h,xmax,n,y,dydx,yout2,yerr,dydx_out, 00273 derivs); 00274 00275 if (this->verbose>0) { 00276 std::cout << x_out << " "; 00277 for(size_t j=0;j<n;j++) std::cout << yout2[j] << " "; 00278 std::cout << std::endl; 00279 } 00280 00281 return ret; 00282 } 00283 00284 /** \brief Make an adaptive integration step of the system 00285 \c derivs 00286 00287 This attempts to take a step of size \c h from the point \c 00288 x of an \c n-dimensional system \c derivs starting with \c 00289 y. On exit, \c x and \c y contain the new values at the end 00290 of the step, \c h contains the size of the step, \c dydx_out 00291 contains the derivative at the end of the step, and \c yerr 00292 contains the estimated error at the end of the step. 00293 00294 If the system \c derivs or the base stepper return a non-zero 00295 value, the adaptive step is aborted and \c y is unmodified. 00296 The error handler is never called. 00297 */ 00298 virtual int astep(double &x, double xmax, double &h, 00299 size_t n, vec_t &y, vec_t &dydx_out, 00300 vec_t &yerr, func_t &derivs) { 00301 count=0; 00302 failed_steps=0; 00303 last_step=0.0; 00304 00305 if (n!=msize) { 00306 ao.allocate(yout,n); 00307 ao.allocate(dydx_int,n); 00308 msize=n; 00309 } 00310 00311 int ret=derivs(x,n,y,dydx_int); 00312 if (ret!=0) return ret; 00313 00314 ret=evolve_apply(x,x,h,xmax,n,y,dydx_int,yout,yerr,dydx_out, 00315 derivs); 00316 00317 if (ret==gsl_success) { 00318 for(size_t i=0;i<n;i++) { 00319 y[i]=yout[i]; 00320 } 00321 } 00322 00323 if (this->verbose>0) { 00324 std::cout << x << " "; 00325 for(size_t j=0;j<n;j++) std::cout << y[j] << " "; 00326 std::cout << std::endl; 00327 } 00328 00329 return ret; 00330 } 00331 00332 }; 00333 00334 #ifndef DOXYGENP 00335 } 00336 #endif 00337 00338 #endif
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).