2014-04-01 85 views
11

我试图利用ODE integration capabilities of Boost使用Matrix class from Eigen 3作为我的状态向量,但我遇到了深入到Boost的问题,我不明白如何地址。使用Boost :: odeint与特征::矩阵作为状态向量

的什么,我试图做一个小例子:

#include <Eigen/Core> 
#include <boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp> 
#include <iostream> 

using namespace Eigen; 
using namespace boost::numeric::odeint; 

template<size_t N> 
using vector = Matrix<double, N, 1>; 

typedef vector<3> state; 

int main() { 

    state X0; 
    X0 << 1., 2., 3.; 
    state xout = X0; 

    runge_kutta_dopri5<state> stepper; 

    // If I remove these lines, everything compiles fine 
    stepper.do_step([](const state x, state dxdt, const double t) -> void { 
     dxdt = x; 
    }, X0, 0.0, xout, 0.01); 

    std::cout << xout << std::endl; 
} 

如果我COMENT了呼叫stepper.do_step一切编译和运行得很好,但当然没有做什么有趣的事。如果我不这样做,升压vomits compile errors over my terminal,其中第一个是

In file included from /usr/include/boost/mpl/aux_/begin_end_impl.hpp:20:0, 
       from /usr/include/boost/mpl/begin_end.hpp:18, 
       from /usr/include/boost/mpl/is_sequence.hpp:19, 
       from /usr/include/boost/fusion/support/detail/is_mpl_sequence.hpp:12, 
       from /usr/include/boost/fusion/support/tag_of.hpp:13, 
       from /usr/include/boost/fusion/support/is_sequence.hpp:11, 
       from /usr/include/boost/fusion/sequence/intrinsic_fwd.hpp:12, 
       from /usr/include/boost/fusion/sequence/intrinsic/front.hpp:10, 
       from /usr/include/boost/fusion/include/front.hpp:10, 
       from /usr/include/boost/numeric/odeint/util/is_resizeable.hpp:26, 
       from /usr/include/boost/numeric/odeint/util/state_wrapper.hpp:25, 
       from /usr/include/boost/numeric/odeint/stepper/base/explicit_error_stepper_fsal_base.hpp:27, 
       from /usr/include/boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp:24, 
       from /home/tlycken/exjobb/Code/alpha-orbit-follower/test/algebra/algebra-tests.cpp:2: 
/usr/include/boost/mpl/eval_if.hpp: In instantiation of ‘struct boost::mpl::eval_if_c<true, boost::range_const_iterator<Eigen::Matrix<double, 3, 1> >, boost::range_mutable_iterator<const Eigen::Matrix<double, 3, 1> > >’: 
/usr/include/boost/range/iterator.hpp:63:63: required from ‘struct boost::range_iterator<const Eigen::Matrix<double, 3, 1> >’ 
/usr/include/boost/range/begin.hpp:112:61: required by substitution of ‘template<class T> typename boost::range_iterator<const T>::type boost::range_adl_barrier::begin(const T&) [with T = Eigen::Matrix<double, 3, 1>]’ 
/usr/include/boost/numeric/odeint/algebra/range_algebra.hpp:52:45: required from ‘static void boost::numeric::odeint::range_algebra::for_each3(S1&, S2&, S3&, Op) [with S1 = Eigen::Matrix<double, 3, 1>; S2 = const Eigen::Matrix<double, 3, 1>; S3 = const Eigen::Matrix<double, 3, 1>; Op = boost::numeric::odeint::default_operations::scale_sum2<double, double>]’ 
/usr/include/boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp:128:9: required from ‘void boost::numeric::odeint::runge_kutta_dopri5<State, Value, Deriv, Time, Algebra, Operations, Resizer>::do_step_impl(System, const StateIn&, const DerivIn&, boost::numeric::odeint::runge_kutta_dopri5<State, Value, Deriv, Time, Algebra, Operations, Resizer>::time_type, StateOut&, DerivOut&, boost::numeric::odeint::runge_kutta_dopri5<State, Value, Deriv, Time, Algebra, Operations, Resizer>::time_type) [with System = main()::__lambda0; StateIn = Eigen::Matrix<double, 3, 1>; DerivIn = Eigen::Matrix<double, 3, 1>; StateOut = Eigen::Matrix<double, 3, 1>; DerivOut = Eigen::Matrix<double, 3, 1>; State = Eigen::Matrix<double, 3, 1>; Value = double; Deriv = Eigen::Matrix<double, 3, 1>; Time = double; Algebra = boost::numeric::odeint::range_algebra; Operations = boost::numeric::odeint::default_operations; Resizer = boost::numeric::odeint::initially_resizer; boost::numeric::odeint::runge_kutta_dopri5<State, Value, Deriv, Time, Algebra, Operations, Resizer>::time_type = double]’ 
/usr/include/boost/numeric/odeint/stepper/base/explicit_error_stepper_fsal_base.hpp:167:9: required from ‘typename boost::disable_if<boost::is_same<StateInOut, Time>, void>::type boost::numeric::odeint::explicit_error_stepper_fsal_base<Stepper, Order, StepperOrder, ErrorOrder, State, Value, Deriv, Time, Algebra, Operations, Resizer>::do_step(System, const StateIn&, boost::numeric::odeint::explicit_error_stepper_fsal_base<Stepper, Order, StepperOrder, ErrorOrder, State, Value, Deriv, Time, Algebra, Operations, Resizer>::time_type, StateOut&, boost::numeric::odeint::explicit_error_stepper_fsal_base<Stepper, Order, StepperOrder, ErrorOrder, State, Value, Deriv, Time, Algebra, Operations, Resizer>::time_type) [with System = main()::__lambda0; StateIn = Eigen::Matrix<double, 3, 1>; StateOut = Eigen::Matrix<double, 3, 1>; Stepper = boost::numeric::odeint::runge_kutta_dopri5<Eigen::Matrix<double, 3, 1> >; short unsigned int Order = 5u; short unsigned int StepperOrder = 5u; short unsigned int ErrorOrder = 4u; State = Eigen::Matrix<double, 3, 1>; Value = double; Deriv = Eigen::Matrix<double, 3, 1>; Time = double; Algebra = boost::numeric::odeint::range_algebra; Operations = boost::numeric::odeint::default_operations; Resizer = boost::numeric::odeint::initially_resizer; typename boost::disable_if<boost::is_same<StateInOut, Time>, void>::type = void; boost::numeric::odeint::explicit_error_stepper_fsal_base<Stepper, Order, StepperOrder, ErrorOrder, State, Value, Deriv, Time, Algebra, Operations, Resizer>::time_type = double]’ 
/home/tlycken/exjobb/Code/alpha-orbit-follower/test/algebra/algebra-tests.cpp:21:137: required from here 
/usr/include/boost/mpl/eval_if.hpp:60:31: error: no type named ‘type’ in ‘boost::mpl::eval_if_c<true, boost::range_const_iterator<Eigen::Matrix<double, 3, 1> >, boost::range_mutable_iterator<const Eigen::Matrix<double, 3, 1> > >::f_ {aka struct boost::range_const_iterator<Eigen::Matrix<double, 3, 1> >}’ 
    typedef typename f_::type type; 

