void ode_evaluate( CppAD::vector<Float> &x , size_t m , CppAD::vector<Float> &fm ) { typedef CppAD::vector<Float> Vector; size_t n = x.size(); size_t ell; CPPAD_ASSERT_KNOWN( m == 0 || m == 1, "ode_evaluate: m is not zero or one" ); CPPAD_ASSERT_KNOWN( ((m==0) & (fm.size()==n)) || ((m==1) & (fm.size()==n*n)), "ode_evaluate: the size of fm is not correct" ); if( m == 0 ) ell = n; else ell = n + n * n; // set up the case we are integrating Float ti = 0.; Float tf = 1.; Float smin = 1e-5; Float smax = 1.; Float scur = 1.; Float erel = 0.; vector<Float> yi(ell), eabs(ell); size_t i, j; for(i = 0; i < ell; i++) { eabs[i] = 1e-10; if( i < n ) yi[i] = 1.; else yi[i] = 0.; } // return values Vector yf(ell), ef(ell), maxabs(ell); size_t nstep; // construct ode method for taking one step ode_evaluate_method<Float> method(m, x); // solve differential equation yf = OdeErrControl(method, ti, tf, yi, smin, smax, scur, eabs, erel, ef, maxabs, nstep); if( m == 0 ) { for(i = 0; i < n; i++) fm[i] = yf[i]; } else { for(i = 0; i < n; i++) for(j = 0; j < n; j++) fm[i * n + j] = yf[n + i * n + j]; } return; }
bool OdeErrMaxabs(void) { bool ok = true; // initial return value CppAD::vector<double> w(2); w[0] = 10.; w[1] = 1.; Method method(w); CppAD::vector<double> xi(2); xi[0] = 1.; xi[1] = 0.; CppAD::vector<double> eabs(2); eabs[0] = 0.; eabs[1] = 0.; CppAD::vector<double> ef(2); CppAD::vector<double> xf(2); CppAD::vector<double> maxabs(2); double ti = 0.; double tf = 1.; double smin = .5; double smax = 1.; double scur = .5; double erel = 1e-4; bool accurate = false; while( ! accurate ) { xf = OdeErrControl(method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs); accurate = true; size_t i; for(i = 0; i < 2; i++) accurate &= ef[i] <= erel * maxabs[i]; if( ! accurate ) smin = smin / 2; } double x0 = exp(-w[0]*tf); ok &= CppAD::NearEqual(x0, xf[0], erel, 0.); ok &= CppAD::NearEqual(0., ef[0], erel, erel); double x1 = w[0] * (exp(-w[0]*tf) - exp(-w[1]*tf))/(w[1] - w[0]); ok &= CppAD::NearEqual(x1, xf[1], erel, 0.); ok &= CppAD::NearEqual(0., ef[1], erel, erel); return ok; }
bool OdeErrControl_three(void) { bool ok = true; // initial return value double alpha = 10.; Method_three method(alpha); CppAD::vector<double> xi(2); xi[0] = 1.; xi[1] = 0.; CppAD::vector<double> eabs(2); eabs[0] = 1e-4; eabs[1] = 1e-4; // inputs double ti = 0.; double tf = 1.; double smin = 1e-4; double smax = 1.; double scur = 1.; double erel = 0.; // outputs CppAD::vector<double> ef(2); CppAD::vector<double> xf(2); CppAD::vector<double> maxabs(2); size_t nstep; xf = OdeErrControl(method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep); double x0 = exp( alpha * tf * tf ); ok &= CppAD::NearEqual(x0, xf[0], 1e-4, 1e-4); ok &= CppAD::NearEqual(0., ef[0], 1e-4, 1e-4); double root_pi = sqrt( 4. * atan(1.)); double root_alpha = sqrt( alpha ); double x1 = CppAD::erf(alpha * tf) * root_pi / (2 * root_alpha); ok &= CppAD::NearEqual(x1, xf[1], 1e-4, 1e-4); ok &= CppAD::NearEqual(0., ef[1], 1e-4, 1e-4); ok &= method.F.was_negative(); return ok; }
Vector OdeErrControl( Method &method, const Scalar &ti , const Scalar &tf , const Vector &xi , const Scalar &smin , const Scalar &smax , Scalar &scur , const Vector &eabs , const Scalar &erel , Vector &ef , Vector &maxabs) { size_t nstep; return OdeErrControl( method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep ); }
bool OdeErrControl_two(void) { bool ok = true; // initial return value CppAD::vector<double> w(2); w[0] = 10.; w[1] = 1.; Method_two method(w); CppAD::vector<double> xi(2); xi[0] = 1.; xi[1] = 0.; CppAD::vector<double> eabs(2); eabs[0] = 1e-4; eabs[1] = 1e-4; // inputs double ti = 0.; double tf = 1.; double smin = 1e-4; double smax = 1.; double scur = .5; double erel = 0.; // outputs CppAD::vector<double> ef(2); CppAD::vector<double> xf(2); CppAD::vector<double> maxabs(2); size_t nstep; xf = OdeErrControl(method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep); double x0 = exp(-w[0]*tf); ok &= CppAD::NearEqual(x0, xf[0], 1e-4, 1e-4); ok &= CppAD::NearEqual(0., ef[0], 1e-4, 1e-4); double x1 = w[0] * (exp(-w[0]*tf) - exp(-w[1]*tf))/(w[1] - w[0]); ok &= CppAD::NearEqual(x1, xf[1], 1e-4, 1e-4); ok &= CppAD::NearEqual(0., ef[1], 1e-4, 1e-4); return ok; }
bool OdeErrControl_one(void) { bool ok = true; // initial return value // Runge45 should yield exact results for x_i (t) = t^(i+1), i < 4 size_t n = 6; // construct method for n component solution Method_one method(n); // inputs to OdeErrControl double ti = 0.; double tf = .9; double smin = 1e-2; double smax = 1.; double scur = .5; double erel = 1e-7; CppAD::vector<double> xi(n); CppAD::vector<double> eabs(n); size_t i; for(i = 0; i < n; i++) { xi[i] = 0.; eabs[i] = 0.; } // outputs from OdeErrControl CppAD::vector<double> ef(n); CppAD::vector<double> xf(n); xf = OdeErrControl(method, ti, tf, xi, smin, smax, scur, eabs, erel, ef); double check = 1.; for(i = 0; i < n; i++) { check *= tf; ok &= CppAD::NearEqual(check, xf[i], erel, 0.); } return ok; }
bool OdeErrControl_four(void) { bool ok = true; // initial return value // construct method for n component solution size_t n = 6; Method_four method(n); // inputs to OdeErrControl // special case where scur is converted to ti - tf // (so it is not equal to smin) double ti = 0.; double tf = .9; double smin = .8; double smax = 1.; double scur = smin; double erel = 1e-7; CppAD::vector<double> xi(n); CppAD::vector<double> eabs(n); size_t i; for(i = 0; i < n; i++) { xi[i] = 0.; eabs[i] = 0.; } // outputs from OdeErrControl CppAD::vector<double> ef(n); CppAD::vector<double> xf(n); xf = OdeErrControl(method, ti, tf, xi, smin, smax, scur, eabs, erel, ef); // check that Fun_four always returning nan results in nan for(i = 0; i < n; i++) { ok &= CppAD::isnan(xf[i]); ok &= CppAD::isnan(ef[i]); } return ok; }