2016-07-29 2 views
1

Я пытаюсь численно интегрировать нелинейную систему с помощью boost :: odeint. Система имеет изменяющиеся во времени параметры, которые генерируются извне, и я хочу включить это в свою программу. Возможно ли это с odeint? В Matlab, если вы должны были сделать что-то подобное, вам нужно будет интерполировать значения по мере их появления.Как включить изменяющиеся во времени параметры из таблицы поиска в boost :: odeint, C++

Заранее благодарю вас за помощь!

ответ

0

Edit:

Вы можете решить нелинейную изменяющуюся во времени систему легко с odeint. Следующий пример нелинейной нестационарной системы берется из Applied Nonlinear Control by Slotine

enter image description here

Обратите внимание, что мы можем вставить 6sin(t) внутри ode безопасно, так как мы ничего не делаем на каждом шаге по времени. Если ваша система имеет контроллер, который зависит от временного шага, такого как ПИД-регулятор, для которого требуется дельта-время для вычисления производных, тогда в этом случае не помещайте его внутри ode, так как ode() вызывается несколько раз решателем ode. Это мой код для решения системы.

#include <iostream> 
#include <boost/math/constants/constants.hpp> 
#include <boost/numeric/odeint.hpp> 
#include <fstream> 

std::ofstream data("data.txt"); 

using namespace boost::numeric::odeint; 

typedef std::vector<double> state_type; 

class System 
{ 
public: 
    System(const double& deltaT); 
    void updateODE(); 
    void updateSystem(); 
private: 
    double t, dt; 
    runge_kutta_dopri5 <state_type> stepper; 
    state_type y; 
    void ode(const state_type &y, state_type &dy, double t); 

}; 

System::System(const double& deltaT) : dt(deltaT), t(0.0), y(2) 
{ 
    /* 
     x = y[0] 
     dx = y[1] = dy[0] 
    ddx  = dy[1] = ode equation 
    */ 

    // initial values 
    y[0] = 2.0; // x1 
    y[1] = 0.0; // x2 
} 

void System::updateODE() 
{ 
    // store data for plotting 
    data << t << " " << y[0] << std::endl; 

    //========================================================================= 
    using namespace std::placeholders; 
    stepper.do_step(std::bind(&System::ode, this, _1, _2, _3), y, t, dt); 
    t += dt; 
} 

void System::updateSystem() 
{ 
    // you can utitilize this function in case you have a controller and 
    // you need to update the controller at a fixed step size. 

} 

void System::ode(const state_type &y, state_type &dy, double t) 
{ 
    //#####################(ODE Equation)################################ 
    dy[0] = y[1]; 
    dy[1] = 6.0*sin(t) - 0.1*y[1] - pow(y[0],5); 
} 

int main(int argc, char **argv) 
{ 
    const double dt(0.001); 
    System sys(dt); 

    for (double t(0.0); t <= 50.0; t += dt){ 
     // update time-varying parameters of the system 
     //sys.updateSystem(); 
     // solve the ODE one step forward. 
     sys.updateODE(); 
    } 

    return 0; 
} 

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

enter image description here

+0

Привет, есть одна проблема: во время одного шага решатель будет вызывать функцию ода ​​несколько раз с разными значениями времени. Например, RK4 может использовать его со временем t, t + dt/2, t + dt/2, t + dt за один шаг. Это можно легко решить, изменив класс на 'double GetTImeParameter (double t) {return 6 * sin (t)} ode (const state_type & y, state_type & dy, double t) { dy [0] = y [1 ]; dy [1] = GetTimeParameter (t) - 0,1 * y [1] - pow (y [0], 5); } ' – headmyshoulder

+0

@headmyshoulder, вы определенно правы. Я буду обновлять ответ, чтобы отразить эту проблему, и, конечно, нет необходимости в 'GetTImeParameter()'. – CroCo

+0

@ macropod, см. Обновление. – CroCo

0

Да, это возможно. Но вам может понадобиться также интерполировать значения. Вы взаимодействуете с решателем через системную функцию. Это может быть функтор, и он может содержать ссылку на данные, например

struct ode 
{ 
    void operator()(const state_type& x , state_type& dxdt , double t) const 
    { 
     // get the the parameter from time_varying_parameters 
    } 
    std::vector<double> time_varying_parameters; 
}; 
Смежные вопросы