gsl_rk8pd.h

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