boost :: odeintを使用して非線形システムを数値的に統合しようとしています。システムには外部から生成される時変パラメータがあり、これをプログラムに組み込みたいと考えています。これはodeintで可能ですか? Matlabでは、同様のことをする場合は、値が利用可能になると補間する必要があります。ルックアップテーブルからの時間可変パラメータをboost :: odeint、C++に組み込む方法
ありがとうございました!
boost :: odeintを使用して非線形システムを数値的に統合しようとしています。システムには外部から生成される時変パラメータがあり、これをプログラムに組み込みたいと考えています。これはodeintで可能ですか? Matlabでは、同様のことをする場合は、値が利用可能になると補間する必要があります。ルックアップテーブルからの時間可変パラメータをboost :: odeint、C++に組み込む方法
ありがとうございました!
編集:
あなたがodeint
で簡単に非線形時変システムを解決することができます
。非線形時変システムの次の例は、Applied Nonlinear Control by Slotineから、我々は各時間ステップで何もしていないので、我々は安全に6sin(t)
ode
内に挿入することができます
注目されています。あなたのシステムに、デリバティブを計算するためにデルタ時間を必要とする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;
}
結果は(すなわち、上記の結果と同じです)。
はい、可能です。しかし、値を補間する必要があるかもしれません。システム関数を介してソルバと対話します。これはファンクタにすることができ、例えば、データへのリンクを含めることができます
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;
};
こんにちは、一つの問題があります: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
@headmyshoulder、あなたは間違いなく正しいです。私はこの問題を反映する答えを更新し、もちろん 'GetTImeParameter()'は必要ありません。 – CroCo
@macropod、アップデートをご覧ください。 – CroCo