在Matlab中使用ode45

在Matlab中使用ode45,matlab,numerical-methods,numerical-integration,Matlab,Numerical Methods,Numerical Integration,我试图模拟由ODE系统控制的物理过程的时间行为。当我将输入脉冲的宽度从20切换到19时,y(1)状态没有耗尽,这在物理上没有意义。我做错了什么?我是否错误地使用了ode45 function test width = 20; center = 100; tspan = 0:0.1:center+50*(width/2); [t,y] = ode45(@ODEsystem,tspan,[1 0 0 0]); plot(t,y(:,1),'k*',t,y(:,2),'k:',t,y(:,3)

我试图模拟由ODE系统控制的物理过程的时间行为。当我将输入脉冲的
宽度
20
切换到
19
时,
y(1)
状态没有耗尽,这在物理上没有意义。我做错了什么?我是否错误地使用了
ode45

function test

width = 20;
center = 100;

tspan = 0:0.1:center+50*(width/2);

[t,y] = ode45(@ODEsystem,tspan,[1 0 0 0]);

plot(t,y(:,1),'k*',t,y(:,2),'k:',t,y(:,3),'k--',t,y(:,4),'k');
hold on;
axis([center-3*(width/2) center+50*(width/2) -0.1 1.1])
xlabel('Time')
ylabel('Relative values')
legend({'y1','y2','y3','y4'});

    function dy = ODEsystem(t,y)
        k1 = 0.1;
        k2 = 0.000333;
        k3 = 0.1;

        dy = zeros(size(y));

        % rectangular pulse
        I = rectpuls(t-center,width);

        % ODE system
        dy(1) = -k1*I*y(1);
        dy(2) = k1*I*y(1) - k2*y(2);
        dy(3) = k2*y(2) - k3*I*y(3);
        dy(4) = k3*I*y(3);
    end
end

你正在不连续地改变你的颂歌的参数。这会导致非常不准确,甚至完全错误的结果。在这种情况下,由于当
I=0
时,您的ODE非常简单,因此像
ode45
这样的自适应解算器将采取非常大的步骤。因此,它很有可能会跨过你注入冲动的区域,而永远看不到它。查看您是否对问题中的代码忽略脉冲的原因感到困惑,即使您已指定
tspan
的(输出)步数仅为
0.1

一般来说,在集成函数中存在任何不连续性(
if
语句、
abs
min
/
max
、函数如
rectpuls
等)是一个坏主意。相反,您需要分解积分并及时分段计算结果。下面是实现以下功能的代码的修改版本:

function test_fixed

width = 19;
center = 100;

t = 0:0.1:center+50*(width/2);
I = rectpuls(t-center,width); % Removed from ODE function, kept if wanted for plotting

% Before pulse
tspan = t(t<=center-width/2);
y0 = [1 0 0 0];
[~,out] = ode45(@(t,y)ODEsystem(t,y,0),tspan,y0); % t pre-calculated, no need to return
y = out;

% Pulse
tspan = t(t>=center-width/2&t<=center+width/2);
y0 = out(end,:); % Initial conditions same as last stage from previous integration
[~,out] = ode45(@(t,y)ODEsystem(t,y,1),tspan,y0);
y = [y;out(2:end,:)]; % Append new data removing identical initial condition

% After pulse
tspan = t(t>=center+width/2);
y0 = out(end,:);
[~,out] = ode45(@(t,y)ODEsystem(t,y,0),tspan,y0);
y = [y;out(2:end,:)];

plot(t,y(:,1),'k*',t,y(:,2),'k:',t,y(:,3),'k--',t,y(:,4),'k');
hold on;
axis([center-3*(width/2) center+50*(width/2) -0.1 1.1])
xlabel('Time')
ylabel('Relative values')
legend({'y1','y2','y3','y4'});

    function dy = ODEsystem(t,y,I)
        k1 = 0.1;
        k2 = 0.000333;
        k3 = 0.1;

        dy = zeros(size(y));

        % ODE system
        dy(1) = -k1*I*y(1);
        dy(2) = k1*I*y(1) - k2*y(2);
        dy(3) = k2*y(2) - k3*I*y(3);
        dy(4) = k3*I*y(3);
    end
end
功能测试\u已修复
宽度=19;
中心=100;
t=0:0.1:中心+50*(宽度/2);
I=矩形(t中心,宽度);%从ODE函数中删除,如果需要打印,则保留
%脉前
tspan=t(t=中心宽度/2&t=中心+宽度/2);
y0=输出(结束,:);
[~,out]=ode45(@(t,y)ODEsystem(t,y,0),tspan,y0);
y=[y;out(2:end,:)];
图(t,y(:,1),'k*',t,y(:,2),'k:',t,y(:,3),'k--',t,y(:,4),'k');
等等
轴([中心-3*(宽度/2)中心+50*(宽度/2)-0.1 1.1])
xlabel(‘时间’)
ylabel('相对值')
图例({'y1','y2','y3','y4'});
函数dy=ODEsystem(t,y,I)
k1=0.1;
k2=0.000333;
k3=0.1;
dy=零(大小(y));
%颂歌系统
dy(1)=-k1*I*y(1);
dy(2)=k1*I*y(1)-k2*y(2);
dy(3)=k2*y(2)-k3*I*y(3);
dy(4)=k3*I*y(3);
结束
结束

另请参见。

谢谢!既然它是僵硬的,难道不应该使用不同的ode解算器吗?或者当你把它分段分解时,它会变成非僵硬的吗?还有,有没有其他方法可以做到这一点,因为如果我尝试模拟一个非常小的宽度(一个delta函数),它会给我一个错误?没有,一个僵硬的解算器可能会稍微可靠一点,但是当你的系统有这样的不连续性时,它不能保证不会遇到同样的问题。ODE基本上需要某种程度的平滑,因此在数学上也是错误的。这个答案中的方法有什么问题?我不知道你说的“消失的小宽度”是什么意思。你在处理离散的浮点值,所以宽度必须是某个有限值。