ODE Events Function Using Persistent Variables

조회 수: 12 (최근 30일)
KostasK
KostasK 2020년 11월 2일
댓글: Ameer Hamza 2020년 11월 3일
Hi all,
I am solving an ODE with an events function, which requires that it gets stopped after a certain criterion is reached in its response, which can only be determined by employing the previous values of the ODE's solution. To demonstrate that problem I have written this simple code below.
The only way I could think of achieving my above objective was by using persistent variables in the ODE events function. This allows me to keep the previous values of the solution whilst the ODE is being solved, and thus terminate it when the specific criterion is reached.
However I run into the following problem: Every time I run the script, either to debug or for any other purpose, the persistent variables are not cleared. So I have to clear them manually, and the process becomes quite tedious, and prone to error as I forget to clear all the appropriate ones some times. I have looked in to how I can clear those variables in the eventsfcn function, however I do not think that its possible to do that automatically.
Hence my question comes in two parts:
  1. Can I clear the persistent variables automatically before I run my code every time?
  2. In case not, is there a better way to achieve my above objective by not utilising persistent variables?
clear ; clc
m = 10 ;
k = 10 ;
f = 10 ;
tol = 1e-3 ;
opts = odeset('Events', @(t, y) eventfcn(t, y, tol)) ;
tspan = [0 10];
y0 = [1 0];
sol = ode15s(@(t, y) odefcn(t, y, m, k, f), tspan, y0, opts);
% Figure
figure
plot(sol.x, sol.y(2,:))
% Events Function
function [v, i, d] = eventfcn(t, y, tol)
persistent Y n
if isempty(n)
n = 0 ;
Y = 0 ;
end
n = n + 1 ;
Y(n) = y(2) ;
if numel(Y) > 2
err = diff(Y(end-1:end))/Y(end) ; % ERROR CRITERION TO STOP SOLVER
else
err = nan ;
end
if err <= tol
v = 0 ;
else
v = 1 ;
end
i = 1 ; % Halt integration
d = 0 ; % Zero can be approached from any direction
end
% ODE Function
function dydt = odefcn(t, y, m, k, f)
dydt = [y(1) ; -(k*y(2) - f)/m] ;
end

채택된 답변

Steven Lord
Steven Lord 2020년 11월 2일
IMO persistent variables is not the right technique to use. One reason why is that the solver does not always evaluate your function with a time that is later than the previous evaluation. If it finds that the error estimate is not within tolerances, it may reject that time step and evaluate your function at an earlier time. So your event function may be comparing the current results against potential future results, not previous results!
What you have is more of a delay differential equation, and for that I'd use the dde23 solver or the ddesd solver. While your ddefun input would not use the "history" input Z the events function you specify in the options structure would.
  댓글 수: 4
KostasK
KostasK 2020년 11월 3일
^^ that is really important info, have you performed any tests on that?
Ameer Hamza
Ameer Hamza 2020년 11월 3일
Yes. I tried it. ODE event function is only called once a step-size is decided in the current iteration, so it will only move in the forward direction.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Ameer Hamza
Ameer Hamza 2020년 11월 2일
Run
clear functions
to re-initialize all the persistent variables.
  댓글 수: 2
KostasK
KostasK 2020년 11월 2일
Does it work for you? Doesn't seem to work for me when I use it after the first line of my code such that
clear ; clc
clear functions
Ameer Hamza
Ameer Hamza 2020년 11월 3일
There does seem to be some issue. Putting
clear functions
inside script does not seems to work everytime. But running it in command window works. This might be a bug.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Ordinary Differential Equations에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by