ODEi​​nt:具有任意精度的自适应积分

时间:2016-03-30 06:49:23

标签: c++ odeint

ODEint是否可以将自适应集成例程与任意精度算法一起使用?例如,我想将Boost multiprecision库与integrate_adaptive()函数与受控步进器一起使用。 ODEi​​nt文档提供了对integrate_const()使用任意精度算术的示例,但我无法修改它们以使用自适应积分器。

我也尝试过使用迭代器(例如make_adaptive_time_iterator ......)但遇到了类似的问题。具体而言,这是一个我希望工作的简单代码:

#include <iostream>

//[ mp_lorenz_defs
#include <boost/numeric/odeint.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>

using namespace std;
using namespace boost::numeric::odeint;

typedef boost::multiprecision::cpp_dec_float_50 value_type;
//typedef double value_type;

typedef boost::array< value_type , 3 > state_type;
//]

//[ mp_lorenz_rhs
struct lorenz
{
    void operator()( const state_type &x , state_type &dxdt , value_type t ) const
    {
        const value_type sigma( 10 );
        const value_type R( 28 );
        const value_type b( value_type( 8 ) / value_type( 3 ) );

        dxdt[0] = sigma * ( x[1] - x[0] );
        dxdt[1] = R * x[0] - x[1] - x[0] * x[2];
        dxdt[2] = -b * x[2] + x[0] * x[1];
    }
};
//]

int main( int argc , char **argv )
{
    //[ mp_lorenz_int
    state_type x = {{ value_type( 10.0 ) , value_type( 10.0 ) , value_type( 10.0 ) }};

    auto stepper = make_controlled( 1.0e-16 , 1.0e-16 , runge_kutta_cash_karp54< state_type >() );


    cout.precision(50);
    integrate_adaptive( stepper ,
           lorenz() , x , value_type( 0.0 ) , value_type( 0.1 ) , value_type( value_type( 1.0 ) / value_type( 2000.0 ) ) );
    //]
    cout << x[0] << endl;

    return 0;
}

编译它会返回错误:

Lorenz_mp2.cpp:52:19: error: no matching function for call to 'make_controlled'
        auto stepper = make_controlled( value_type(1.0e-16) , value_type(1.0e-16) , runge_kutta_cash_karp54< state_type >() );

如果我将value_type的typedef更改为double,则编译并运行正常。

1 个答案:

答案 0 :(得分:1)

使用odeint可以使用具有任意精度的自适应积分器。您的代码几乎是正确的,您只是忘记将value_type(用于步进器的内部常量,用于“时间”变量t)配置为任意精度类型。如果您回到文档(http://headmyshoulder.github.io/odeint-v2/doc/boost_numeric_odeint/tutorial/using_arbitrary_precision_floating_point_types.html),您会看到这是由步进器的第二个模板参数完成的。因此make_controlled中正确的步进器定义应为:

runge_kutta_cash_karp54< state_type , value_type >()

有了它,它应该以任意精度编译和运行。

独立于此问题,我想补充一点,使用从double到multi_prec类型的转换可能会有问题。例如,0.1无法准确表示为double(http://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/)。因此,您将得到一个不完全为0.1的multi_prec值。我建议总是从Integers转换,例如将0.1表示为value_type(1)/value_type(10)