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 00024 #ifndef O2SCL_GSL_RKCK_H 00025 #define O2SCL_GSL_RKCK_H 00026 00027 #include <o2scl/err_hnd.h> 00028 #include <o2scl/odestep.h> 00029 00030 #ifndef DOXYGENP 00031 namespace o2scl { 00032 #endif 00033 00034 /** \brief Cash-Karp embedded Runge-Kutta ODE stepper (GSL) 00035 */ 00036 template<class param_t, class func_t, class vec_t=ovector_view, 00037 class alloc_vec_t=ovector, class alloc_t=ovector_alloc> class gsl_rkck : 00038 public odestep<param_t,func_t,vec_t> { 00039 00040 protected: 00041 00042 /// \name Storage for the intermediate steps 00043 //@{ 00044 alloc_vec_t k2, k3, k4, k5, k6, ytmp; 00045 //@} 00046 00047 /// Size of allocated vectors 00048 size_t ndim; 00049 00050 /// Memory allocator for objects of type \c alloc_vec_t 00051 alloc_t ao; 00052 00053 /** \name Storage for the coefficients 00054 */ 00055 //@{ 00056 double ah[5], b3[2], b4[3], b5[4], b6[5], ec[7]; 00057 double b21, c1, c3, c4, c6; 00058 //@} 00059 00060 public: 00061 00062 gsl_rkck() { 00063 this->order=5; 00064 00065 ah[0]=1.0/5.0; 00066 ah[1]=3.0/10.0; 00067 ah[2]=3.0/5.0; 00068 ah[3]=1.0; 00069 ah[4]=7.0/8.0; 00070 b3[0]=3.0/40.0; 00071 b3[1]=9.0/40.0; 00072 b4[0]=3.0/10.0; 00073 b4[1]=-9.0/10.0; 00074 b4[2]=12.0/10.0; 00075 b5[0]=-11.0/54.0; 00076 b5[1]=5.0/2.0; 00077 b5[2]=-70.0/27.0; 00078 b5[3]=35.0/27.0; 00079 b6[0]=1631.0/55296.0; 00080 b6[1]=175.0/512.0; 00081 b6[2]=575.0/13824.0; 00082 b6[3]=44275.0/110592.0; 00083 b6[4]=253.0/4096.0; 00084 ec[0]=0.0; 00085 ec[1]=37.0/378.0-2825.0/27648.0; 00086 ec[2]=0.0; 00087 ec[3]=250.0/621.0-18575.0/48384.0; 00088 ec[4]=125.0/594.0-13525.0/55296.0; 00089 ec[5]=-277.0/14336.0; 00090 ec[6]=512.0/1771.0-1.0/4.0; 00091 00092 b21=1.0/5.0; 00093 c1=37.0/378.0; 00094 c3=250.0/621.0; 00095 c4=125.0/594.0; 00096 c6=512.0/1771.0; 00097 00098 ndim=0; 00099 } 00100 00101 virtual ~gsl_rkck() { 00102 if (ndim!=0) { 00103 ao.free(k2); 00104 ao.free(k3); 00105 ao.free(k4); 00106 ao.free(k5); 00107 ao.free(k6); 00108 ao.free(ytmp); 00109 } 00110 } 00111 00112 /** 00113 \brief Perform an integration step 00114 00115 Given initial value of the n-dimensional function in \c y and 00116 the derivative in \c dydx (which must generally be computed 00117 beforehand) at the point \c x, take a step of size \c h giving 00118 the result in \c yout, the uncertainty in \c yerr, and the new 00119 derivative in \c dydx_out using function \c derivs to 00120 calculate derivatives. The parameters \c yout and \c y and the 00121 parameters \c dydx_out and \c dydx may refer to the same 00122 object. 00123 */ 00124 virtual int step(double x, double h, size_t n, vec_t &y, vec_t &dydx, 00125 vec_t &yout, vec_t &yerr, vec_t &dydx_out, param_t &pa, 00126 func_t &derivs) { 00127 00128 int ret=0; 00129 size_t i; 00130 00131 if (ndim!=n) { 00132 if (ndim>0) { 00133 ao.free(k2); 00134 ao.free(k3); 00135 ao.free(k4); 00136 ao.free(k5); 00137 ao.free(k6); 00138 ao.free(ytmp); 00139 } 00140 ao.allocate(k2,n); 00141 ao.allocate(k3,n); 00142 ao.allocate(k4,n); 00143 ao.allocate(k5,n); 00144 ao.allocate(k6,n); 00145 ao.allocate(ytmp,n); 00146 00147 ndim=n; 00148 } 00149 00150 for (i=0;i<n;i++) { 00151 ytmp[i]=y[i]+b21*h*dydx[i]; 00152 } 00153 00154 o2scl::error_update(ret,derivs(x+ah[0]*h,n,ytmp,k2,pa)); 00155 00156 for (i=0;i<n;i++) { 00157 ytmp[i]=y[i]+h*(b3[0]*dydx[i]+b3[1]*k2[i]); 00158 } 00159 00160 o2scl::error_update(ret,derivs(x+ah[1]*h,n,ytmp,k3,pa)); 00161 00162 for (i=0;i<n;i++) { 00163 ytmp[i]=y[i]+h*(b4[0]*dydx[i]+b4[1]*k2[i]+b4[2]*k3[i]); 00164 } 00165 00166 o2scl::error_update(ret,derivs(x+ah[2]*h,n,ytmp,k4,pa)); 00167 00168 for (i=0;i<n;i++) { 00169 ytmp[i]=y[i]+h*(b5[0]*dydx[i]+b5[1]*k2[i]+b5[2]*k3[i]+ 00170 b5[3]*k4[i]); 00171 } 00172 00173 o2scl::error_update(ret,derivs(x+ah[3]*h,n,ytmp,k5,pa)); 00174 00175 for (i=0;i<n;i++) { 00176 ytmp[i]=y[i]+h*(b6[0]*dydx[i]+b6[1]*k2[i]+b6[2]*k3[i]+ 00177 b6[3]*k4[i]+b6[4]*k5[i]); 00178 } 00179 00180 o2scl::error_update(ret,derivs(x+ah[4]*h,n,ytmp,k6,pa)); 00181 00182 for (i=0;i<n;i++) { 00183 yout[i]=y[i]+h*(c1*dydx[i]+c3*k3[i]+c4*k4[i]+c6*k6[i]); 00184 } 00185 00186 // We put this before the last function evaluation, in contrast 00187 // to the GSL version, so that the dydx[i] that appears in the 00188 // for loop below isn't modified by the subsequent derivative 00189 // evaluation using dydx_out. (The user could have given the 00190 // same vector for both) 00191 for (i=0;i<n;i++) { 00192 yerr[i]=h*(ec[1]*dydx[i]+ec[3]*k3[i]+ec[4]*k4[i]+ec[5]*k5[i]+ 00193 ec[6]*k6[i]); 00194 } 00195 00196 o2scl::error_update(ret,derivs(x+h,n,yout,dydx_out,pa)); 00197 00198 return ret; 00199 } 00200 00201 }; 00202 00203 /** \brief Faster Cash-Karp embedded Runge-Kutta ODE stepper (GSL) 00204 00205 This a faster version of \ref gsl_rkck, which is a stepper for a 00206 fixed number of ODEs. It ignores the error values returned by 00207 the \c derivs argument. The argument \c n to step() should 00208 always be equal to the template parameter \c N, and the vector 00209 parameters to step must have space allocated for at least \c N 00210 elements. No error checking is performed to ensure that this is 00211 the case. 00212 */ 00213 template<size_t N, class param_t, class func_t, class vec_t=ovector_view, 00214 class alloc_vec_t=ovector, class alloc_t=ovector_alloc> 00215 class gsl_rkck_fast : 00216 public odestep<param_t,func_t,vec_t> { 00217 00218 protected: 00219 00220 /// \name Storage for the intermediate steps 00221 //@{ 00222 alloc_vec_t k2, k3, k4, k5, k6, ytmp; 00223 //@} 00224 00225 /// Memory allocator for objects of type \c alloc_vec_t 00226 alloc_t ao; 00227 00228 /** \name Storage for the coefficients 00229 */ 00230 //@{ 00231 double ah[5], b3[2], b4[3], b5[4], b6[5], ec[7]; 00232 double b21, c1, c3, c4, c6; 00233 //@} 00234 00235 public: 00236 00237 gsl_rkck_fast() { 00238 this->order=5; 00239 00240 ah[0]=1.0/5.0; 00241 ah[1]=3.0/10.0; 00242 ah[2]=3.0/5.0; 00243 ah[3]=1.0; 00244 ah[4]=7.0/8.0; 00245 b3[0]=3.0/40.0; 00246 b3[1]=9.0/40.0; 00247 b4[0]=3.0/10.0; 00248 b4[1]=-9.0/10.0; 00249 b4[2]=12.0/10.0; 00250 b5[0]=-11.0/54.0; 00251 b5[1]=5.0/2.0; 00252 b5[2]=-70.0/27.0; 00253 b5[3]=35.0/27.0; 00254 b6[0]=1631.0/55296.0; 00255 b6[1]=175.0/512.0; 00256 b6[2]=575.0/13824.0; 00257 b6[3]=44275.0/110592.0; 00258 b6[4]=253.0/4096.0; 00259 ec[0]=0.0; 00260 ec[1]=37.0/378.0-2825.0/27648.0; 00261 ec[2]=0.0; 00262 ec[3]=250.0/621.0-18575.0/48384.0; 00263 ec[4]=125.0/594.0-13525.0/55296.0; 00264 ec[5]=-277.0/14336.0; 00265 ec[6]=512.0/1771.0-1.0/4.0; 00266 00267 b21=1.0/5.0; 00268 c1=37.0/378.0; 00269 c3=250.0/621.0; 00270 c4=125.0/594.0; 00271 c6=512.0/1771.0; 00272 00273 ao.allocate(k2,N); 00274 ao.allocate(k3,N); 00275 ao.allocate(k4,N); 00276 ao.allocate(k5,N); 00277 ao.allocate(k6,N); 00278 ao.allocate(ytmp,N); 00279 00280 } 00281 00282 virtual ~gsl_rkck_fast() { 00283 00284 ao.free(k2); 00285 ao.free(k3); 00286 ao.free(k4); 00287 ao.free(k5); 00288 ao.free(k6); 00289 ao.free(ytmp); 00290 } 00291 00292 /** 00293 \brief Perform an integration step 00294 00295 Given initial value of the n-dimensional function in \c y and 00296 the derivative in \c dydx (which must generally be computed 00297 beforehand) at the point \c x, take a step of size \c h giving 00298 the result in \c yout, the uncertainty in \c yerr, and the new 00299 derivative in \c dydx_out using function \c derivs to 00300 calculate derivatives. The parameters \c yout and \c y and the 00301 parameters \c dydx_out and \c dydx may refer to the same 00302 object. 00303 00304 \note The value of the parameter \c n should be equal to 00305 the template parameter \c N. 00306 */ 00307 virtual int step(double x, double h, size_t n, vec_t &y, vec_t &dydx, 00308 vec_t &yout, vec_t &yerr, vec_t &dydx_out, param_t &pa, 00309 func_t &derivs) { 00310 00311 size_t i; 00312 00313 for (i=0;i<N;i++) { 00314 ytmp[i]=y[i]+b21*h*dydx[i]; 00315 } 00316 00317 derivs(x+ah[0]*h,N,ytmp,k2,pa); 00318 00319 for (i=0;i<N;i++) { 00320 ytmp[i]=y[i]+h*(b3[0]*dydx[i]+b3[1]*k2[i]); 00321 } 00322 00323 derivs(x+ah[1]*h,N,ytmp,k3,pa); 00324 00325 for (i=0;i<N;i++) { 00326 ytmp[i]=y[i]+h*(b4[0]*dydx[i]+b4[1]*k2[i]+b4[2]*k3[i]); 00327 } 00328 00329 derivs(x+ah[2]*h,N,ytmp,k4,pa); 00330 00331 for (i=0;i<N;i++) { 00332 ytmp[i]=y[i]+h*(b5[0]*dydx[i]+b5[1]*k2[i]+b5[2]*k3[i]+ 00333 b5[3]*k4[i]); 00334 } 00335 00336 derivs(x+ah[3]*h,N,ytmp,k5,pa); 00337 00338 for (i=0;i<N;i++) { 00339 ytmp[i]=y[i]+h*(b6[0]*dydx[i]+b6[1]*k2[i]+b6[2]*k3[i]+ 00340 b6[3]*k4[i]+b6[4]*k5[i]); 00341 } 00342 00343 derivs(x+ah[4]*h,N,ytmp,k6,pa); 00344 00345 for (i=0;i<n;i++) { 00346 yout[i]=y[i]+h*(c1*dydx[i]+c3*k3[i]+c4*k4[i]+c6*k6[i]); 00347 } 00348 00349 // We put this before the last function evaluation, in contrast 00350 // to the GSL version, so that the dydx[i] that appears in the 00351 // for loop below isn't modified by the subsequent derivative 00352 // evaluation using dydx_out. (The user could have given the 00353 // same vector for both) 00354 for (i=0;i<n;i++) { 00355 yerr[i]=h*(ec[1]*dydx[i]+ec[3]*k3[i]+ec[4]*k4[i]+ec[5]*k5[i]+ 00356 ec[6]*k6[i]); 00357 } 00358 00359 derivs(x+h,n,yout,dydx_out,pa); 00360 00361 return 0; 00362 } 00363 00364 }; 00365 00366 #ifndef DOXYGENP 00367 } 00368 #endif 00369 00370 #endif
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