Как выполнить простое числовое интегрирование с помощью odeint в C++

Можете ли вы предоставить мне простой пример выполнения числовой интеграции с odeint в C++?

Я хотел бы использовать удобную функцию интеграции, задокументировано как:

integrate( system , x0 , t0 , t1 , dt )

Также я не уверен, как передать вместо функции или функтора метод класса, если это возможно.


person Itay Grudev    schedule 12.09.2013    source источник
comment
Разве интеграция не является циклом for?   -  person crush    schedule 12.09.2013
comment
@crush Да, это так. Но Odeint автоматизирует процесс и позволяет позже интегрироваться с OpenMP, Cuda и Thrust, поэтому я решил использовать его.   -  person Itay Grudev    schedule 12.09.2013
comment
@crush: интеграция - это больше, чем цикл for. Я также создаю степпер, и он выполняет интеграцию с плотным выходом и контролем размера шага.   -  person headmyshoulder    schedule 12.09.2013


Ответы (2)


В С++ 11 вы можете использовать простую лямбда-функцию, обертывающую вызов вашего метода-члена.

Class c;
auto f = [&c]( const state_type & x , state_type &dxdt , double t ) {
    c.system_func( x , dxdt , t ); };
integrate( f , x0 , t0 , t1 , dt );

std::bind также может работать, но тогда вам нужно позаботиться о том, чтобы значения передаются по ссылке или по значению.

В С++ 03 вам нужно написать простую оболочку вокруг вашего метода класса.

struct wrapper
{
    Class &c;
    wrapper( Class &c_ ) : c( c_ )  { }
    template< typename State , typename Time >
    void operator()( State const &x , State &dxdt , Time t ) const
    {
        c.system_func( x , dxdt , t );
    }
};

// ...
integrate( wrapper( c ) , x0 , t0 , t1 , dt );

(Boost.Bind не будет корректно работать с более чем двумя аргументами).

person headmyshoulder    schedule 12.09.2013
comment
Может ли метод быть членом одного и того же экземпляра класса? - person Itay Grudev; 12.09.2013
comment
А также, что такое c, p1::_1 и т. д. в вашем примере? - person Itay Grudev; 12.09.2013
comment
Я не понимаю ваш первый вопрос. Метод вызывается с экземпляром c. pl — это пространство имен для std::placeholders. Я отредактировал свой ответ. - person headmyshoulder; 12.09.2013
comment
Я не понимаю, как моя функция (в этом примере system_func) передает значение результата. (Точка графика, которая используется при расчете поверхности функции). - person Itay Grudev; 13.09.2013
comment
Ах, вы правы, значения, передаваемые в std::bind, передаются по значению. Но вы можете использовать лямбда-функцию, в которой вы явно указываете, как передаются значения. }; интегрировать( f , x , t0 , t1 , dt ); - person headmyshoulder; 13.09.2013

Вы имеете в виду примеры в дополнение к тем, которые предоставлены в Интернете?

#include <iostream>
#include <boost/array.hpp>

#include <boost/numeric/odeint.hpp>

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

const double sigma = 10.0;
const double R = 28.0;
const double b = 8.0 / 3.0;

typedef boost::array< double , 3 > state_type;

void lorenz( const state_type &x , state_type &dxdt , double t )
{
    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];
}

void write_lorenz( const state_type &x , const double t )
{
    cout << t << '\t' << x[0] << '\t' << x[1] << '\t' << x[2] << endl;
}

int main(int argc, char **argv)
{
    state_type x = { 10.0 , 1.0 , 1.0 }; // initial conditions
    integrate( lorenz , x , 0.0 , 25.0 , 0.1 , write_lorenz );
}

График вывода из приведенного выше примера

А что касается системы, вы можете предоставить что угодно, где допустимо следующее выражение:

sys( x , dxdt , t ) // returning void

Ознакомьтесь с руководством пользователя (и другими примерами) онлайн. .

person Escualo    schedule 12.09.2013