1#ifndef STAN_MATH_PRIM_FUNCTOR_ODE_RK45_HPP
2#define STAN_MATH_PRIM_FUNCTOR_ODE_RK45_HPP
9#include <boost/numeric/odeint.hpp>
55template <
typename F,
typename T_y0,
typename T_t0,
typename T_ts,
56 typename... Args, require_eigen_vector_t<T_y0>* =
nullptr>
60 T_t0 t0,
const std::vector<T_ts>& ts,
61 double relative_tolerance,
double absolute_tolerance,
62 long int max_num_steps,
63 std::ostream* msgs,
const Args&... args) {
64 using boost::numeric::odeint::integrate_times;
65 using boost::numeric::odeint::make_dense_output;
66 using boost::numeric::odeint::max_step_checker;
67 using boost::numeric::odeint::no_progress_error;
68 using boost::numeric::odeint::runge_kutta_dopri5;
69 using boost::numeric::odeint::vector_space_algebra;
73 Eigen::Matrix<T_y0_t0, Eigen::Dynamic, 1> y0
74 = y0_arg.template cast<T_y0_t0>();
80 std::tuple<ref_type_t<Args>...> args_ref_tuple(args...);
83 [&](
const auto&... args_ref) {
85 std::vector<int> unused_temp{
87 (
check_finite(function_name,
"ode parameters and data", args_ref),
95 check_less(function_name,
"initial time", t0, ts[0]);
106 [&](
const auto&... args_ref) {
113 std::vector<double> ts_vec(ts.size() + 1);
115 for (
size_t i = 0; i < ts.size(); ++i)
118 std::vector<Eigen::Matrix<return_t, Eigen::Dynamic, 1>> y;
119 y.reserve(ts.size());
120 bool observer_initial_recorded =
false;
121 size_t time_index = 0;
125 auto filtered_observer
126 = [&](
const std::vector<double>& coupled_state,
double t) ->
void {
127 if (!observer_initial_recorded) {
128 observer_initial_recorded =
true;
132 [&](
const auto&... args_ref) {
134 f, coupled_state, y0, t0, ts[time_index], msgs, args_ref...));
141 std::vector<double> initial_coupled_state = coupled_system.initial_state();
143 const double step_size = 0.1;
146 make_dense_output(absolute_tolerance, relative_tolerance,
147 runge_kutta_dopri5<std::vector<double>,
double,
148 std::vector<double>,
double>()),
149 std::ref(coupled_system), initial_coupled_state, std::begin(ts_vec),
150 std::end(ts_vec), step_size, filtered_observer,
151 max_step_checker(max_num_steps));
152 }
catch (
const no_progress_error&
e) {
154 "Failed to integrate to next output time (",
155 ") in less than max_num_steps steps");
197template <
typename F,
typename T_y0,
typename T_t0,
typename T_ts,
202 const std::vector<T_ts>& ts,
double relative_tolerance,
203 double absolute_tolerance,
204 long int max_num_steps,
205 std::ostream* msgs,
const Args&... args) {
207 relative_tolerance, absolute_tolerance,
208 max_num_steps, msgs, args...);
243template <
typename F,
typename T_y0,
typename T_t0,
typename T_ts,
247ode_rk45(
const F& f,
const T_y0& y0, T_t0 t0,
const std::vector<T_ts>& ts,
248 std::ostream* msgs,
const Args&... args) {
249 double relative_tolerance = 1
e-6;
250 double absolute_tolerance = 1
e-6;
251 long int max_num_steps = 1e6;
254 absolute_tolerance, max_num_steps, msgs, args...);
require_t< is_eigen_vector< std::decay_t< T > > > require_eigen_vector_t
Require type satisfies is_eigen_vector.
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
std::vector< Eigen::Matrix< stan::return_type_t< T_y0, T_t0, T_ts, Args... >, Eigen::Dynamic, 1 > > ode_rk45_tol_impl(const char *function_name, const F &f, const T_y0 &y0_arg, T_t0 t0, const std::vector< T_ts > &ts, double relative_tolerance, double absolute_tolerance, long int max_num_steps, std::ostream *msgs, const Args &... args)
Solve the ODE initial value problem y' = f(t, y), y(t0) = y0 at a set of times, { t1,...
static constexpr double e()
Return the base of the natural logarithm.
std::vector< Eigen::Matrix< stan::return_type_t< T_y0, T_t0, T_ts, Args... >, Eigen::Dynamic, 1 > > ode_rk45(const F &f, const T_y0 &y0, T_t0 t0, const std::vector< T_ts > &ts, std::ostream *msgs, const Args &... args)
Solve the ODE initial value problem y' = f(t, y), y(t0) = y0 at a set of times, { t1,...
T value_of(const fvar< T > &v)
Return the value of the specified variable.
void throw_domain_error(const char *function, const char *name, const T &y, const char *msg1, const char *msg2)
Throw a domain error with a consistently formatted message.
std::vector< Eigen::Matrix< stan::return_type_t< T_y0, T_t0, T_ts, Args... >, Eigen::Dynamic, 1 > > ode_rk45_tol(const F &f, const T_y0 &y0_arg, T_t0 t0, const std::vector< T_ts > &ts, double relative_tolerance, double absolute_tolerance, long int max_num_steps, std::ostream *msgs, const Args &... args)
Solve the ODE initial value problem y' = f(t, y), y(t0) = y0 at a set of times, { t1,...
void check_finite(const char *function, const char *name, const T_y &y)
Return true if all values in y are finite.
Eigen::VectorXd ode_store_sensitivities(const F &f, const std::vector< double > &coupled_state, const Eigen::Matrix< T_y0_t0, Eigen::Dynamic, 1 > &y0, T_t0 t0, T_t t, std::ostream *msgs, const Args &... args)
When all arguments are arithmetic, there are no sensitivities to store, so the function just returns ...
void check_nonzero_size(const char *function, const char *name, const T_y &y)
Check if the specified matrix/vector is of non-zero size.
void check_positive(const char *function, const char *name, const T_y &y)
Check if y is positive.
void check_sorted(const char *function, const char *name, const EigVec &y)
Check if the specified vector is sorted into increasing order (repeated values are okay).
void check_less(const char *function, const char *name, const T_y &y, const T_high &high, Idxs... idxs)
Throw an exception if y is not strictly less than high.
constexpr decltype(auto) apply(F &&f, Tuple &&t, PreArgs &&... pre_args)
void check_positive_finite(const char *function, const char *name, const T_y &y)
Check if y is positive and finite.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...