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 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 yerr[i]=h*(ec[1]*dydx[i]+ec[3]*k3[i]+ec[4]*k4[i]+ec[5]*k5[i]+ 00184 ec[6]*k6[i]); 00185 } 00186 00187 for (i=0;i<n;i++) { 00188 dydx_out[i]=c1*dydx[i]+c3*k3[i]+c4*k4[i]+c6*k6[i]; 00189 00190 yout[i]=y[i]+h*dydx_out[i]; 00191 } 00192 00193 return ret; 00194 } 00195 00196 }; 00197 00198 /** \brief Faster Cash-Karp embedded Runge-Kutta ODE stepper (GSL) 00199 00200 This a faster version of \ref gsl_rkck, which is a stepper for a 00201 fixed number of ODEs. It ignores the error values returned by 00202 the \c derivs argument. The argument \c n to step() should 00203 always be equal to the template parameter \c N, and the vector 00204 parameters to step must have space allocated for at least \c N 00205 elements. No error checking is performed to ensure that this is 00206 the case. 00207 */ 00208 template<size_t N, class param_t, class func_t, class vec_t=ovector_view, 00209 class alloc_vec_t=ovector, class alloc_t=ovector_alloc> 00210 class gsl_rkck_fast : 00211 public odestep<param_t,func_t,vec_t> { 00212 00213 protected: 00214 00215 /// \name Storage for the intermediate steps 00216 //@{ 00217 alloc_vec_t k2, k3, k4, k5, k6, ytmp; 00218 //@} 00219 00220 /// Memory allocator for objects of type \c alloc_vec_t 00221 alloc_t ao; 00222 00223 /** \name Storage for the coefficients 00224 */ 00225 //@{ 00226 double ah[5], b3[2], b4[3], b5[4], b6[5], ec[7]; 00227 double b21, c1, c3, c4, c6; 00228 //@} 00229 00230 public: 00231 00232 gsl_rkck_fast() { 00233 this->order=5; 00234 00235 ah[0]=1.0/5.0; 00236 ah[1]=3.0/10.0; 00237 ah[2]=3.0/5.0; 00238 ah[3]=1.0; 00239 ah[4]=7.0/8.0; 00240 b3[0]=3.0/40.0; 00241 b3[1]=9.0/40.0; 00242 b4[0]=3.0/10.0; 00243 b4[1]=-9.0/10.0; 00244 b4[2]=12.0/10.0; 00245 b5[0]=-11.0/54.0; 00246 b5[1]=5.0/2.0; 00247 b5[2]=-70.0/27.0; 00248 b5[3]=35.0/27.0; 00249 b6[0]=1631.0/55296.0; 00250 b6[1]=175.0/512.0; 00251 b6[2]=575.0/13824.0; 00252 b6[3]=44275.0/110592.0; 00253 b6[4]=253.0/4096.0; 00254 ec[0]=0.0; 00255 ec[1]=37.0/378.0-2825.0/27648.0; 00256 ec[2]=0.0; 00257 ec[3]=250.0/621.0-18575.0/48384.0; 00258 ec[4]=125.0/594.0-13525.0/55296.0; 00259 ec[5]=-277.0/14336.0; 00260 ec[6]=512.0/1771.0-1.0/4.0; 00261 00262 b21=1.0/5.0; 00263 c1=37.0/378.0; 00264 c3=250.0/621.0; 00265 c4=125.0/594.0; 00266 c6=512.0/1771.0; 00267 00268 ao.allocate(k2,N); 00269 ao.allocate(k3,N); 00270 ao.allocate(k4,N); 00271 ao.allocate(k5,N); 00272 ao.allocate(k6,N); 00273 ao.allocate(ytmp,N); 00274 00275 } 00276 00277 virtual ~gsl_rkck_fast() { 00278 00279 ao.free(k2); 00280 ao.free(k3); 00281 ao.free(k4); 00282 ao.free(k5); 00283 ao.free(k6); 00284 ao.free(ytmp); 00285 } 00286 00287 /** 00288 \brief Perform an integration step 00289 00290 Given initial value of the n-dimensional function in \c y and 00291 the derivative in \c dydx (which must generally be computed 00292 beforehand) at the point \c x, take a step of size \c h giving 00293 the result in \c yout, the uncertainty in \c yerr, and the new 00294 derivative in \c dydx_out using function \c derivs to 00295 calculate derivatives. The parameters \c yout and \c y and the 00296 parameters \c dydx_out and \c dydx may refer to the same 00297 object. 00298 00299 \note The value of the parameter \c n should be equal to 00300 the template parameter \c N. 00301 */ 00302 virtual int step(double x, double h, size_t n, vec_t &y, vec_t &dydx, 00303 vec_t &yout, vec_t &yerr, vec_t &dydx_out, param_t &pa, 00304 func_t &derivs) { 00305 00306 size_t i; 00307 00308 for (i=0;i<N;i++) { 00309 ytmp[i]=y[i]+b21*h*dydx[i]; 00310 } 00311 00312 derivs(x+ah[0]*h,N,ytmp,k2,pa); 00313 00314 for (i=0;i<N;i++) { 00315 ytmp[i]=y[i]+h*(b3[0]*dydx[i]+b3[1]*k2[i]); 00316 } 00317 00318 derivs(x+ah[1]*h,N,ytmp,k3,pa); 00319 00320 for (i=0;i<N;i++) { 00321 ytmp[i]=y[i]+h*(b4[0]*dydx[i]+b4[1]*k2[i]+b4[2]*k3[i]); 00322 } 00323 00324 derivs(x+ah[2]*h,N,ytmp,k4,pa); 00325 00326 for (i=0;i<N;i++) { 00327 ytmp[i]=y[i]+h*(b5[0]*dydx[i]+b5[1]*k2[i]+b5[2]*k3[i]+ 00328 b5[3]*k4[i]); 00329 } 00330 00331 derivs(x+ah[3]*h,N,ytmp,k5,pa); 00332 00333 for (i=0;i<N;i++) { 00334 ytmp[i]=y[i]+h*(b6[0]*dydx[i]+b6[1]*k2[i]+b6[2]*k3[i]+ 00335 b6[3]*k4[i]+b6[4]*k5[i]); 00336 } 00337 00338 derivs(x+ah[4]*h,N,ytmp,k6,pa); 00339 00340 for (i=0;i<N;i++) { 00341 yerr[i]=h*(ec[1]*dydx[i]+ec[3]*k3[i]+ec[4]*k4[i]+ec[5]*k5[i]+ 00342 ec[6]*k6[i]); 00343 } 00344 00345 for (i=0;i<N;i++) { 00346 dydx_out[i]=c1*dydx[i]+c3*k3[i]+c4*k4[i]+c6*k6[i]; 00347 yout[i]=y[i]+h*dydx_out[i]; 00348 } 00349 00350 return 0; 00351 } 00352 00353 }; 00354 00355 #ifndef DOXYGENP 00356 } 00357 #endif 00358 00359 #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