如何将查找 table 中的时变参数合并到 boost::odeint 中,c++
How to incorporate time-varying parameters from lookup table into boost::odeint, c++
我正在尝试使用 boost::odeint 对非线性系统进行数值积分。该系统具有外部生成的时变参数,我想将其合并到我的程序中。 odeint 可以吗?在 Matlab 中,如果您要执行类似的操作,则需要在值可用时对其进行插值。
提前感谢您的帮助!
是的,这是可能的。但是您可能也需要对这些值进行插值。您通过系统功能与求解器交互。它可以是仿函数,它可以包含数据的 link,例如
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;
};
编辑:
您可以使用 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;
}
结果是(即上述书中出现的相同结果)。
我正在尝试使用 boost::odeint 对非线性系统进行数值积分。该系统具有外部生成的时变参数,我想将其合并到我的程序中。 odeint 可以吗?在 Matlab 中,如果您要执行类似的操作,则需要在值可用时对其进行插值。
提前感谢您的帮助!
是的,这是可能的。但是您可能也需要对这些值进行插值。您通过系统功能与求解器交互。它可以是仿函数,它可以包含数据的 link,例如
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;
};
编辑:
您可以使用 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;
}
结果是(即上述书中出现的相同结果)。