使用高精度的boost odeint计算多维积分的推荐方法是什么?以下代码将f = x * y从-1加到2,但相对于解析解的误差超过1%(gcc 4.8.2,-std = c ++ 0x):
#include "array"
#include "boost/numeric/odeint.hpp"
#include "iostream"
using integral_type = std::array<double, 1>;
int main() {
integral_type outer_integral{0};
double current_x = 0;
boost::numeric::odeint::integrate(
[&](
const integral_type&,
integral_type& dfdx,
const double x
) {
integral_type inner_integral{0};
boost::numeric::odeint::integrate(
[¤t_x](
const integral_type&,
integral_type& dfdy,
const double y
) {
dfdy[0] = current_x * y;
},
inner_integral,
-1.0,
2.0,
1e-3
);
dfdx[0] = inner_integral[0];
},
outer_integral,
-1.0,
2.0,
1e-3,
[¤t_x](const integral_type&, const double x) {
current_x = x; // update x in inner integrator
}
);
std::cout
<< "Exact: 2.25, numerical: "
<< outer_integral[0]
<< std::endl;
return 0;
}
打印:
Exact: 2.25, numerical: 2.19088
我是否应该在内部积分中使用更严格的停止条件,或者是否有更快/更准确的方法来执行此操作?谢谢!
答案 0 :(得分:2)
首先,可能有更好的数值方法来计算高维积分而不是ODE方案(http://en.wikipedia.org/wiki/Numerical_integration),但我认为这是odeint的一个巧妙的应用,我发现。
但是,代码的问题在于它假定您在外部集成中使用观察者来更新内部集成的x值。但是,integrate
函数在内部使用密集输出步进器,这意味着实际时间步长和观察者调用不同步。因此,内部集成的x不会在适当的时刻更新。快速解决方法是使用integration_const和runge_kutta4步进器,它使用常量步长并确保在外循环的每个步骤之后调用观察者调用,从而调用x更新。但是,这是一个依赖于集成例程的一些内部细节的黑客攻击。更好的方法是以这样的方式设计程序,即状态确实是二维的,但是每个集成仅在两个变量中的一个上起作用。