我试图钻进去the Boost header where the error occurs,但我没有足够的理解发生了什么事情,能够解决我的代码。由于odeint库文档clearly states

odeint的主要重点是提供的方式,其中所述算法是完全独立于用于表示状态x中的数据结构来实现的数值方法。

即使odeint本身不支持Eigen,我相信这应该不会太难。

+0

而有人问前:我在喜欢本征的矩阵类由于其线性代数能力,Boost或std中的内置函数。我需要将状态向量视为状态空间中的实际向量,其中支持向量减法,规范和点积等操作。我希望使用'Eigen :: Matrix'会比我自己的std :: array'包装更简单... –

+0

您可以尝试将步进器的定义替换为runge_kutta_dopri5 步进器;我想你还需要包含向量空间代数:#include 。 – headmyshoulder

+0

@headmyshoulder:谢谢!我刚刚从[这个例子](http://www.boost.org/doc/libs/1_55_0/libs/numeric/odeint/examples/lorenz_point.cpp)中发现了这一点,并且在我回到这里时试着尝试看到你的评论。如果我做出这样的改变,我的代码确实可以编译,尽管它打印的是最初的起点而不是下一个。我认为这可能是其他地方的错误(在屏幕和键盘之间),但是......在更多的故障排除后会回来! –

回答

7

你只需要通过

runge_kutta_dopri5<state,double,state,double,vector_space_algebra> stepper; 

征应开箱与vector_space_algebra更换步进的定义,但需要手动指定它们。在接下来的版本中,我们有一个自动检测代数的机制。

Btw。悠逸的ODE的定义是不正确的,你需要的derivatve

stepper.do_step([](const state &x, state &dxdt, const double t) -> void { 
    dxdt = x; 
}, X0, 0.0, xout, 0.01); 
+0

非常感谢!从你的用户名猜测,我认为你可能是正确的人告诉这件事;)我最终确实解决了这个问题,这要归功于在一个没有列出的例子中的示例文件底部的小评论任何TOC,但仅限于“所有示例”列表([this one](http://www.boost.org/doc/libs/1_55_0/libs/numeric/odeint/examples/lorenz_point.cpp))。在文档中有一个前面提到的功能(在概述页面上被命名为库的重点),如果关于如何实现这个目标的文档更容易达到=) –

2

该解决方案似乎并不自适应集成工作的参考

typedef runge_kutta_dopri5<state,double,state,double,vector_space_algebra> stepper_type; 
auto rhs = [](const state &x, state &dxdt, const double t) -> void { dxdt = x;} 
integrate_adaptive(make_controlled<stepper_type>(1E-12 , 1E-12), rhs , X0 , 0. , xout , 0.01;) 
+0

_does not seem_? – Nithin

+1

看一看[升压odeint DOC(http://www.boost.org/doc/libs/1_53_0/libs/numeric/odeint/doc/html/boost_numeric_odeint/odeint_in_detail/state_types__algebras_and_operations.html#boost_numeric_odeint.odeint_in_detail。 state_types__algebras_and_operations.algebras_and_operations.vector_space_algebra)用于自适应积分,状态类型需要支持元素明智的分割,元素明确abs,这不支持Eigen :: Matrix(仅适用于Eigen :: Array)因此,您需要告诉boost如何用Eigen :: Matrix(向数组和向后)转换! –

相关问题