33
44#include < stan/math/prim/meta.hpp>
55#include < stan/math/prim/functor/coupled_ode_system.hpp>
6- #include < stan/math/prim/fun /ode_store_sensitivities.hpp>
6+ #include < stan/math/prim/functor /ode_store_sensitivities.hpp>
77#include < boost/numeric/odeint/external/eigen/eigen_algebra.hpp>
88#include < boost/numeric/odeint.hpp>
99#include < ostream>
1212namespace stan {
1313namespace math {
1414
15+ /* *
16+ * Solve the ODE initial value problem y' = f(t, y), y(t0) = y0 at a set of
17+ * times, { t1, t2, t3, ... } using the non-stiff Runge-Kutta 45 solver in Boost
18+ * with a relative tolerance of 1e-10, an absolute tolerance of 1e-10, and
19+ * taking a maximum of 1e8 steps.
20+ *
21+ * If the system of equations is stiff, <code>ode_bdf</code> will likely be
22+ * faster.
23+ *
24+ * \p f must define an operator() with the signature as:
25+ * template<typename T_t, typename T_y, typename... T_Args>
26+ * Eigen::Matrix<stan::return_type_t<T_t, T_y, T_Args...>, Eigen::Dynamic, 1>
27+ * operator()(const T_t& t, const Eigen::Matrix<T_y, Eigen::Dynamic, 1>& y,
28+ * std::ostream* msgs, const T_Args&... args);
29+ *
30+ * t is the time, y is the state, msgs is a stream for error messages, and args
31+ * are optional arguments passed to the ODE solve function (which are passed
32+ * through to \p f without modification).
33+ *
34+ * @tparam F Type of ODE right hand side
35+ * @tparam T_0 Type of initial time
36+ * @tparam T_ts Type of output times
37+ * @tparam T_Args Types of pass-through parameters
38+ *
39+ * @param f Right hand side of the ODE
40+ * @param y0 Initial state
41+ * @param t0 Initial time
42+ * @param ts Times at which to solve the ODE at. All values must be sorted and
43+ * not less than t0.
44+ * @param relative_tolerance Relative tolerance passed to CVODES
45+ * @param absolute_tolerance Absolute tolerance passed to CVODES
46+ * @param max_num_steps Upper limit on the number of integration steps to
47+ * take between each output (error if exceeded)
48+ * @param[in, out] msgs the print stream for warning messages
49+ * @param args Extra arguments passed unmodified through to ODE right hand side
50+ * @return Solution to ODE at times \p ts
51+ */
1552template <typename F, typename T_initial, typename T_t0, typename T_ts,
1653 typename ... Args>
1754std::vector<Eigen::Matrix<stan::return_type_t <T_initial, Args...>, Eigen::Dynamic, 1 >>
1855ode_rk45 (const F& f, const Eigen::Matrix<T_initial, Eigen::Dynamic, 1 >& y0, double t0,
1956 const std::vector<double >& ts, std::ostream* msgs,
2057 const Args&... args) {
21- double relative_tolerance = 1e-6 ;
22- double absolute_tolerance = 1e-6 ;
23- long int max_num_steps = 1e6 ;
58+ double relative_tolerance = 1e-10 ;
59+ double absolute_tolerance = 1e-10 ;
60+ long int max_num_steps = 1e8 ;
2461
2562 return ode_rk45_tol (f, y0, t0, ts, relative_tolerance, absolute_tolerance,
2663 max_num_steps, msgs, args...);
2764}
2865
66+ /* *
67+ * Solve the ODE initial value problem y' = f(t, y), y(t0) = y0 at a set of
68+ * times, { t1, t2, t3, ... } using the non-stiff Runge-Kutta 45 solver in Boost
69+ * with a relative tolerance of 1e-10, an absolute tolerance of 1e-10, and
70+ * taking a maximum of 1e8 steps.
71+ *
72+ * If the system of equations is stiff, <code>ode_bdf</code> will likely be
73+ * faster.
74+ *
75+ * \p f must define an operator() with the signature as:
76+ * template<typename T_t, typename T_y, typename... T_Args>
77+ * Eigen::Matrix<stan::return_type_t<T_t, T_y, T_Args...>, Eigen::Dynamic, 1>
78+ * operator()(const T_t& t, const Eigen::Matrix<T_y, Eigen::Dynamic, 1>& y,
79+ * std::ostream* msgs, const T_Args&... args);
80+ *
81+ * t is the time, y is the state, msgs is a stream for error messages, and args
82+ * are optional arguments passed to the ODE solve function (which are passed
83+ * through to \p f without modification).
84+ *
85+ * @tparam F Type of ODE right hand side
86+ * @tparam T_0 Type of initial time
87+ * @tparam T_ts Type of output times
88+ * @tparam T_Args Types of pass-through parameters
89+ *
90+ * @param f Right hand side of the ODE
91+ * @param y0 Initial state
92+ * @param t0 Initial time
93+ * @param ts Times at which to solve the ODE at. All values must be sorted and
94+ * not less than t0.
95+ * @param relative_tolerance Relative tolerance passed to CVODES
96+ * @param absolute_tolerance Absolute tolerance passed to CVODES
97+ * @param max_num_steps Upper limit on the number of integration steps to
98+ * take between each output (error if exceeded)
99+ * @param[in, out] msgs the print stream for warning messages
100+ * @param args Extra arguments passed unmodified through to ODE right hand side
101+ * @return Solution to ODE at times \p ts
102+ */
29103template <typename F, typename T_initial, typename T_t0, typename T_ts,
30104 typename ... Args>
31105std::vector<Eigen::Matrix<stan::return_type_t <T_initial, T_t0, T_ts, Args...>, Eigen::Dynamic, 1 >>
@@ -88,6 +162,8 @@ ode_rk45_tol(const F& f, const Eigen::Matrix<T_initial, Eigen::Dynamic, 1>& y0_a
88162 bool observer_initial_recorded = false ;
89163 size_t time_index = 0 ;
90164
165+ max_step_checker step_checker (max_num_steps);
166+
91167 // avoid recording of the initial state which is included by the
92168 // conventions of odeint in the output
93169 auto filtered_observer
@@ -99,6 +175,7 @@ ode_rk45_tol(const F& f, const Eigen::Matrix<T_initial, Eigen::Dynamic, 1>& y0_a
99175 y.emplace_back (ode_store_sensitivities (f, coupled_state, y0,
100176 t0, ts[time_index],
101177 msgs, args...));
178+ step_checker.reset ();
102179 time_index++;
103180 };
104181
@@ -113,7 +190,7 @@ ode_rk45_tol(const F& f, const Eigen::Matrix<T_initial, Eigen::Dynamic, 1>& y0_a
113190 vector_space_algebra>()),
114191 std::ref (coupled_system), initial_coupled_state,
115192 std::begin (ts_vec), std::end (ts_vec), step_size, filtered_observer,
116- max_step_checker (max_num_steps) );
193+ step_checker );
117194
118195 return y;
119196}
0 commit comments