struct Ross_constants { static const Doub c2,c3,c4,bet2p,bet3p,bet4p,d1,d2,d3,d4,a21,a31,a32, a41,a42,a43,a51,a52,a53,a54,c21,c31,c32,c41,c42,c43,c51,c52, c53,c54,c61,c62,c63,c64,c65,gam,d21,d22,d23,d24,d25,d31,d32, d33,d34,d35; }; const Doub Ross_constants::c2=0.386; const Doub Ross_constants::c3=0.21; const Doub Ross_constants::c4=0.63; const Doub Ross_constants::bet2p=0.0317; const Doub Ross_constants::bet3p=0.0635; const Doub Ross_constants::bet4p=0.3438; const Doub Ross_constants::d1= 0.2500000000000000e+00; const Doub Ross_constants::d2=-0.1043000000000000e+00; const Doub Ross_constants::d3= 0.1035000000000000e+00; const Doub Ross_constants::d4=-0.3620000000000023e-01; const Doub Ross_constants::a21= 0.1544000000000000e+01; const Doub Ross_constants::a31= 0.9466785280815826e+00; const Doub Ross_constants::a32= 0.2557011698983284e+00; const Doub Ross_constants::a41= 0.3314825187068521e+01; const Doub Ross_constants::a42= 0.2896124015972201e+01; const Doub Ross_constants::a43= 0.9986419139977817e+00; const Doub Ross_constants::a51= 0.1221224509226641e+01; const Doub Ross_constants::a52= 0.6019134481288629e+01; const Doub Ross_constants::a53= 0.1253708332932087e+02; const Doub Ross_constants::a54=-0.6878860361058950e+00; const Doub Ross_constants::c21=-0.5668800000000000e+01; const Doub Ross_constants::c31=-0.2430093356833875e+01; const Doub Ross_constants::c32=-0.2063599157091915e+00; const Doub Ross_constants::c41=-0.1073529058151375e+00; const Doub Ross_constants::c42=-0.9594562251023355e+01; const Doub Ross_constants::c43=-0.2047028614809616e+02; const Doub Ross_constants::c51= 0.7496443313967647e+01; const Doub Ross_constants::c52=-0.1024680431464352e+02; const Doub Ross_constants::c53=-0.3399990352819905e+02; const Doub Ross_constants::c54= 0.1170890893206160e+02; const Doub Ross_constants::c61= 0.8083246795921522e+01; const Doub Ross_constants::c62=-0.7981132988064893e+01; const Doub Ross_constants::c63=-0.3152159432874371e+02; const Doub Ross_constants::c64= 0.1631930543123136e+02; const Doub Ross_constants::c65=-0.6058818238834054e+01; const Doub Ross_constants::gam= 0.2500000000000000e+00; const Doub Ross_constants::d21= 0.1012623508344586e+02; const Doub Ross_constants::d22=-0.7487995877610167e+01; const Doub Ross_constants::d23=-0.3480091861555747e+02; const Doub Ross_constants::d24=-0.7992771707568823e+01; const Doub Ross_constants::d25= 0.1025137723295662e+01; const Doub Ross_constants::d31=-0.6762803392801253e+00; const Doub Ross_constants::d32= 0.6087714651680015e+01; const Doub Ross_constants::d33= 0.1643084320892478e+02; const Doub Ross_constants::d34= 0.2476722511418386e+02; const Doub Ross_constants::d35=-0.6594389125716872e+01; template struct StepperRoss : StepperBase, Ross_constants { typedef D Dtype; MatDoub dfdy; VecDoub dfdx; VecDoub k1,k2,k3,k4,k5,k6; VecDoub cont1,cont2,cont3,cont4; MatDoub a; StepperRoss(VecDoub_IO &yy, VecDoub_IO &dydxx, Doub &xx, const Doub atoll, const Doub rtoll, bool dens); void step(const Doub htry,D &derivs); void dy(const Doub h,D &derivs); void prepare_dense(const Doub h,VecDoub_I &dydxnew); Doub dense_out(const Int i, const Doub x, const Doub h); Doub error(); struct Controller { Doub hnext; bool reject; bool first_step; Doub errold; Doub hold; Controller(); bool success(Doub err, Doub &h); }; Controller con; }; template StepperRoss::StepperRoss(VecDoub_IO &yy, VecDoub_IO &dydxx, Doub &xx, const Doub atoll,const Doub rtoll, bool dens) : StepperBase(yy,dydxx,xx,atoll,rtoll,dens),dfdy(n,n),dfdx(n),k1(n),k2(n), k3(n),k4(n),k5(n),k6(n),cont1(n),cont2(n),cont3(n),cont4(n),a(n,n) { EPS=numeric_limits::epsilon(); } template void StepperRoss::step(const Doub htry,D &derivs) { VecDoub dydxnew(n); Doub h=htry; derivs.jacobian(x,y,dfdx,dfdy); for (;;) { dy(h,derivs); Doub err=error(); if (con.success(err,h)) break; if (abs(h) <= abs(x)*EPS) throw("stepsize underflow in StepperRoss"); } derivs(x+h,yout,dydxnew); if (dense) prepare_dense(h,dydxnew); dydx=dydxnew; y=yout; xold=x; x += (hdid=h); hnext=con.hnext; } template void StepperRoss::dy(const Doub h,D &derivs) { VecDoub ytemp(n),dydxnew(n); Int i; for (i=0;i void StepperRoss::prepare_dense(const Doub h,VecDoub_I &dydxnew) { for (Int i=0;i Doub StepperRoss::dense_out(const Int i,const Doub x,const Doub h) { Doub s=(x-xold)/h; Doub s1=1.0-s; return cont1[i]*s1+s*(cont2[i]+s1*(cont3[i]+s*cont4[i])); } template Doub StepperRoss::error() { Doub err=0.0,sk; for (Int i=0;i StepperRoss::Controller::Controller() : reject(false), first_step(true) {} template bool StepperRoss::Controller::success(Doub err, Doub &h) { static const Doub safe=0.9,fac1=5.0,fac2=1.0/6.0; Doub fac=MAX(fac2,MIN(fac1,pow(err,0.25)/safe)); Doub hnew=h/fac; if (err <= 1.0) { if (!first_step) { Doub facpred=(hold/h)*pow(err*err/errold,0.25)/safe; facpred=MAX(fac2,MIN(fac1,facpred)); fac=MAX(fac,facpred); hnew=h/fac; } first_step=false; hold=h; errold=MAX(0.01,err); if (reject) hnew=(h >= 0.0 ? MIN(hnew,h) : MAX(hnew,h)); hnext=hnew; reject=false; return true; } else { h=hnew; reject=true; return false; } }