odeint的runge_kutta4与Matlab的ode45的比较 [英] Comparison of odeint's runge_kutta4 with Matlab's ode45

查看:398
本文介绍了odeint的runge_kutta4与Matlab的ode45的比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 odeint C ++库中使用runge_kutta4方法.我已经解决了Matlab中的问题.我在Matlab中用以下初始值x1 = 1x2 = 0求解x'' = -x - g*x'的代码如下

I would like to use runge_kutta4 method in the odeint C++ library. I've solved the problem in Matlab. My following code in Matlab to solve x'' = -x - g*x', with initial values x1 = 1, x2 = 0, is as follows

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)');

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

我已经安装了odeint库.我使用runge_kutta4的代码如下

I've installed the odeint Library. My code for using runge_kutta4 is as follows

#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;
}

结果如下图

我的问题是为什么结果会有所不同?我的C ++代码有问题吗?

My question is why the result varies? Is there something wrong with my C++ code?

这些是这两种方法的第一个值

These are the first values of both methods

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


更新:


Update:

问题是我忘记在C ++代码中包含初始值.感谢@horchler注意到它.包含正确的值并按照@horchler的建议使用runge_kutta_dopri5后,结果为

The problem is that I forgot to include the initial value in my C++ code. Thanks for @horchler for noticing it. After including the proper values and using runge_kutta_dopri5 as @horchler suggested, the result is

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

我已经更新了代码以反映这些修改.

I've updated the code to reflect these modifications.

推荐答案

odeint中的runge_kutta4步进器与Matlab的

The runge_kutta4 stepper in odeint is nothing like Matlab's ode45, which is an adaptive scheme based on the Dormand-Prince method. To replicate Matlab's results, you should probably try the runge_kutta_dopri5 stepper. Also, make sure that your C++ code uses the same absolute and relative tolerances as ode45 (defaults are 1e-6 and 1e-3, respectively). Lastly, it looks like you may not be saving/printing your initial condition in your C++ results.

如果即使您指定了t = 0:0.1:10;,对于为什么ode45仍未采取固定步骤感到困惑,请参阅我的详细答案这里.

If you're confused at why ode45 is not taking fixed steps even though you specified t = 0:0.1:10;, see my detailed answer here.

如果必须使用固定的step runge_kutta4步进器,则需要减小C ++代码中的集成步长,以匹配Matlab的输出.

If you must use the fixed steprunge_kutta4 stepper, then you'll need to reduce the integration step-size in your C++ code to match Matlab's output.

这篇关于odeint的runge_kutta4与Matlab的ode45的比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