boost odeint:使用自定义 class 和矢量 space 代数控制步进器
boost odeint: controlled stepper with custom class and vector space algebra
我正在使用 boost odeint 来演化一个微分方程。
时间和值由围绕普通数字的包装器 class 给出(进行高斯误差传播)。
using Time = Number<double>;
using Value = Number<double>;
状态及其导数由带有声明
的自定义class给出
class State : boost::addable<State>, boost::multipliable<State, Time>, boost::dividable<State>
{
public:
void Add(Group const& group, Value alpha);
Value Get(Group const& group) const;
State& operator*=(Time const& time);
State& operator+=(State const& state);
State& operator/=(State const& state);
State abs() const;
Value norm_inf() const;
private:
std::map<Group, Value> map_;
};
State abs(State const& state);
namespace boost
{
namespace numeric
{
namespace odeint
{
template<>
struct boost::numeric::odeint::vector_space_norm_inf<State> {
using result_type = Value;
result_type operator()(State const& state) const;
};
}
}
}
using Derivative = State;
我将 Runge-Kutta-Dopri-5 步进器与矢量 space 代数一起使用
using Stepper = boost::numeric::odeint::runge_kutta_dopri5<State, Value, Derivative, Time, boost::numeric::odeint::vector_space_algebra>;
而且我整个人都这么想
auto start_state = GetStart();
auto system = GetSystem();
auto min = GetMin();
auto max = GetMax();
auto dt = GetDt;
auto observer = GetObserver();
auto stepper = boost::numeric::odeint::make_controlled<Stepper>(1e-6, 1e-6);
boost::numeric::odeint::integrate_adaptive(Stepper(), system, start_state, min, max, dt, observer);
这很有魅力。但是您可能会注意到,我没有使用我在倒数第二行中定义的受控步进器,而是使用默认步进器。当我尝试在最后一行中使用 stepper
变量而不是默认的 Stepper()
时,出现以下编译错误:
In file included from /home/me/Integrate.cpp:2:
In file included from /usr/include/boost/numeric/odeint.hpp:35:
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:85:17: error: no matching constructor for initialization of 'typename operations_type::rel_error<value_type>' (aka 'rel_error<me::Number<double> >')
typename operations_type::template rel_error< value_type >( m_eps_abs , m_eps_rel , m_a_x , m_a_dxdt * abs(get_unit_value( dt )) ) );
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:768:50: note: in instantiation of function template specialization 'odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>::error<me::State, me::State, me::State, me::Number<double> >' requested here
value_type max_rel_err = m_error_checker.error( m_stepper.algebra() , in , dxdt_in , m_xerr.m_v , dt );
^
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:716:38: note: in instantiation of function template specialization 'odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>::try_step<(lambda at /home/me/Integrate.cpp:28:19), me::State, me::State, me::State, me::State>' requested here
controlled_step_result res = try_step( system , x , dxdt , t , m_xnew.m_v , m_dxdtnew.m_v , dt );
^
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:899:16: note: in instantiation of function template specialization 'odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>::try_step<(lambda at /home/me/Integrate.cpp:28:19), me::State, me::State>' requested here
return try_step( system , x , m_dxdt.m_v , t , dt );
^
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:617:16: note: in instantiation of function template specialization 'odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>::try_step_v1<(lambda at /home/me/Integrate.cpp:28:19), me::State>' requested here
return try_step_v1( system , x , t , dt );
^
/usr/include/boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp:103:22: note: in instantiation of function template specialization 'odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>::try_step<(lambda at /home/me/Integrate.cpp:28:19), me::State>' requested here
res = st.try_step( system , start_state , start_time , dt );
^
/usr/include/boost/numeric/odeint/integrate/integrate_adaptive.hpp:42:20: note: in instantiation of function template specialization 'odeint::detail::integrate_adaptive<odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>, (lambda at /home/me/Integrate.cpp:28:19), me::State, me::Number<double>, (lambda at /home/me/Integrate.cpp:48:21)>' requested here
return detail::integrate_adaptive(
^
/usr/include/boost/numeric/odeint/algebra/default_operations.hpp:435:9: note: candidate constructor not viable: no known conversion from 'me::State' to 'me::Number<double>' for 4th argument
rel_error( Fac1 eps_abs , Fac1 eps_rel , Fac1 a_x , Fac1 a_dxdt )
^
/usr/include/boost/numeric/odeint/algebra/default_operations.hpp:431:12: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 4 were provided
struct rel_error
^
/usr/include/boost/numeric/odeint/algebra/default_operations.hpp:431:12: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 4 were provided
我可以看到 odeint::rel_error<me::Number<double>>
应该是 Number
类型,但是乘积 m_a_dxdt * abs(get_unit_value( dt ))
用作 rel_error
的第 4 个参数构造函数是 State
类型。
我假设我在为 State
class 实现向量 space 代数时犯了一个错误,但我找不到我在哪里犯了错误。
如果我用普通 double
替换时间和值类型,错误检查器将再次工作。
odeint指令好像有错误。
如果 abs
函数的 return 类型是 Value
而不是人们天真地认为它是 State
,那么编译错误就会消失。
我正在使用 boost odeint 来演化一个微分方程。 时间和值由围绕普通数字的包装器 class 给出(进行高斯误差传播)。
using Time = Number<double>;
using Value = Number<double>;
状态及其导数由带有声明
的自定义class给出class State : boost::addable<State>, boost::multipliable<State, Time>, boost::dividable<State>
{
public:
void Add(Group const& group, Value alpha);
Value Get(Group const& group) const;
State& operator*=(Time const& time);
State& operator+=(State const& state);
State& operator/=(State const& state);
State abs() const;
Value norm_inf() const;
private:
std::map<Group, Value> map_;
};
State abs(State const& state);
namespace boost
{
namespace numeric
{
namespace odeint
{
template<>
struct boost::numeric::odeint::vector_space_norm_inf<State> {
using result_type = Value;
result_type operator()(State const& state) const;
};
}
}
}
using Derivative = State;
我将 Runge-Kutta-Dopri-5 步进器与矢量 space 代数一起使用
using Stepper = boost::numeric::odeint::runge_kutta_dopri5<State, Value, Derivative, Time, boost::numeric::odeint::vector_space_algebra>;
而且我整个人都这么想
auto start_state = GetStart();
auto system = GetSystem();
auto min = GetMin();
auto max = GetMax();
auto dt = GetDt;
auto observer = GetObserver();
auto stepper = boost::numeric::odeint::make_controlled<Stepper>(1e-6, 1e-6);
boost::numeric::odeint::integrate_adaptive(Stepper(), system, start_state, min, max, dt, observer);
这很有魅力。但是您可能会注意到,我没有使用我在倒数第二行中定义的受控步进器,而是使用默认步进器。当我尝试在最后一行中使用 stepper
变量而不是默认的 Stepper()
时,出现以下编译错误:
In file included from /home/me/Integrate.cpp:2:
In file included from /usr/include/boost/numeric/odeint.hpp:35:
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:85:17: error: no matching constructor for initialization of 'typename operations_type::rel_error<value_type>' (aka 'rel_error<me::Number<double> >')
typename operations_type::template rel_error< value_type >( m_eps_abs , m_eps_rel , m_a_x , m_a_dxdt * abs(get_unit_value( dt )) ) );
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:768:50: note: in instantiation of function template specialization 'odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>::error<me::State, me::State, me::State, me::Number<double> >' requested here
value_type max_rel_err = m_error_checker.error( m_stepper.algebra() , in , dxdt_in , m_xerr.m_v , dt );
^
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:716:38: note: in instantiation of function template specialization 'odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>::try_step<(lambda at /home/me/Integrate.cpp:28:19), me::State, me::State, me::State, me::State>' requested here
controlled_step_result res = try_step( system , x , dxdt , t , m_xnew.m_v , m_dxdtnew.m_v , dt );
^
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:899:16: note: in instantiation of function template specialization 'odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>::try_step<(lambda at /home/me/Integrate.cpp:28:19), me::State, me::State>' requested here
return try_step( system , x , m_dxdt.m_v , t , dt );
^
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:617:16: note: in instantiation of function template specialization 'odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>::try_step_v1<(lambda at /home/me/Integrate.cpp:28:19), me::State>' requested here
return try_step_v1( system , x , t , dt );
^
/usr/include/boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp:103:22: note: in instantiation of function template specialization 'odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>::try_step<(lambda at /home/me/Integrate.cpp:28:19), me::State>' requested here
res = st.try_step( system , start_state , start_time , dt );
^
/usr/include/boost/numeric/odeint/integrate/integrate_adaptive.hpp:42:20: note: in instantiation of function template specialization 'odeint::detail::integrate_adaptive<odeint::controlled_runge_kutta<odeint::runge_kutta_dopri5<me::State, me::Number<double>, me::State, me::Number<double>, odeint::vector_space_algebra, odeint::default_operations, odeint::initially_resizer>, odeint::default_error_checker<me::Number<double>, odeint::vector_space_algebra, odeint::default_operations>, odeint::default_step_adjuster<me::Number<double>, me::Number<double> >, odeint::initially_resizer, odeint::explicit_error_stepper_fsal_tag>, (lambda at /home/me/Integrate.cpp:28:19), me::State, me::Number<double>, (lambda at /home/me/Integrate.cpp:48:21)>' requested here
return detail::integrate_adaptive(
^
/usr/include/boost/numeric/odeint/algebra/default_operations.hpp:435:9: note: candidate constructor not viable: no known conversion from 'me::State' to 'me::Number<double>' for 4th argument
rel_error( Fac1 eps_abs , Fac1 eps_rel , Fac1 a_x , Fac1 a_dxdt )
^
/usr/include/boost/numeric/odeint/algebra/default_operations.hpp:431:12: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 4 were provided
struct rel_error
^
/usr/include/boost/numeric/odeint/algebra/default_operations.hpp:431:12: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 4 were provided
我可以看到 odeint::rel_error<me::Number<double>>
应该是 Number
类型,但是乘积 m_a_dxdt * abs(get_unit_value( dt ))
用作 rel_error
的第 4 个参数构造函数是 State
类型。
我假设我在为 State
class 实现向量 space 代数时犯了一个错误,但我找不到我在哪里犯了错误。
如果我用普通 double
替换时间和值类型,错误检查器将再次工作。
odeint指令好像有错误。
如果 abs
函数的 return 类型是 Value
而不是人们天真地认为它是 State
,那么编译错误就会消失。