Cro*_*oCo 4 c++ matlab boost numerical-integration odeint
我想runge_kutta4
在odeint C++库中使用方法.我在Matlab中解决了这个问题.在Matlab我以下代码来解决x'' = -x - g*x'
,具有初始值的x1 = 1
,x2 = 0
是如下
main.m
clear all
clc
t = 0:0.1:10;
x0 = [1; 0];
[t, x] = ode45('ODESolver', t, x0);
plot(t, x(:,1));
title('Position');
xlabel('time (sec)');
ylabel('x(t)');
Run Code Online (Sandbox Code Playgroud)
ODESolver.m
function dx = ODESolver(t, x)
dx = zeros(2,1);
g = 0.15;
dx(1) = x(2);
dx(2) = -x(1) - g*x(2);
end
Run Code Online (Sandbox Code Playgroud)
我已经安装了odeint库.我的使用代码runge_kutta4
如下
#include <iostream>
#include <boost/numeric/odeint.hpp>
using namespace std;
using namespace boost::numeric::odeint;
/* The type of container used to hold the state vector */
typedef std::vector< double > state_type;
const double gam = 0.15;
/* The rhs of x' = f(x) */
void lorenz( const state_type &x , state_type &dx , double t )
{
dx[0] = x[1];
dx[1] = -x[0] - gam*x[1];
}
int main(int argc, char **argv)
{
const double dt = 0.1;
runge_kutta_dopri5<state_type> stepper;
state_type x(2);
x[0] = 1.0;
x[1] = 0.0;
double t = 0.0;
cout << x[0] << endl;
for ( size_t i(0); i <= 100; ++i){
stepper.do_step(lorenz, x , t, dt );
t += dt;
cout << x[0] << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果如下图所示
我的问题是为什么结果会有所不同?我的C++代码有问题吗?
这些是两种方法的第一个值
Matlab C++
-----------------
1.0000 0.9950
0.9950 0.9803
0.9803 0.9560
0.9560 0.9226
0.9226 0.8806
0.8806 0.8304
0.8304 0.7728
0.7728 0.7084
0.7083 0.6379
Run Code Online (Sandbox Code Playgroud)
更新:
问题是我忘了在我的C++代码中包含初始值.感谢@horchler注意到它.包含正确的值并使用runge_kutta_dopri5
@horchler建议后,结果是
Matlab C++
-----------------
1.0000 1.0000
0.9950 0.9950
0.9803 0.9803
0.9560 0.9560
0.9226 0.9226
0.8806 0.8806
0.8304 0.8304
0.7728 0.7728
0.7083 0.7084
Run Code Online (Sandbox Code Playgroud)
我已更新代码以反映这些修改.
runge_kutta4
odeint中的步进器与Matlab不同ode45
,后者是基于Dormand-Prince方法的自适应方案.要复制Matlab的结果,您应该尝试使用runge_kutta_dopri5
步进器.此外,请确保您的C++代码使用相同的绝对和相对容差ode45
(默认值分别为1e-6
和1e-3
).最后,看起来您可能没有在C++结果中保存/打印初始条件.
如果您对为什么ode45
即使您指定了没有采取固定步骤感到困惑t = 0:0.1:10;
,请在此处查看我的详细答案.
如果必须使用固定runge_kutta4
步进步进器,那么您需要减少C++代码中的集成步长以匹配Matlab的输出.