Unsure about how to use event function in Matlab

眉间皱痕 提交于 2021-01-29 14:39:56

问题


I am trying to plot a state-space diagram, as well as a time-history diagram, of a dynamical system. There's a catch, though. The state-space is divided into two halves by a plane located at x1 = 0. The state-space axes are x1, x2, x3. The x1 = 0 plane is parallel to the x2/x3 plane. The state-space above the x1 = 0 plane is described by the ODEs in eqx3, whereas the state-space below the x1 = 0 plane is described by the ODEs in eqx4.

So, there is a discontinuity on the plane x1 = 0. I have a vague understanding that an event function (function [value,isterminal,direction] = myEventsFcn(t,y)) should be used, but I do not know what values to give to "value", "isterminal", and "direction".

In my code below, I have an initial condition for eqx3, and another initial condition for eqx4. The initial condition for eqx3 is in the upper half of the state-space (x1 > 0). The orbit then hits the x1 = 0 plane and there is a discontinuity, and the eqx4 trajectory begins on this plane, but from a different point from where eqx3 ended.

Can this be done? How do I put it into a code? Do I stop the integration when the orbit reaches the plane x1 = 0?

eta = 0.05;
omega = 25;
tspan = [0,50];
initcond = [2, 3, 4]
[t,x] = ode45(@(t,x) eqx3(t,x,eta, omega), tspan, initcond);
initcond1 = [0, 1, 1]
[t,y] = ode45(@(t,y) eqx4(t,y,eta, omega), tspan, initcond1);

plot3(x(:,1), x(:,2), x(:,3),y(:,1), y(:,2), y(:,3))
xlabel('x1')
ylabel('x2')
zlabel('x3')

%subplot(222)
%plot(t, x(:,1), t,x(:,2),t,x(:,3),'--');
%xlabel('t')

function xdot = eqx3(t,x,eta,omega)
  xdot = zeros(3,1);
  xdot(1) = -(2*eta*omega + 1)*x(1) + x(2) - 1;
  xdot(2) = -(2*eta*omega + (omega^2))*x(1) + x(3) + 2;
  xdot(3) = -(omega^2)*x(1) + x(2) - 1;
  
end

function ydot = eqx4(t,y,eta,omega)
  ydot = zeros(3,1);
  ydot(1) = -(2*eta*omega + 1)*y(1) + y(2) + 1;
  ydot(2) = -(2*eta*omega + (omega^2))*y(1) + y(3) - 2;
  ydot(3) = -(omega^2)*y(1) + y(2) + 1;
  
end
 
function [value,isterminal,direction] = myEventsFcn(t,y)
   value = 0
   isterminal = 1
   direction = 1

end

回答1:


Without events, using a close-by smooth system

First, as the difference between the systems is the addition or subtraction of a constant vector it is easy to find an approximate smooth version of the system using some sigmoid function like tanh.

  eta = 0.05;
  omega = 25;
  t0=0; tf=4;
  initcond = [2, 3, 4];
  opt = odeset('AbsTol',1e-11,'RelTol',1e-13);
  opt = odeset(opt,'MaxStep',0.005); % in Matlab: opt = odeset('Refine',10);
  [t,x] = ode45(@(t,x) eqx34(t,x,eta, omega), [t0, tf], initcond, opt);

  clf;
  subplot(121);
  plot3(x(:,1), x(:,2), x(:,3));
  xlabel('x1');
  ylabel('x2');
  zlabel('x3');

  subplot(122);
  plot(t, 10.*x(:,1), t,x(:,2),':',t,x(:,3),'--');
  xlabel('t');

  function xdot = eqx34(t,x,eta,omega)
    S = tanh(1e6*x(1));
    xdot = zeros(3,1);
    xdot(1) = -(2*eta*omega + 1)*x(1) + x(2) - S;
    xdot(2) = -(2*eta*omega + (omega^2))*x(1) + x(3) + 2*S;
    xdot(3) = -(omega^2)*x(1) + x(2) - S;
  end

resulting in the plots

As is visible, after t=1.2 the solution is essentially constant with x(1)=0 and the other coordinates close to zero.

With events

If you want to use the event mechanism, make ODE and event function dependent on a sign parameter S denoting the phase and the direction of the zero crossing.

 eta = 0.05;
 omega = 25;
 t0=0; tf=4;
 initcond = [2, 3, 4];
 opt = odeset('AbsTol',1e-10,'RelTol',1e-12,'InitialStep',1e-6);
 opt = odeset(opt,'MaxStep',0.005); % in Matlab: opt = odeset('Refine',10);
 T = [t0]; TE = [];
 X = [initcond]; XE = [];
 S = 1; % sign of x(1)
 while t0<tf
    opt = odeset(opt,'Events', @(t,x)myEventsFcn(t,x,S));
    [t,x,te,xe,ie] = ode45(@(t,x) eqx34(t,x,eta, omega, S), [t0, tf], initcond, opt);
    T = [ T; t(2:end) ]; TE = [ TE; te ];
    X = [ X; x(2:end,:)]; XE = [ XE; xe ];
    t0 = t(end);
    initcond = x(end,:);
    S = -S % alternatively = 1-2*(initcond(1)<0);
 end
 disp(TE); disp(XE);

 subplot(121);
 hold on;
 plot3(X(:,1), X(:,2), X(:,3),'b-');
 plot3(XE(:,1), XE(:,2), XE(:,3),'or');
 hold off;
 xlabel('x1');
 ylabel('x2');
 zlabel('x3');

 subplot(122);
 plot(T, 10.*X(:,1), T,X(:,2),':',T,X(:,3),'--');
 xlabel('t');

 function xdot = eqx34(t,x,eta,omega,S)
  xdot = zeros(3,1);
  xdot(1) = -(2*eta*omega + 1)*x(1) + x(2) - S;
  xdot(2) = -(2*eta*omega + (omega^2))*x(1) + x(3) + 2*S;
  xdot(3) = -(omega^2)*x(1) + x(2) - S;
 end

 function [value,isterminal,direction] = myEventsFcn(t,x,S)
   value = x(1)+2e-4*S;
   isterminal = 1;
   direction = -S;
 end

The solution enters a sliding mode for 1.36 < t < 1.43 where (theoretically) x(1)=0 and the vector field points to the other phase from both sides. The theoretical solution is to take a linear combination that sets the first component to zero, so that the resulting direction is tangential to the separating surface. In the first variant above the sigmoid achieves something like this automatically. Using events one could add additional event functions that test the vector field for these conditions, and when they cease to persist.

A quick solution is to thicken the boundary surface, that is, test for x(1)+epsilon*S==0 so that the solution has to cross the boundary surface before triggering the event. In sliding mode, it will be immediately pushed back, giving a ping-pong or zigzag motion. epsilon has to be small to not perturb the solution too much, however not too small to avoid the triggering of too many events. With epsilon=2e-4 octave gives the following solution in a close-up to the sliding interval

The octave solver, and in some way also Matlab, will not trigger a terminal event if it happens in the first integration step. For that reason the InitialStep option was set to a rather small value, it should be about 0.01*epsilon. The full solution looks now similar to the one obtained in the first variant



来源:https://stackoverflow.com/questions/60309851/unsure-about-how-to-use-event-function-in-matlab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!