gsl_rk8pd.h

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_RK8PD_H
00025 #define O2SCL_GSL_RK8PD_H
00026 
00027 #include <o2scl/vec_arith.h>
00028 #include <o2scl/odestep.h>
00029 
00030 #ifndef DOXYGENP
00031 namespace o2scl {
00032 #endif
00033 
00034   /** 
00035       \brief Embedded Runge-Kutta Prince-Dormand ODE stepper (GSL)
00036   */
00037   template<class param_t, class func_t=ode_funct<param_t>, 
00038     class vec_t=ovector_view, class alloc_vec_t=ovector,
00039     class alloc_t=ovector_alloc> class gsl_rk8pd : 
00040   public odestep<param_t,func_t,vec_t> {
00041 
00042   protected:
00043   
00044     /// \name Storage for the intermediate steps
00045     //@{
00046     alloc_vec_t k2, k3, k4, k5, k6, k7, ytmp;
00047     alloc_vec_t k8, k9, k10, k11, k12, k13;
00048     //@}
00049     
00050     /// Size of allocated vectors
00051     size_t ndim;
00052 
00053     /// Memory allocator for objects of type \c alloc_vec_t
00054     alloc_t ao;
00055 
00056     /** \name Storage for the coefficients
00057      */
00058     //@{
00059     double Abar[13], A[12], ah[10], b21, b3[2], b4[3], b5[4], b6[5];
00060     double b7[6], b8[7], b9[8], b10[9], b11[10], b12[11], b13[12];
00061     //@}
00062       
00063   public:
00064 
00065     gsl_rk8pd() {
00066       this->order=8;
00067 
00068       Abar[0]=14005451.0/335480064.0;
00069       Abar[1]=0.0;
00070       Abar[2]=0.0;
00071       Abar[3]=0.0;
00072       Abar[4]=0.0;
00073       Abar[5]=-59238493.0/1068277825.0;
00074       Abar[6]=181606767.0/758867731.0;
00075       Abar[7]=561292985.0/797845732.0;
00076       Abar[8]=-1041891430.0/1371343529.0;
00077       Abar[9]=760417239.0/1151165299.0;
00078       Abar[10]=118820643.0/751138087.0;
00079       Abar[11]=-528747749.0/2220607170.0;
00080       Abar[12]=1.0/4.0;
00081 
00082       A[0]=13451932.0/455176623.0;
00083       A[1]=0.0;
00084       A[2]=0.0;
00085       A[3]=0.0;
00086       A[4]=0.0;
00087       A[5]=-808719846.0/976000145.0;
00088       A[6]=1757004468.0/5645159321.0;
00089       A[7]=656045339.0/265891186.0;
00090       A[8]=-3867574721.0/1518517206.0;
00091       A[9]=465885868.0/322736535.0;
00092       A[10]=53011238.0/667516719.0;
00093       A[11]=2.0/45.0;
00094 
00095       ah[0]=1.0/18.0;
00096       ah[1]=1.0/12.0;
00097       ah[2]=1.0/8.0;
00098       ah[3]=5.0/16.0;
00099       ah[4]=3.0/8.0;
00100       ah[5]=59.0/400.0;
00101       ah[6]=93.0/200.0;
00102       ah[7]=5490023248.0/9719169821.0;
00103       ah[8]=13.0/20.0;
00104       ah[9]=1201146811.0/1299019798.0;
00105       
00106       b21=1.0/18.0;
00107 
00108       b3[0]=1.0/48.0;
00109       b3[1]=1.0/16.0;
00110 
00111       b4[0]=1.0/32.0;
00112       b4[1]=0.0;
00113       b4[2]=3.0/32.0;
00114 
00115       b5[0]=5.0/16.0;
00116       b5[1]=0.0;
00117       b5[2]=-75.0/64.0;
00118       b5[3]=75.0/64.0;
00119 
00120       b6[0]=3.0/80.0;
00121       b6[1]=0.0;
00122       b6[2]=0.0;
00123       b6[3]=3.0/16.0;
00124       b6[4]=3.0/20.0;
00125 
00126       b7[0]=29443841.0/614563906.0;
00127       b7[1]=0.0;
00128       b7[2]=0.0;
00129       b7[3]=77736538.0/692538347.0;
00130       b7[4]=-28693883.0/1125000000.0;
00131       b7[5]=23124283.0/1800000000.0;
00132 
00133       b8[0]=16016141.0/946692911.0;
00134       b8[1]=0.0;
00135       b8[2]=0.0;
00136       b8[3]=61564180.0/158732637.0;
00137       b8[4]=22789713.0/633445777.0;
00138       b8[5]=545815736.0/2771057229.0;
00139       b8[6]=-180193667.0/1043307555.0;
00140 
00141       b9[0]=39632708.0/573591083.0;
00142       b9[1]=0.0;
00143       b9[2]=0.0;
00144       b9[3]=-433636366.0/683701615.0;
00145       b9[4]=-421739975.0/2616292301.0;
00146       b9[5]=100302831.0/723423059.0;
00147       b9[6]=790204164.0/839813087.0;
00148       b9[7]=800635310.0/3783071287.0;
00149 
00150       b10[0]=246121993.0/1340847787.0;
00151       b10[1]=0.0;
00152       b10[2]=0.0;
00153       b10[3]=-37695042795.0/15268766246.0;
00154       b10[4]=-309121744.0/1061227803.0;
00155       b10[5]=-12992083.0/490766935.0;
00156       b10[6]=6005943493.0/2108947869.0;
00157       b10[7]=393006217.0/1396673457.0;
00158       b10[8]=123872331.0/1001029789.0;
00159 
00160       b11[0]=-1028468189.0/846180014.0;
00161       b11[1]=0.0;
00162       b11[2]=0.0;
00163       b11[3]=8478235783.0/508512852.0;
00164       b11[4]=1311729495.0/1432422823.0;
00165       b11[5]=-10304129995.0/1701304382.0;
00166       b11[6]=-48777925059.0/3047939560.0;
00167       b11[7]=15336726248.0/1032824649.0;
00168       b11[8]=-45442868181.0/3398467696.0;
00169       b11[9]=3065993473.0/597172653.0;
00170 
00171       b12[0]=185892177.0/718116043.0;
00172       b12[1]=0.0;
00173       b12[2]=0.0;
00174       b12[3]=-3185094517.0/667107341.0;
00175       b12[4]=-477755414.0/1098053517.0;
00176       b12[5]=-703635378.0/230739211.0;
00177       b12[6]=5731566787.0/1027545527.0;
00178       b12[7]=5232866602.0/850066563.0;
00179       b12[8]=-4093664535.0/808688257.0;
00180       b12[9]=3962137247.0/1805957418.0;
00181       b12[10]=65686358.0/487910083.0;
00182 
00183       b13[0]=403863854.0/491063109.0;
00184       b13[1]=0.0;
00185       b13[2]=0.0;
00186       b13[3]=-5068492393.0/434740067.0;
00187       b13[4]=-411421997.0/543043805.0;
00188       b13[5]=652783627.0/914296604.0;
00189       b13[6]=11173962825.0/925320556.0;
00190       b13[7]=-13158990841.0/6184727034.0;
00191       b13[8]=3936647629.0/1978049680.0;
00192       b13[9]=-160528059.0/685178525.0;
00193       b13[10]=248638103.0/1413531060.0;
00194       b13[11]=0.0;
00195 
00196       ndim=0;
00197     }
00198       
00199     virtual ~gsl_rk8pd() {
00200       if (ndim!=0) {
00201         ao.free(k2);
00202         ao.free(k3);
00203         ao.free(k4);
00204         ao.free(k5);
00205         ao.free(k6);
00206         ao.free(k7);
00207         ao.free(k8);
00208         ao.free(k9);
00209         ao.free(k10);
00210         ao.free(k11);
00211         ao.free(k12);
00212         ao.free(k13);
00213         ao.free(ytmp);
00214       }
00215     }
00216 
00217     /** 
00218         \brief Perform an integration step
00219 
00220         Given initial value of the n-dimensional function in \c y and
00221         the derivative in \c dydx (which must generally be computed
00222         beforehand) at the point \c x, take a step of size \c h giving
00223         the result in \c yout, the uncertainty in \c yerr, and the new
00224         derivative in \c dydx_out using function \c derivs to
00225         calculate derivatives. The parameters \c yout and \c y and the
00226         parameters \c dydx_out and \c dydx may refer to the same
00227         object.
00228     */
00229     virtual int step(double x, double h, size_t n, vec_t &y, vec_t &dydx, 
00230                      vec_t &yout, vec_t &yerr, vec_t &dydx_out, param_t &pa, 
00231                      func_t &derivs) {
00232         
00233       int ret=0;
00234       size_t i;
00235       
00236       if (ndim!=n) {
00237         if (ndim>0) {
00238           ao.free(k2);
00239           ao.free(k3);
00240           ao.free(k4);
00241           ao.free(k5);
00242           ao.free(k6);
00243           ao.free(k7);
00244           ao.free(k8);
00245           ao.free(k9);
00246           ao.free(k10);
00247           ao.free(k11);
00248           ao.free(k12);
00249           ao.free(k13);
00250           ao.free(ytmp);
00251         }
00252         ao.allocate(k2,n);
00253         ao.allocate(k3,n);
00254         ao.allocate(k4,n);
00255         ao.allocate(k5,n);
00256         ao.allocate(k6,n);
00257         ao.allocate(k7,n);
00258         ao.allocate(k8,n);
00259         ao.allocate(k9,n);
00260         ao.allocate(k10,n);
00261         ao.allocate(k11,n);
00262         ao.allocate(k12,n);
00263         ao.allocate(k13,n);
00264         ao.allocate(ytmp,n);
00265 
00266         ndim=n;
00267       }
00268 
00269       for (i=0;i<n;i++) {
00270         ytmp[i]=y[i]+b21*h*dydx[i];
00271       }
00272         
00273       error_update(ret,derivs(x+ah[0]*h,n,ytmp,k2,pa));
00274 
00275       for (i=0;i<n;i++) {
00276         ytmp[i]=y[i]+h*(b3[0]*dydx[i]+b3[1]*k2[i]);
00277       }
00278       
00279       error_update(ret,derivs(x+ah[1]*h,n,ytmp,k3,pa));
00280       
00281       for (i=0;i<n;i++) {
00282         ytmp[i]=y[i]+h*(b4[0]*dydx[i]+b4[2]*k3[i]);
00283       }
00284 
00285       error_update(ret,derivs(x+ah[2]*h,n,ytmp,k4,pa));
00286 
00287       for (i=0;i<n;i++) {
00288         ytmp[i]=y[i]+h*(b5[0]*dydx[i]+b5[2]*k3[i]+b5[3]*k4[i]);
00289       }
00290       
00291       error_update(ret,derivs(x+ah[3]*h,n,ytmp,k5,pa));
00292       
00293       for (i=0;i<n;i++) {
00294         ytmp[i]=y[i]+h*(b6[0]*dydx[i]+b6[3]*k4[i]+b6[4]*k5[i]);
00295       }
00296       
00297       error_update(ret,derivs(x+ah[4]*h,n,ytmp,k6,pa));
00298       
00299       for (i=0;i<n;i++) {
00300         ytmp[i]=y[i]+h*(b7[0]*dydx[i]+b7[3]*k4[i]+b7[4]*k5[i]+b7[5]*k6[i]);
00301       }
00302       
00303       error_update(ret,derivs(x+ah[5]*h,n,ytmp,k7,pa));
00304       
00305       for (i=0;i<n;i++) {
00306         ytmp[i]=y[i]+h*(b8[0]*dydx[i]+b8[3]*k4[i]+b8[4]*k5[i]+b8[5]*k6[i]+
00307                    b8[6]*k7[i]);
00308       }
00309 
00310       error_update(ret,derivs(x+ah[6]*h,n,ytmp,k8,pa));
00311       
00312       for (i=0;i<n;i++) {
00313         ytmp[i]=y[i]+h*(b9[0]*dydx[i]+b9[3]*k4[i]+b9[4]*k5[i]+b9[5]*k6[i]+
00314                    b9[6]*k7[i]+b9[7]*k8[i]);
00315       }
00316 
00317       error_update(ret,derivs(x+ah[7]*h,n,ytmp,k9,pa));
00318       
00319       for (i=0;i<n;i++) {
00320         ytmp[i]=y[i]+h*(b10[0]*dydx[i]+b10[3]*k4[i]+b10[4]*k5[i]+
00321                         b10[5]*k6[i]+b10[6]*k7[i]+b10[7]*k8[i]+
00322                         b10[8]*k9[i]);
00323       }
00324 
00325       error_update(ret,derivs(x+ah[8]*h,n,ytmp,k10,pa));
00326       
00327       for (i=0;i<n;i++) {
00328         ytmp[i]=y[i]+h*(b11[0]*dydx[i]+b11[3]*k4[i]+b11[4]*k5[i]+
00329                         b11[5]*k6[i]+b11[6]*k7[i]+b11[7]*k8[i]+
00330                         b11[8]*k9[i]+b11[9]*k10[i]);
00331       }
00332 
00333       error_update(ret,derivs(x+ah[9]*h,n,ytmp,k11,pa));
00334       
00335       for (i=0;i<n;i++) {
00336         ytmp[i]=y[i]+h*(b12[0]*dydx[i]+b12[3]*k4[i]+b12[4]*k5[i]+
00337                         b12[5]*k6[i]+b12[6]*k7[i]+b12[7]*k8[i]+
00338                         b12[8]*k9[i]+b12[9]*k10[i]+b12[10]*k11[i]);
00339       }
00340 
00341       error_update(ret,derivs(x+h,n,ytmp,k12,pa));
00342       
00343       for (i=0;i<n;i++) {
00344         ytmp[i]=y[i]+h*(b13[0]*dydx[i]+b13[3]*k4[i]+b13[4]*k5[i]+
00345                         b13[5]*k6[i]+b13[6]*k7[i]+b13[7]*k8[i]+
00346                         b13[8]*k9[i]+b13[9]*k10[i]+b13[10]*k11[i]+
00347                         b13[11]*k12[i]);
00348       }
00349 
00350       error_update(ret,derivs(x+h,n,ytmp,k13,pa));
00351 
00352       // final sum
00353 
00354       for (i=0;i<n;i++) {
00355         double ksum8=Abar[0]*dydx[i]+Abar[5]*k6[i]+Abar[6]*k7[i]+
00356           Abar[7]*k8[i]+Abar[8]*k9[i]+Abar[9]*k10[i]+
00357           Abar[10]*k11[i]+Abar[11]*k12[i]+Abar[12]*k13[i];
00358 
00359         yout[i]=y[i]+h*ksum8;
00360       }
00361       
00362       // We put this before the last function evaluation, in contrast
00363       // to the GSL version, so that the dydx[i] that appears in the
00364       // for loop below isn't modified by the subsequent derivative
00365       // evaluation using dydx_out. (The user could have given the
00366       // same vector for both)
00367       for (i=0;i<n;i++) {
00368 
00369         double ksum8=Abar[0]*dydx[i]+Abar[5]*k6[i]+Abar[6]*k7[i]+
00370           Abar[7]*k8[i]+Abar[8]*k9[i]+Abar[9]*k10[i]+
00371           Abar[10]*k11[i]+Abar[11]*k12[i]+Abar[12]*k13[i];
00372         double ksum7=A[0]*dydx[i]+A[5]*k6[i]+A[6]*k7[i]+A[7]*k8[i]+
00373           A[8]*k9[i]+A[9]*k10[i]+A[10]*k11[i]+A[11]*k12[i];
00374         
00375         yerr[i]=h*(ksum7-ksum8);
00376       }
00377       
00378       error_update(ret,derivs(x+h,n,yout,dydx_out,pa));
00379 
00380       return ret;
00381     }
00382     
00383   };
00384   
00385   /** 
00386       \brief Faster embedded Runge-Kutta Prince-Dormand ODE stepper 
00387       (GSL)
00388 
00389       This a fast version of \ref gsl_rk8pd, which is a stepper for a
00390       fixed number of ODEs. It ignores the error values returned by
00391       the \c derivs argument. The argument \c n to step() should
00392       always be equal to the template parameter \c N, and the vector
00393       parameters to step must have space allocated for at least \c N
00394       elements. No error checking is performed to ensure that this is
00395       the case.
00396   */
00397   template<size_t N, class param_t, class func_t=ode_funct<param_t>, 
00398     class vec_t=ovector_view, class alloc_vec_t=ovector, 
00399     class alloc_t=ovector_alloc> class gsl_rk8pd_fast : 
00400   public odestep<param_t,func_t,vec_t> {
00401     
00402   protected:
00403     
00404     /// \name Storage for the intermediate steps
00405     //@{
00406     alloc_vec_t k2, k3, k4, k5, k6, k7, ytmp;
00407     alloc_vec_t k8, k9, k10, k11, k12, k13;
00408     //@}
00409     
00410     /// Memory allocator for objects of type \c alloc_vec_t
00411     alloc_t ao;
00412 
00413     /** \name Storage for the coefficients
00414      */
00415     //@{
00416     double Abar[13], A[12], ah[10], b21, b3[2], b4[3], b5[4], b6[5];
00417     double b7[6], b8[7], b9[8], b10[9], b11[10], b12[11], b13[12];
00418     //@}
00419       
00420   public:
00421 
00422     gsl_rk8pd_fast() {
00423       this->order=8;
00424 
00425       Abar[0]=14005451.0/335480064.0;
00426       Abar[1]=0.0;
00427       Abar[2]=0.0;
00428       Abar[3]=0.0;
00429       Abar[4]=0.0;
00430       Abar[5]=-59238493.0/1068277825.0;
00431       Abar[6]=181606767.0/758867731.0;
00432       Abar[7]=561292985.0/797845732.0;
00433       Abar[8]=-1041891430.0/1371343529.0;
00434       Abar[9]=760417239.0/1151165299.0;
00435       Abar[10]=118820643.0/751138087.0;
00436       Abar[11]=-528747749.0/2220607170.0;
00437       Abar[12]=1.0/4.0;
00438 
00439       A[0]=13451932.0/455176623.0;
00440       A[1]=0.0;
00441       A[2]=0.0;
00442       A[3]=0.0;
00443       A[4]=0.0;
00444       A[5]=-808719846.0/976000145.0;
00445       A[6]=1757004468.0/5645159321.0;
00446       A[7]=656045339.0/265891186.0;
00447       A[8]=-3867574721.0/1518517206.0;
00448       A[9]=465885868.0/322736535.0;
00449       A[10]=53011238.0/667516719.0;
00450       A[11]=2.0/45.0;
00451 
00452       ah[0]=1.0/18.0;
00453       ah[1]=1.0/12.0;
00454       ah[2]=1.0/8.0;
00455       ah[3]=5.0/16.0;
00456       ah[4]=3.0/8.0;
00457       ah[5]=59.0/400.0;
00458       ah[6]=93.0/200.0;
00459       ah[7]=5490023248.0/9719169821.0;
00460       ah[8]=13.0/20.0;
00461       ah[9]=1201146811.0/1299019798.0;
00462       
00463       b21=1.0/18.0;
00464 
00465       b3[0]=1.0/48.0;
00466       b3[1]=1.0/16.0;
00467 
00468       b4[0]=1.0/32.0;
00469       b4[1]=0.0;
00470       b4[2]=3.0/32.0;
00471 
00472       b5[0]=5.0/16.0;
00473       b5[1]=0.0;
00474       b5[2]=-75.0/64.0;
00475       b5[3]=75.0/64.0;
00476 
00477       b6[0]=3.0/80.0;
00478       b6[1]=0.0;
00479       b6[2]=0.0;
00480       b6[3]=3.0/16.0;
00481       b6[4]=3.0/20.0;
00482 
00483       b7[0]=29443841.0/614563906.0;
00484       b7[1]=0.0;
00485       b7[2]=0.0;
00486       b7[3]=77736538.0/692538347.0;
00487       b7[4]=-28693883.0/1125000000.0;
00488       b7[5]=23124283.0/1800000000.0;
00489 
00490       b8[0]=16016141.0/946692911.0;
00491       b8[1]=0.0;
00492       b8[2]=0.0;
00493       b8[3]=61564180.0/158732637.0;
00494       b8[4]=22789713.0/633445777.0;
00495       b8[5]=545815736.0/2771057229.0;
00496       b8[6]=-180193667.0/1043307555.0;
00497 
00498       b9[0]=39632708.0/573591083.0;
00499       b9[1]=0.0;
00500       b9[2]=0.0;
00501       b9[3]=-433636366.0/683701615.0;
00502       b9[4]=-421739975.0/2616292301.0;
00503       b9[5]=100302831.0/723423059.0;
00504       b9[6]=790204164.0/839813087.0;
00505       b9[7]=800635310.0/3783071287.0;
00506 
00507       b10[0]=246121993.0/1340847787.0;
00508       b10[1]=0.0;
00509       b10[2]=0.0;
00510       b10[3]=-37695042795.0/15268766246.0;
00511       b10[4]=-309121744.0/1061227803.0;
00512       b10[5]=-12992083.0/490766935.0;
00513       b10[6]=6005943493.0/2108947869.0;
00514       b10[7]=393006217.0/1396673457.0;
00515       b10[8]=123872331.0/1001029789.0;
00516 
00517       b11[0]=-1028468189.0/846180014.0;
00518       b11[1]=0.0;
00519       b11[2]=0.0;
00520       b11[3]=8478235783.0/508512852.0;
00521       b11[4]=1311729495.0/1432422823.0;
00522       b11[5]=-10304129995.0/1701304382.0;
00523       b11[6]=-48777925059.0/3047939560.0;
00524       b11[7]=15336726248.0/1032824649.0;
00525       b11[8]=-45442868181.0/3398467696.0;
00526       b11[9]=3065993473.0/597172653.0;
00527 
00528       b12[0]=185892177.0/718116043.0;
00529       b12[1]=0.0;
00530       b12[2]=0.0;
00531       b12[3]=-3185094517.0/667107341.0;
00532       b12[4]=-477755414.0/1098053517.0;
00533       b12[5]=-703635378.0/230739211.0;
00534       b12[6]=5731566787.0/1027545527.0;
00535       b12[7]=5232866602.0/850066563.0;
00536       b12[8]=-4093664535.0/808688257.0;
00537       b12[9]=3962137247.0/1805957418.0;
00538       b12[10]=65686358.0/487910083.0;
00539 
00540       b13[0]=403863854.0/491063109.0;
00541       b13[1]=0.0;
00542       b13[2]=0.0;
00543       b13[3]=-5068492393.0/434740067.0;
00544       b13[4]=-411421997.0/543043805.0;
00545       b13[5]=652783627.0/914296604.0;
00546       b13[6]=11173962825.0/925320556.0;
00547       b13[7]=-13158990841.0/6184727034.0;
00548       b13[8]=3936647629.0/1978049680.0;
00549       b13[9]=-160528059.0/685178525.0;
00550       b13[10]=248638103.0/1413531060.0;
00551       b13[11]=0;
00552 
00553       ao.allocate(k2,N);
00554       ao.allocate(k3,N);
00555       ao.allocate(k4,N);
00556       ao.allocate(k5,N);
00557       ao.allocate(k6,N);
00558       ao.allocate(k7,N);
00559       ao.allocate(k8,N);
00560       ao.allocate(k9,N);
00561       ao.allocate(k10,N);
00562       ao.allocate(k11,N);
00563       ao.allocate(k12,N);
00564       ao.allocate(k13,N);
00565       ao.allocate(ytmp,N);
00566 
00567     }
00568       
00569     virtual ~gsl_rk8pd_fast() {
00570 
00571       ao.free(k2);
00572       ao.free(k3);
00573       ao.free(k4);
00574       ao.free(k5);
00575       ao.free(k6);
00576       ao.free(k7);
00577       ao.free(k8);
00578       ao.free(k9);
00579       ao.free(k10);
00580       ao.free(k11);
00581       ao.free(k12);
00582       ao.free(k13);
00583       ao.free(ytmp);
00584     }
00585 
00586     /** 
00587         \brief Perform an integration step
00588 
00589         Given initial value of the n-dimensional function in \c y and
00590         the derivative in \c dydx (which must generally be computed
00591         beforehand) at the point \c x, take a step of size \c h giving
00592         the result in \c yout, the uncertainty in \c yerr, and the new
00593         derivative in \c dydx_out using function \c derivs to
00594         calculate derivatives. The parameters \c yout and \c y and the
00595         parameters \c dydx_out and \c dydx may refer to the same
00596         object.
00597 
00598         \note The value of the parameter \c n should be equal to 
00599         the template parameter \c N.
00600     */
00601     virtual int step(double x, double h, size_t n, vec_t &y, vec_t &dydx, 
00602                      vec_t &yout, vec_t &yerr, vec_t &dydx_out, param_t &pa, 
00603                      func_t &derivs) {
00604       size_t i;
00605       
00606       for (i=0;i<N;i++) {
00607         ytmp[i]=y[i]+b21*h*dydx[i];
00608       }
00609         
00610       derivs(x+ah[0]*h,N,ytmp,k2,pa);
00611 
00612       for (i=0;i<N;i++) {
00613         ytmp[i]=y[i]+h*(b3[0]*dydx[i]+b3[1]*k2[i]);
00614       }
00615       
00616       derivs(x+ah[1]*h,N,ytmp,k3,pa);
00617       
00618       for (i=0;i<N;i++) {
00619         ytmp[i]=y[i]+h*(b4[0]*dydx[i]+b4[2]*k3[i]);
00620       }
00621 
00622       derivs(x+ah[2]*h,N,ytmp,k4,pa);
00623 
00624       for (i=0;i<N;i++) {
00625         ytmp[i]=y[i]+h*(b5[0]*dydx[i]+b5[2]*k3[i]+b5[3]*k4[i]);
00626       }
00627       
00628       derivs(x+ah[3]*h,N,ytmp,k5,pa);
00629       
00630       for (i=0;i<N;i++) {
00631         ytmp[i]=y[i]+h*(b6[0]*dydx[i]+b6[3]*k4[i]+b6[4]*k5[i]);
00632       }
00633       
00634       derivs(x+ah[4]*h,N,ytmp,k6,pa);
00635       
00636       for (i=0;i<N;i++) {
00637         ytmp[i]=y[i]+h*(b7[0]*dydx[i]+b7[3]*k4[i]+b7[4]*k5[i]+b7[5]*k6[i]);
00638       }
00639       
00640       derivs(x+ah[5]*h,N,ytmp,k7,pa);
00641       
00642       for (i=0;i<N;i++) {
00643         ytmp[i]=y[i]+h*(b8[0]*dydx[i]+b8[3]*k4[i]+b8[4]*k5[i]+b8[5]*k6[i]+
00644                         b8[6]*k7[i]);
00645       }
00646       
00647       derivs(x+ah[6]*h,N,ytmp,k8,pa);
00648       
00649       for (i=0;i<N;i++) {
00650         ytmp[i]=y[i]+h*(b9[0]*dydx[i]+b9[3]*k4[i]+b9[4]*k5[i]+b9[5]*k6[i]+
00651                         b9[6]*k7[i]+b9[7]*k8[i]);
00652       }
00653       
00654       derivs(x+ah[7]*h,N,ytmp,k9,pa);
00655       
00656       for (i=0;i<N;i++) {
00657         ytmp[i]=y[i]+h*(b10[0]*dydx[i]+b10[3]*k4[i]+b10[4]*k5[i]+
00658                         b10[5]*k6[i]+b10[6]*k7[i]+b10[7]*k8[i]+
00659                         b10[8]*k9[i]);
00660       }
00661 
00662       derivs(x+ah[8]*h,N,ytmp,k10,pa);
00663       
00664       for (i=0;i<N;i++) {
00665         ytmp[i]=y[i]+h*(b11[0]*dydx[i]+b11[3]*k4[i]+b11[4]*k5[i]+
00666                         b11[5]*k6[i]+b11[6]*k7[i]+b11[7]*k8[i]+
00667                         b11[8]*k9[i]+b11[9]*k10[i]);
00668       }
00669 
00670       derivs(x+ah[9]*h,N,ytmp,k11,pa);
00671       
00672       for (i=0;i<N;i++) {
00673         ytmp[i]=y[i]+h*(b12[0]*dydx[i]+b12[3]*k4[i]+b12[4]*k5[i]+
00674                         b12[5]*k6[i]+b12[6]*k7[i]+b12[7]*k8[i]+
00675                         b12[8]*k9[i]+b12[9]*k10[i]+b12[10]*k11[i]);
00676       }
00677       
00678       derivs(x+h,N,ytmp,k12,pa);
00679       
00680       for (i=0;i<N;i++) {
00681         ytmp[i]=y[i]+h*(b13[0]*dydx[i]+b13[3]*k4[i]+b13[4]*k5[i]+
00682                         b13[5]*k6[i]+b13[6]*k7[i]+b13[7]*k8[i]+
00683                         b13[8]*k9[i]+b13[9]*k10[i]+b13[10]*k11[i]+
00684                         b13[11]*k12[i]);
00685       }
00686 
00687       derivs(x+h,N,ytmp,k13,pa);
00688 
00689       // final sum
00690 
00691       for (i=0;i<N;i++) {
00692         double ksum8= Abar[0]*dydx[i]+Abar[5]*k6[i]+Abar[6]*k7[i]+
00693           Abar[7]*k8[i]+Abar[8]*k9[i]+Abar[9]*k10[i]+
00694           Abar[10]*k11[i]+Abar[11]*k12[i]+Abar[12]*k13[i];
00695 
00696         yout[i]=y[i]+h*ksum8;
00697       }
00698       
00699       // We put this before the last function evaluation, in contrast
00700       // to the GSL version, so that the dydx[i] that appears in the
00701       // for loop below isn't modified by the subsequent derivative
00702       // evaluation using dydx_out. (The user could have given the
00703       // same vector for both)
00704       for (i=0;i<N;i++) {
00705 
00706         double ksum8=Abar[0]*dydx[i]+Abar[5]*k6[i]+Abar[6]*k7[i]+
00707           Abar[7]*k8[i]+Abar[8]*k9[i]+Abar[9]*k10[i]+
00708           Abar[10]*k11[i]+Abar[11]*k12[i]+Abar[12]*k13[i];
00709         double ksum7=A[0]*dydx[i]+A[5]*k6[i]+A[6]*k7[i]+A[7]*k8[i]+
00710           A[8]*k9[i]+A[9]*k10[i]+A[10]*k11[i]+A[11]*k12[i];
00711         
00712         yerr[i]=h*(ksum7-ksum8);
00713       }
00714 
00715       derivs(x+h,N,yout,dydx_out,pa);
00716       
00717       return 0;
00718     }
00719     
00720   };
00721 
00722 #ifndef DOXYGENP
00723 }
00724 #endif
00725 
00726 #endif

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page