Switch between 3 different ODE using event functions
Mostrar comentarios más antiguos
Hello, I have a system of 3 different equations of motion of second order which I set up as ODEs. These ODEs should toggle on and off depending on the time dependent parameters y(1) & y(3) as seen below, using 1 or more event functions. But this doesn't work with my current code. It only calculates the last of my 3 ODEs. If I delete the last one it calculates only the 2nd one and if I delete the 2nd and 3rd one it doesn't seem to work at all (which is another problem). I need it to automatically switch back and forth between the 3 ODEs. In the end I need a continous plot of my desired variables as also seen below.
Note: I only now that eqmi is the starting equation but I don't know which of the other 2 equation comes next and the time at which the event occurs. It also can switch back and forth between the 3 ODEs multiple times in one timespan.
This was my first question regarding my problem and might help understanding what I'm actually doing, just theoretically, without events. This was my 2nd question, where the answers helped me a lot and shows some of the progress I made but it still doesn't work as needed.
Can anyone help me out with this? Down below is my current Matlab-Code.
function mfc
clc
%%parameters
m1=10; m2=10; m3=500; k3=300; k2=(k3*(m1+m2))/m3; my=m1/(m1+m2); FW=10; s=0.4; r=0.4; om=5.73; dv0s=2; dv0=dv0s-my*r*om;
%%starting parameters
tspan = [0 100];
tstart = tspan(1);
tend = tspan(end);
y0 = [0 dv0 0 0];
tout = tstart; % copied from ballode example
yout = y0;
teout = [];
yeout = [];
ieout = [];
while tout < tend % main loop
[t,y,te,ye,ie] = ode45(@(t,y) eqmi(t,y), [tstart tend], y0, odeset('Events', @ZustandI));
[t,y,te,ye,ie] = ode45(@(t,y) eqmii(t,y), [tstart tend], y0, odeset('Events', @ZustandII));
[t,y,te,ye,ie] = ode45(@(t,y) eqmiii(t,y), [tstart tend], y0, odeset('Events', @ZustandIII));
nt = length(t); % Accumulate output. Copied from ballode example
tout = [tout; t(2:nt)];
yout = [yout; y(2:nt,1:4)];
teout = [teout; te];
yeout = [yeout; ye];
ieout = [ieout; ie];
y0 = [y(nt,1) y(nt,2) y(nt,3) y(nt,4)]; % new IC and tspan
tstart = t(nt);
end
%%Plots
figure(1); % displacement
plot(teout,yeout(:,1),'b--',teout,yeout(:,3),'r:')
xlabel('time');
ylabel('displacement');
title('mfc');
legend('v2','v3');
figure(2); % velocity
plot(teout,yeout(:,2),'r:',teout,yeout(:,4),'b--')
xlabel('time');
ylabel('velocity');
title('mfcvelocity');
legend('v2dot','v3dot');
figure(3); % v2-v3
plot(teout,yeout(:,1)-yeout(:,3),'r:')
xlabel('time');
ylabel('v2-v3');
title('mfcunterschied');
legend('v2-v3');
%%functions
function dy=eqmi(t,y)
dy=zeros(4,1);
dy(1)=y(2); % v2dot
dy(2)=my*r*om^2*sin(om*t); % Gl. 2a
dy(3)=y(4); % v3dot
dy(4)=(FW*sin(om*t)-k3*y(3))/m3; % Gl. 3a
end
function dy=eqmii(t,y)
dy=zeros(4,1);
dy(1)=y(2); % v2dot
dy(2)=my*r*om^2*sin(om*t)-(k2*(y(1)-y(3)-s))/(m1+m2); % Gl. 2b II
dy(3)=y(4); % v3dot
dy(4)=(FW*sin(om*t)-k3*y(3)+k2*(y(1)-y(3)-s))/m3; % Gl. 3b II
end
function dy=eqmiii(t,y)
dy=zeros(4,1);
dy(1)=y(2); % v2dot
dy(2)=my*r*om^2*sin(om*t)-(k2*(y(1)-y(3)+s))/(m1+m2); % Gl. 2b III
dy(3)=y(4); % v3dot
dy(4)=(FW*sin(om*t)-k3*y(3)+k2*(y(1)-y(3)+s))/m3; % Gl. 3b III
end
%%Events
function [value,isterminal,direction] = ZustandI(t,y)
value = [double(y(1)-y(3)>-s),double(y(1)-y(3)<s)];
isterminal = [1,1];
direction = [-1,1];
end
function [value,isterminal,direction] = ZustandII(t,y)
value = double(y(1)-y(3)>-s);
isterminal = 1;
direction = 0;
end
function [value,isterminal,direction] = ZustandIII(t,y)
value = double(y(1)-y(3)<s);
isterminal = 1;
direction = 0;
end
end
Respuesta aceptada
Más respuestas (1)
Lennart
el 30 de Jul. de 2018
7 comentarios
In my code at, ay, etc are the data from the current integration. They are accumulated by:
t = cat(1, t, at(2:end));
y = cat(1, y, ay(2:end, :));
The first element of at and ay is ignored, because this is the initial value already and contained in t and y before the integration.
By the way: cat(1, x, y] is equivalent to [x; y]
My code had a typo:
[at, ay, ate, aye, aie] = ode45(fcn, [t, tend], y(end, :), opt);
^
Better:
[at, ay, ate, aye, aie] = ode45(fcn, [t(end), tend], y(end, :), opt);
^^^^
Now the correct time span is provided.
This will not work:
if -s<y(end,1)-y(end,3)<s
Matlab computes it from left to right. First step:
-s < y(end,1) - y(end,3)
This is either true or false, which are converted to 1 or 0. Then in te second step:
0 < s or 1 < s
I'm sure you mean:
if (-s < y(end,1) - y(end,3)) && (y(end,1) - y(end,3) < s)
Use the debugger to find out, which index is exceeded. Type this in the command window:
dbstop if error
Run the code again, and when it stops at the error, check the size of e.g. ate.
Jan
el 31 de Jul. de 2018
@Lennart: Did you read my comment concerning the if condition "-s<y(end,1)-y(end,3)<s"?
Categorías
Más información sobre Ordinary Differential Equations en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!