ODE Solvers在一起跑时慢慢跑

时间:2017-04-25 07:22:14

标签: matlab runge-kutta

我有一个类的一些ODE解算器的自定义实现。我遇到了问题,如果我将时间步长dt小于.2,程序将停止运行。但是,如果我注释掉其中一个Runge-Kutta解算器,它会很快执行,我可以切换哪一个被注释掉,这样我就可以从两个解算器中得到解决方案。我想知道如何解决这个问题。我一直试图找到某种解决方案可能会干扰另一种解决方案的方法,但我不知道这是怎么发生的。

实现:

global dt;
dt = .5;  % going below ~.25 makes the program take a very long time to exit

g = 1;
c_d = 2;
m = 3;

tf = 15;

dudt = @(t, u) g - (c_d/m) * u.^2

[t_euler, u_euler] = euler(dudt, [0, tf], 0);
[t_rk4, u_rk4] = rk4(dudt, [0, tf], 0); % either of this one or rk2
                                        % can be commented out to make the program
                                        % run quickly, but rk2 and rk4 cannot be
                                        % run at the same time
[t_rk2, u_rk2] = rk2(dudt, [0, tf], 0);


%% rk4.m %%

function [t, u] = rk4(odefun, tspan, u0)

t0 = tspan(1);
t = [ t0 ];
t_new = t0;
global dt;
tf = tspan(2);
u_new = u0;

u = [ u0 ];

while (t_new < tf)
   if (t_new + dt > tf)
        dt = tf - t_new;
    end

    k1 = dt * odefun(t_new, u_new);
    k2 = dt * odefun(t_new + dt/2, u_new + k1/2);
    k3 = dt * odefun(t_new + dt/2, u_new + k2/2);
    k4 = dt * odefun(t_new + dt, u_new + k3);

    u_new = u_new + 1/6 * (k1 + 2*k2 + 2*k3 + k4);
    % rk2.m is the same as rk4.m, except u_new = u_new + k2
    % euler.m is also the same, except u_new = u_new + k1
    u = [ u, u_new ];

    t_new = t_new + dt;
    t = [ t, t_new ];
end
end

1 个答案:

答案 0 :(得分:0)

当计算最后一步的间隔长度完全符合tf时,减少全局变量dt,而在另一种方法中,使用现在较小的dt值。根据您的数据,您可能会将新dt缩小到1e-16甚至0

您希望将全局dt视为常量,也许使用局部变量h而不是dt。或者将dt作为函数的参数传递。