2016-07-29 8 views
1

boost :: odeintを使用して非線形システムを数値的に統合しようとしています。システムには外部から生成される時変パラメータがあり、これをプログラムに組み込みたいと考えています。これはodeintで可能ですか? Matlabでは、同様のことをする場合は、値が利用可能になると補間する必要があります。ルックアップテーブルからの時間可変パラメータをboost :: odeint、C++に組み込む方法

ありがとうございました!

答えて

0

編集:

あなたが odeintで簡単に非線形時変システムを解決することができます

。非線形時変システムの次の例は、Applied Nonlinear Control by Slotineから、我々は各時間ステップで何もしていないので、我々は安全に6sin(t)ode内に挿入することができます

enter image description here

注目されています。あなたのシステムに、デリバティブを計算するためにデルタ時間を必要とするPIDコントローラのような時間ステップに依存するコントローラがある場合は、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

こんにちは、一つの問題があります:1つのステップの間、ソルバは、異なる時間値を持つとODE関数を複数回呼び出します。例えば、RK4は1ステップの間に時間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; 
}; 
関連する問題