How to work variables outside function
2 views (last 30 days)
I have an issue here. I'm working with the built-in Differential Equation Solver ode45 and I have it like:
Vs = 14 * (1852 / 3600); % [m/s] Ship approach speed (reasonable value)
t = (0:250); % Manouevre time
y0 = [Vs 0 0 0 0 0 0]; % Inital condition - surge valocity is equal to the approach speed
option = menu('Choose a Manoeuvre:','Straight Run','Exit Menu');
if option == 1 % Choosing Straight Run
[T,Y] = ode45 ('StraightRun' , t , y0); % Calls Straight Run Function
figure % 1 % Ship Trajectory
axis([0 2500 -500 500])
plot(Y(:,4) , Y(:,5));
xlabel('X pos [m]');
ylabel('Y pos [m]');
legend('Ship Trajectory in Straight Run');
elseif option == 2 % Exit the Menu
in which everything is well defined and working fine.
y0 is the array displaying the initial conditions,
t is time.
StraightRun is a function:
function [dy] = StraightRun(t,y)
What I'm hoping for is that I am able to read a few variables outside the function like, for the X and Y position, I have the need to define X_AH and X_AS inside StraightRun.
How can I plot a graph of those (and other) variables outside the function. Without them having to go through ode45.
Walter Roberson on 6 Oct 2022
People often ask to be able to get a copy outside the ode function of all of the values they computed inside the ode function. It is understandable that people ask that... but it turns out to be the wrong thing to do in the great majority of cases.
ode45() and similar functions always internally have a "current" point -- a current time and current set of boundary conditions. At each step, the ode*() functions have a current step size, h. The ode*() evaluate the ode function at several different carefully chosen locations near the current point, with the locations determined by the stepsize relative to the current point. For example they might evaluate at (t*(1+h), boundary*(1+h/5)), (t*(1+2*h), boundary*(1-h/7)) and others. These are not points that are intended to become current points: these are more like a blind person swinging their cane in a careful pattern to figure out the general shape of the land. Using the results of evaluating at several points, ode*() makes a prediction about yet another point, and then it tests whether the prediction is "close enough" to the actual value. If it is close enough to the actual then ode*() "accepts" the point of prediction as the new point, and increases the step-size; if the prediction is not "close enough" then ode*() "rejects" the point and reduces the step size and tries again from where it was. In steep areas it might end up shrinking the stepsize a number of times in a row -- and at each attempt ode45() is evaluating the ode function at 6 different locations.
ode*() records the values at each "accepted" point. But by default, unless the user knew to set the Refine option to 1 (which I had never even heard of until recently), ode*() also takes the ode point and the newly accepted point, and generates several intermediate points that it records in the output, without ever having evaluated the function at those locations. So there are usually output points recorded for which ode*() never evaluated the ode function (so there could not be a record of the values of the intermediate variables at those locations)... and the complete record of values of intermediate variables would include evaluations at lots of locations where ode*() never intended the point to be accepted.
A record of the intermediate variables would therefore typically be incomplete (the function never having been evaluated for 3/4 of the output locations by default), and the record of intermediate variables would typically have a lot of junk, places never intended to be permanent.
Yes, you might potentially want a complete record of the intermdiate variables if you intended to do a surface plot of the shape of the surface. But mostly the complete record would be too useless for practical work.
For these reasons, what the great majority of people should do is not try to record the intermediate variables during ode*() evaluation, and instead should afterwards take each of the output t and y rows and calculate the intermediate variables related to those positions.