在 boost::odeint 中指定插值时间
Specify interpolation times in boost::odeint
我已经开始在我的 C++ 代码中使用 boost::odeint
,我认为我缺少其他集成器中可用的一个简单功能,即 Scipy 的 odeint
。
scipy.odeint
允许用户指定必须将状态添加到输出状态历史记录的时间。scipy.odeint
是一个可变时间步长积分器,其单行调用如下所示(状态从初始条件 X0
和 interpolated/stored 在 times
中指定的时间积分)
X = scipy.odeint(dxdt,X0,times,atol = 1e-13,rtol = 1e-13)
其中 X
是一个矩阵,其行数与 times
中的元素数相同
基本上,我正在 boost::odeint
中寻找类似的功能,以便做两件事:
- 将状态从
t0
传播到 tf
,但只检索状态的最终值。我认为如果内部时间满足 t == tf
,我可以编写一个只存储状态的观察者,但这看起来像是一个相当丑陋的 hack。如果我想让积分器选择合适的内部时间步来满足公差值,存储中间状态是一个不必要的负担。
- 将状态从
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
中,没有让我指定存储时间应该是多少。
我该如何进行?
您似乎在寻找 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));
我已经开始在我的 C++ 代码中使用 boost::odeint
,我认为我缺少其他集成器中可用的一个简单功能,即 Scipy 的 odeint
。
scipy.odeint
允许用户指定必须将状态添加到输出状态历史记录的时间。scipy.odeint
是一个可变时间步长积分器,其单行调用如下所示(状态从初始条件 X0
和 interpolated/stored 在 times
中指定的时间积分)
X = scipy.odeint(dxdt,X0,times,atol = 1e-13,rtol = 1e-13)
其中 X
是一个矩阵,其行数与 times
基本上,我正在 boost::odeint
中寻找类似的功能,以便做两件事:
- 将状态从
t0
传播到tf
,但只检索状态的最终值。我认为如果内部时间满足t == tf
,我可以编写一个只存储状态的观察者,但这看起来像是一个相当丑陋的 hack。如果我想让积分器选择合适的内部时间步来满足公差值,存储中间状态是一个不必要的负担。 - 将状态从
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
中,没有让我指定存储时间应该是多少。
我该如何进行?
您似乎在寻找 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));