ode45收敛到正确的曲线形状,但是解决方法错误

时间:2019-02-15 18:45:19

标签: matlab numerical-methods numerical-analysis

在此先感谢您的帮助。我不是在寻找解决问题的明确方法,而是要指出可能的明显错误。

我一直致力于解决MATLAB中的非线性一阶ODE系统。在这项研究中对该系统进行了数值求解:http://web.math.ku.dk/~moller/e04/bio/ludwig78.pdf

我一直在遵循documentation for ode45,并且有正在运行的代码。

我已经完成了所有工作,以从头开始理解并重新创建模型。我介绍了课堂项目的定性部分。我现在正在做的是通过使用runge-kutta(或任何可行的方法)在MATLAB中解决系统,从而使该项目更进一步。最后,我想深入探讨数值分析背后的理论,以找出所选方法收敛的原因。

这是数值求解系统的图解,我正尝试重新创建它:enter image description here

我发现我可以创建形状大致相同的图,但是存在一些问题:

  1. 发生变化的时间尺度是上图的三倍。
  2. 函数值的范围是完全错误的。
  3. 仅当我将初始条件调整为 与上面的t = 0附近显示的明显不同。

所以我要寻找的是这些差异的原因。我已经检查了ODE和参数值的系统,以至于我的眼睛模糊了很多次。也许我在概念上缺少什么?

代码:

% System Parameters:
r_b = 1.52;
k_b = 355;
alph = 1.11;
bet = 43200;
r_e = 0.92;
k_e = 1;
p = 0.00195;
r_s = 0.095;
k_s = 25440;

tspan = [0 200];
init = [1 1 1];

[t, Y] = ode45(@(t,y) odefcn(t, y, r_b, k_b, alph, bet, r_e, k_e, p, r_s, k_s), tspan, init);
subplot(3,1,1);
plot(t,Y(:,1),'b');
title('Budworm Density');

subplot(3,1,2)
plot(t,Y(:,2),'g');
title('Branch Density');

subplot(3,1,3);
plot(t,Y(:,3),'r');
title('Foliage Condition');

function dydt = odefcn(t, y, r_b, k_b, alph, bet, r_e, k_e, p, r_s, k_s)
dydt = [ r_b*y(1)*(1 - y(1)/(k_b*y(2))) - bet*(y(1)^2/((alph*y(2))^2 + y(1)^2));
         r_s*y(2)*(1 - (y(2)*k_e)/(k_s*y(3)));
         r_e*y(3)*(1 - (y(3)/k_e)) - p*y(1)/y(2)
        ];

end

1 个答案:

答案 0 :(得分:1)

我认为您的代码没有任何问题。但是我认为在制作图形时涉及到一些细微之处,而本文中对此并没有很好地解释。

1)S轴已缩放(在标签中显示为“相对”)。我相信他们已经按k_s缩放了S。我认为您还需要缩放参数p(设置p = p * k_s),否则E方程中的最后一项将很小,并且E人口不会在所需的时间范围内减少。

2)我认为他们必须对E强制执行一些下限,以避免除以0。在图中可以看到E-> 0首先,但是在S的方程式中,如果发生这种情况,那么您将除以0,求解器将不会收敛。

将这些内容放在一起,对您的代码进行以下稍作修改即可产生与本文更相似的结果:

ODE result

% System Parameters:
r_b = 1.52;
k_b = 355;
alph = 1.11;
bet = 43200;
r_e = 0.92;
k_e = 1;
p = 0.00195;
r_s = 0.095;
k_s = 25440;

% Scale p with k_s
p = p*k_s;

tspan = [0 50]; % [0 200];
init = [1e-16 0.075*k_s 1]; % [1 1 1];

[t, Y] = ode45(@(t,y) odefcn(t, y, r_b, k_b, alph, bet, r_e, k_e, p, r_s, k_s), tspan, init);

% To scale before plotting, so everything fits on a 0->1 y axis.
maxB = 500;
S_scale = k_s;

figure('Position', [200 200 1000 600]);
hold on;
plot(t,Y(:,1)/maxB,'b');
plot(t,Y(:,2)/(S_scale),'g');
plot(t,Y(:,3),'r');

ylim([0, 1]);

hold off;

box on;

legend({['Budworm Density, B / ', num2str(maxB)], 'Branch Density, S / 0.75', 'Foliage Condition, E'}, ...
    'Location', 'eastoutside')

function dydt = odefcn(t, y, r_b, k_b, alph, bet, r_e, k_e, p, r_s, k_s)

% Place lower limit on E
E = max(y(3), 1e-5);

dydt = [ r_b*y(1)*(1 - y(1)/(k_b*y(2))) - bet*(y(1)^2/((alph*y(2))^2 + y(1)^2));
         r_s*y(2)*(1 - (y(2)*k_e)/(k_s*E));
         r_e*E*(1 - (E/k_e)) - p*y(1)/y(2)
        ];

end

对初始条件有很多敏感性。

进一步的调整使您更接近原始图,但是我不确定这是否只是hack:在第一个方程式中,仅用k_b替换k_b * y(2)。没有这个,芽孢密度在降低之前就太大了。新的情节在下面。

Modified k_b