【问题标题】:Specify interpolation times in boost::odeint在 boost::odeint 中指定插值时间
【发布时间】:2018-05-28 02:53:43
【问题描述】:

我已经开始在我的 C++ 代码中使用 boost::odeint,但我认为我缺少其他集成商提供的一个简单功能,即 Scipy 的 odeint

scipy.odeint 让用户指定必须将状态添加到输出状态历史记录的时间。scipy.odeint 是一个可变时间步长积分器,其单线调用如下所示(状态是从初始条件积分X0 并在times 中指定的时间进行插值/存储)

X = scipy.odeint(dxdt,X0,times,atol = 1e-13,rtol = 1e-13) 

其中X 是一个矩阵,其行数与times 中的元素数一样多

基本上,我正在boost::odeint 中寻找类似的功能,以便做两件事:

  1. 将状态从t0 传播到tf,但只检索状态的最终值。如果内部时间满足t == tf,我想我可以写一个观察者只存储状态,但这看起来像一个相当丑陋的黑客。如果我想让积分器选择合适的内部时间步来满足容差值,存储中间状态是不必要的负担。
  2. 将状态从t0 传播到tf,但在预先指定的时间存储状态,这些时间不一定均匀分布,类似于上面对scipy.odeint 的调用,同时也让集成商选择正确的内部时间步长。

我最接近实现这一目标的是以下

size_t steps = integrate_adaptive( make_controlled< error_stepper_type >( 1.0e-10 , 1.0e-16 ) , 
    dynamics , x , 0.0 , 10.0 , 1. , push_back_state_and_time( x_vec , times ));

满足公差,但所有状态都由观察者存储到x_vec,而没有让我指定存储时间应该是多少。

我应该如何进行?

【问题讨论】:

    标签: python c++ boost odeint


    【解决方案1】:

    看来您正在寻找integrate_times 函数:

    它允许您指定调用观察者的确切时间范围,如有必要,可以调整步长以准确到达每个时间步。

    特别是对于自适应方法,这非常有用,因为它会在您指定的确切时间计算解决方案,同时仍控制时间步长以不超过误差范围。

    所以您当前的通话可以修改为类似

    auto stepper = make_controlled<error_stepper_type>( 1.0e-10 , 1.0e-16 );
    // std::vector<time> times;
    // std::vector<state> x_vec;
    // time tstep;
    auto tbegin = times.begin();
    auto tend = times.end();
    integrate_times(stepper, dynamics, x, tbegin, tend, tstep, push_back_state(x_vec));
    

    【讨论】:

    • 谢谢。编译需要非常小的修改:在 t_end 之后和观察者之前添加一个默认的 dt。如下所示:integrate_times(stepper, dynamics, x, tbegin, tend, 0.1,push_back_state(x_vec));
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-14
    • 1970-01-01
    相关资源
    最近更新 更多