Matlab 使用ODE事件位置并使用事件处的解决方案作为ode45的输入

Matlab 使用ODE事件位置并使用事件处的解决方案作为ode45的输入,matlab,ode,Matlab,Ode,我一直在尝试重新创建一个在以下论文中发现的绘图: 我试图重新创建的图位于第267页右上角,具体是$x(t)$和$t$ 本文使用的颂歌是 $$m\ddot{x}(t)+k_0x(t)+k_1(x(t)-x_s)=0$$ 其中,$x_s$是由$x_s=x(t_r)$定义的分段常量函数,只要$\dot{x}(t_r)=0$ 使用值$m=1、k_0=150、$k_1=50生成绘图$ 解决此问题的代码如下所示: tstart = 0; tfinal = 2; tspan = [tstart tfina

我一直在尝试重新创建一个在以下论文中发现的绘图:

我试图重新创建的图位于第267页右上角,具体是$x(t)$和$t$

本文使用的颂歌是 $$m\ddot{x}(t)+k_0x(t)+k_1(x(t)-x_s)=0$$ 其中,$x_s$是由$x_s=x(t_r)$定义的分段常量函数,只要$\dot{x}(t_r)=0$

使用值$m=1、k_0=150、$k_1=50生成绘图$

解决此问题的代码如下所示:

tstart = 0;
tfinal = 2;

tspan = [tstart tfinal];
u0 = [1; 0];
refine = 4;
options = odeset('Events', @resetevent , 'OutputSel' , 1, 'Refine', refine);

tout = tstart;
uout = u0';
teout = [];
ueout = [];
ieout = [];
ue = [];
while tout(end) < tfinal

% Solve until the first terminal event.
[t, u, te, ue, ie] = ode45(@(t,u) sys(t, u, ue), [tstart tfinal] , u0, options);

% Accumulate output.  This could be passed out as output arguments.

nt = length(t);
tout = [tout; t(2:nt)];
uout = [uout; u(2:nt,:)];
teout = [teout; te];          % Events at tstart are never reported.
ueout = [ueout; ue];
ieout = [ieout; ie];


% Set the new initial conditions, with .9 attenuation (??).

u0 = [u(nt,1) ; u(nt,2)];

% A good guess of a valid first timestep is the length of the last valid
% timestep, so use it for faster computation.  'refine' is 4 by default.
options = odeset(options,'InitialStep',t(nt)-t(nt-refine),...
    'MaxStep',t(nt)-t(1));

tstart = t(nt);
end

figure(1)
set(gcf,'units','normalized','outerposition',[0 0 1 1])

subplot(2,1,1);
plot(tout,uout(:,1));
title(['Time history of $x(t)$'],'interpreter','latex','fontsize',20)
ylabel('$x$','interpreter','latex','fontsize',15)
xlabel('$t$','interpreter','latex','fontsize',15)
xlim(tspan)

grid on
hold on

subplot(2,1,2);
plot(tout,uout(:,2))
title('Time history of $\dot{x}(t)$','interpreter','latex','fontsize',20)
ylabel('$\dot{x}$','interpreter','latex','fontsize',15)
xlabel('$t$','interpreter','latex','fontsize',15)
xlim(tspan)

grid on
hold on

subplot(2,1,1);
stairs(teout,ueout(:,1))
title('Time history of $x_s(t)$','interpreter','latex','fontsize',20)
xlabel('$t$','interpreter','latex','fontsize',15)
xlim(tspan)

grid on
hold on

% 
function dz = sys(t, z , us)
dz = zeros(2,1);
if isempty(us) == 1
    us = 0;
else
    us;
end

% if isempty(us) == 1
%     us = 0;
% elseif us(1) == 1
%     us(1) = -1;
% else
%     us;
% end

m = 1;
k0 = 150;
k1 = 50;

dz(1) = z(2);
dz(2) = - ((k0 + k1)/m)*z(1) + (k1/m)*us(1);
end


% Reset Event Function
function [lookfor, stop, direction] = resetevent(t, z)
% Locate the time when xdot passes through zero in any direction
% and stop integration.
lookfor = z(2);  % when xdot = 0
stop = 1;        % stop the integration
direction = 0;   % any direction
end
tstart=0;
tfinal=2;
tspan=[tstart tfinal];
u0=[1;0];
精炼=4;
选项=odeset('Events',@resetevent',OutputSel',1',Refine',Refine);
tout=tstart;
uout=u0';
teout=[];
ueout=[];
ieout=[];
ue=[];
当兜售(结束)时
%求解直到第一个终端事件。
[t,u,te,ue,ie]=ode45(@(t,u)系统(t,u,ue),[tstart tfinal],u0,选项);
%积累产量。这可以作为输出参数传递。
nt=长度(t);
tout=[tout;t(2:nt)];
uout=[uout;u(2:nt,:)];
teout=[teout;te];%从未报告tstart上的事件。
ueout=[ueout;ue];
ieout=[ieout;ie];
%设置新的初始条件,衰减为.9(?)。
u0=[u(nt,1);u(nt,2)];
%有效的第一个时间步的准确猜测是最后一个有效时间步的长度
%timestep,因此使用它可以加快计算速度。”“优化”默认为4。
选项=odeset(选项,'InitialStep',t(nt)-t(nt优化),。。。
‘MaxStep’,t(nt)-t(1));
tstart=t(nt);
结束
图(1)
集合(gcf、'units'、'normalized'、'outerposition'、[0 0 1 1])
子批次(2,1,1);
地块(tout,uout(:,1));
标题(['x(t)$'的时间历史,'transparer','latex','fontsize',20)
ylabel(“$x$”、“解释器”、“乳胶”、“字体大小”,15)
xlabel(“$t$”、“解释器”、“latex”、“fontsize”、15)
xlim(tspan)
网格化
等等
子批次(2,1,2);
地块(tout,uout(:,2))
标题($\dot{x}(t)$,“解释器”,“乳胶”,“字体大小”,20的时间历史)
ylabel(“$\dot{x}$”、“解释器”、“乳胶”、“fontsize”、15)
xlabel(“$t$”、“解释器”、“latex”、“fontsize”、15)
xlim(tspan)
网格化
等等
子批次(2,1,1);
楼梯(teout,ueout(:,1))
标题($x_s(t)$的时间历史,'transparer','latex','fontsize',20)
xlabel(“$t$”、“解释器”、“latex”、“fontsize”、15)
xlim(tspan)
网格化
等等
% 
函数dz=sys(t,z,us)
dz=零(2,1);
如果isempty(us)=1
us=0;
其他的
美国;
结束
%如果isempty(us)=1
%us=0;
%elseif us(1)=1
%us(1)=-1;
%否则
%美国;
%结束
m=1;
k0=150;
k1=50;
dz(1)=z(2);
dz(2)=-((k0+k1)/m)*z(1)+(k1/m)*us(1);
结束
%重置事件功能
函数[查找、停止、方向]=resetevent(t,z)
%确定xdot在任何方向通过零点的时间
%停止整合。
查找=z(2);%当xdot=0时
停止=1;%停止整合
方向=0;%任何方向
结束
使用
u0=[1;0]
生成的绘图为

使用
u0=[1;-eps]
生成的绘图为

u0=[u(nt,1);0]
作为重新启动初始条件生成的绘图 我有几个与此相关的问题:

  • 让我困惑的是,出于某种原因,Matlab确实找到了 $\dot{x}$的第一个零,并输入到函数中,但 上的文档称它跳过了第一个 终点事件。这可能是我做错了什么,但我不能 看看是什么

  • 如果您查看$\dot{x}(t)$的绘图,在它通过零的点处,初始条件从 最后一个值以结束,它在绘图中给出了一个扭结,这意味着导数不匹配。我试过了 使用0作为初始值,这对我来说很有意义,但它会导致解算器发散。然而,衍生品似乎更匹配。 我不确定0.9衰减是做什么的,我试着搞砸了 那是徒劳的

  • 如果您在函数
    sys
    中使用注释代码,它将强制执行
    us
    的值,并且绘图将与本文中的一样,但它太具体了,不是我想做的,因为我想将重置的想法扩展到不同的ODE

    我还注意到,如果我将初始条件设置为
    u0=[1;-eps]
    ,它实际上会从零开始,但不会精确地注册为零,从而生成正确的绘图


    谢谢你的帮助

    这个问题太长了吗?我可以做些什么来获得一些帮助,了解ODE事件位置的情况吗?你的问题不在于如何使用软件,而在于软件对解决方案的影响。这有点离题,在scicomp.stackexchange.com上您可能会获得更好的成功。-为了更好地理解,您应该说
    xs(t)
    是分段常数,其值
    xs(t)=x(te)
    在顶点
    dotx(te)=0
    --访问问题中提到的图表会有所帮助。(是的,二阶导数的跳跃会导致一阶导数的扭曲。)如果您愿意设置,则应将最大时间步长设置为振荡周期的三分之一或四分之一
    m*u'+(k0+k1)*u=0
    。也就是说,
    dtmax=pi/2/sqrt((k0+k1)/m)
    。感谢您的回复和建议。为了清晰起见,我将进行必要的修改。我还将查看scicomp.stack.exchange.com并了解它的发展方向。至于问题1),确切的语言是“在集成的第一步中”,但您的第一个事件是在第一步之前的初始条件中。这意味着使用
    u0=[1;+eps]
    可以满足此限制,并忽略第一次过零。这是一个太长的问题吗?我可以做些什么来获得一些帮助,了解ODE事件位置的情况吗?你的问题不在于如何使用软件,而在于软件对解决方案的影响。这有点离题了,你可能会在sci取得更好的成绩