Matlab脚本移动到C但是ode45的输出不同

时间:2013-04-04 14:17:14

标签: c matlab gsl ode

我在C中实现了一个等效版本的Matlab脚本。为了运行ode45,我选择了GNU科学库。但是ode45为每个版本产生不同的输出。我已经工作了一段时间,我无法找到问题。 我使用gsl_odeiv2_driver_apply_fixed_step来完成与Matlab相同的步骤。

Matlab脚本

function ExpoGrowthEqn
% code to solve the exponential growth equation 
% dN/dt = r*N, N(0)=N0

% parameter values
r=0.2;
N0=10;

% numerical parameters
step=0.25;
tspan=[0:step:10];

% EXACT solution is: N(t)=N0 * exp(r*t)
for i=1:length(tspan)
    N(i,1)=N0*exp(r*tspan(1,i));
end
plot(tspan,N,'ob') %plots EXACT solution
hold on

% solve ODE using ode45
options = odeset('RelTol',1e-12,'AbsTol',1e-12);
    [t y] = ode45( @growth_eqn, tspan, N0, options, r);
    plot(t,y,'-r') %plot APPROXIMATE solution

    solutions=[t N y]
end

function dy = growth_eqn(t, y, r)
N=y(1)
dy=r*N;
end

C代码

void fixed_step(void) {

    PARAM parameters;
    parameters.N = 11500000;
    parameters.beta = 0.1;
    parameters.gamma = 1/2;   

    double I0=500.0/parameters.N;
    double R0=9000000.0/parameters.N;
    double S0=1-I0-R0;
    double y[3] = {S0, I0, R0};

    gsl_odeiv2_system sys = {func, NULL, 3, &parameters};
    gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-12, 1e-12, 0);

    printf ("=== Initial values ===\n");
    printf ("y[0]=%6.15lf y[1]=%6.15lf y[2]=%6.15lf\n", y[0], y[1], y[2]);
    int length = 53;
    const double step = 0.25;
    double ti; double t = 0.0, tant = t;
    int i;
    for (i = 0; i <= length*(1/step); i++)
    {
        printf ("%.2f(%3.d) -> t=%.2f %6.15lf %6.15lf %6.15lf\n", (float)tant, i, (float)t, y[0], y[1], y[2]);
        tant = t;
        int status = gsl_odeiv2_driver_apply_fixed_step (d, &t, step/8, 8, y);

        if (status != GSL_SUCCESS)
        {
            printf ("error, return value=%d\n", status);
        }
    }
    gsl_odeiv2_driver_free (d);        
}

Matlab输出

S                   I                   R
------------------------------------------------------------------
0.217347826086956   0.000043478260870   0.782608695652174
0.217347603416592   0.000038578485741   0.782613818097667
0.217347405784518   0.000034229664122   0.782618364551360
0.217347230418583   0.000030370797298   0.782622398784119
0.217347074884551   0.000026948321844   0.782625976793605
...
0.217345850226451   0.000000000007068   0.782654149766481
0.217345850226413   0.000000000006234   0.782654149767354
0.217345850226380   0.000000000005510   0.782654149768110
0.217345850226351   0.000000000004888   0.782654149768761
0.217345850226327   0.000000000004356   0.782654149769316
0.217345850226307   0.000000000003903   0.782654149769790
0.217345850226289   0.000000000003514   0.782654149770197
0.217345850226273   0.000000000003172   0.782654149770554
0.217345850226259   0.000000000002859   0.782654149770881
0.217345850226245   0.000000000002556   0.782654149771198

C输出

=== Initial values ===
y[0]=0.217347826086956 y[1]=0.000043478260870 y[2]=0.782608695652174
0.00(   ) -> t=0.00 0.217347826086956 0.000043478260870 0.782608695652174
0.00(  1) -> t=0.25 0.217347589196436 0.000043715151390 0.782608695652174
0.25(  2) -> t=0.50 0.217347351015482 0.000043953332344 0.782608695652174
0.50(  3) -> t=0.75 0.217347111537070 0.000044192810757 0.782608695652174
0.75(  4) -> t=1.00 0.217346870754133 0.000044433593694 0.782608695652174
...
51.00(205) -> t=51.25 0.217258883883215 0.000132420464611 0.782608695652174
51.25(206) -> t=51.50 0.217258162689554 0.000133141658272 0.782608695652174
51.50(207) -> t=51.75 0.217257437570519 0.000133866777307 0.782608695652174
51.75(208) -> t=52.00 0.217256708504771 0.000134595843055 0.782608695652174
52.00(209) -> t=52.25 0.217255975470856 0.000135328876970 0.782608695652174
52.25(210) -> t=52.50 0.217255238447202 0.000136065900623 0.782608695652174
52.50(211) -> t=52.75 0.217254497412123 0.000136806935703 0.782608695652174
52.75(212) -> t=53.00 0.217253752343811 0.000137552004014 0.782608695652174

在第二列的末尾,数据有很大不同。在Matlab中几乎为0但不是C代码。

Matlab时间戳

t =
                0
0.250000000000000
0.500000000000000
0.750000000000000
1.000000000000000
1.250000000000000
1.500000000000000
1.750000000000000
...
52.250000000000000
52.500000000000000
52.750000000000000
53.000000000000000

2 个答案:

答案 0 :(得分:0)

当您指定tspan(阅读here)时,Matlab在其内部计算中不使用固定步长。它在选定的时间输出。因此,您正在进行两种不同的计算。阅读the first GSL example如何使用固定输出时间的自适应时间步进。

答案 1 :(得分:0)

我道歉,我没有包含导致问题的一小段代码。已编辑C代码以添加缺失的4行。 找到问题:

  

// gamma = 0.0   parameters.gamma = 1/2;

结果返回0。显然这是错误的。用逗号声明数字就可以解决问题了。

  

// gamma = 0.5   parameters.gamma = 1.0 / 2.0;