Matlab ODE解算器在一起运行时运行缓慢

Matlab ODE解算器在一起运行时运行缓慢,matlab,runge-kutta,Matlab,Runge Kutta,我为一个类定制了一些ODE解算器的实现。我遇到了一个问题,如果我使时间步长dt小于.2,程序将暂停。但是,如果我注释掉其中一个龙格-库塔解算器,它将执行得非常快,我可以切换注释掉的那一个,以便从两个解算器中得到解。我想知道如何解决这个问题。我一直在试图找到一种方法,一个解算器可能会干扰另一个解算器,但我不知道这是怎么发生的 实施: global dt; dt = .5; % going below ~.25 makes the program take a very long time to

我为一个类定制了一些ODE解算器的实现。我遇到了一个问题,如果我使时间步长
dt
小于
.2
,程序将暂停。但是,如果我注释掉其中一个龙格-库塔解算器,它将执行得非常快,我可以切换注释掉的那一个,以便从两个解算器中得到解。我想知道如何解决这个问题。我一直在试图找到一种方法,一个解算器可能会干扰另一个解算器,但我不知道这是怎么发生的

实施:

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
global-dt;
dt=.5;%低于0.25会使程序需要很长时间才能退出
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);%这一个还是rk2
%可以注释掉以制作程序
%快速运行,但rk2和rk4无法运行
%同时运行
[t_-rk2,u_-rk2]=rk2(dudt[0,tf],0);
%%rk4.m%%
函数[t,u]=rk4(odefun,tspan,u0)
t0=tspan(1);
t=[t0];
t_new=t0;
全球dt;
tf=tspan(2);
u_new=u0;
u=[u0];
while(t_newtf)
dt=tf-t_新;
结束
k1=dt*odefun(新的、新的);
k2=dt*odefun(新建+dt/2,新建+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与rk4.m相同,只是u_new=u_new+k2
%euler.m也相同,只是u_new=u_new+k1
u=[u,u_新];
t_new=t_new+dt;
t=[t,t_新];
结束
结束

当计算最后一步的间隔长度以精确满足
tf
时,减少全局变量
dt
,在另一种方法中使用现在更小的
dt
。根据您的数据,新的
dt
可能小到
1e-16
甚至
0


要将全局
dt
视为常数,可以使用局部变量
h
而不是
dt
。或者将
dt
作为函数的参数传递。

就是这样。非常感谢你!