How to save a variable computed inside ODE?
11 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Inside an ode function I perform some calculations to compute a variable. I would like to save the values of that variable in a matrix so after the ode is done I can plot it vs time. Because it would not be useful to save the values during the integration, since the function is evaluated several times for each step and a step could be rejected, I followed michio's suggestion to use an Output function.
His solution is also described here: Get variable out of ode 45
function status = myOutputFcn(time, x, flag)
% q: value of variable at each succesfull time step
% q_save: matrix of variable values I want to save for plotting after ode is done
persistent q_save
switch flag
case 'init'
q_save = q;
case ''
q_save = [q_save; q];
case 'done' % when it's done
assignin('base','q_save',q_save); % get the data to the workspace.
end
status = 0;
end
The problem I have with this approach is that after the ode finishes, the size of the time vector is different from the size of the variable 'q_save'. The Output function is called less times than the succesfull steps. For example, time=800x1 and q_save=150x1.
I have also tried declaring tspan in two ways
tspan = linspace(t0,tf,100)
tspan = [t0 tf]
So, how can I save a variable computed inside ODE for every succesfull ode step?
Meaning that I want a value of q for every (time,x) pair that the ode gives me as a solution.
0 Kommentare
Akzeptierte Antwort
Jan
am 28 Mai 2019
Bearbeitet: Jan
am 27 Mai 2022
assignin is a bad programming technique. Producing variables remotely in another workspace is not clean. A better method is to let the integration run regularily and request the wanted values afterwards:
[t, y] = ode45(@fcn, tSpan, y0);
function dy = fcn(t, y)
p = sin(y(2)); % <- The wanted parameter
dy = [2 * t; p / y(1)];
end
If this is the function to be integrated, it must be modified such, that it accepts vectors as input and replies p as output:
function [dy, p] = fcn(t, y)
p = sin(y(2, :)); % <- The wanted parameter [EDITED] y(:,2) --> y(2,:)
dy = [2 .* t; p ./ y(1, :)]; % [EDITED] y(:,1) --> y(1,:)
end
Then:
[t, y] = ode45(@fcn, tSpan, y0);
[~, p] = fcn(t.', y.');
This is much easier than letting the output function create variables remotely.
For some cases the output function is the best choice. Then provide the value as output instead of assignin
function status = myOutputFcn(time, x, flag)
persistent q_save
status = 0;
switch flag
case 'init'
q_save = q;
case ''
q_save = [q_save; q];
case 'done' % when it's done
status = q_save;
q_save = [];
end
end
But now to the actual problem: Unfortunately the ODE integrators reply different time steps, if the output is obtained as a struct. You did not show, how you call the integrator, so the most important detail is missing. (In opposite to this, the code or the output function is not a part of the problem.)
If you want to call the integrator in the form sol = ode45(___), and use a tspan defined as vector also, you have to modify ode45 such that the Output function is called regularily as for the [t,y,te,ye,ie] = ode45(odefun,tspan,y0,options) form. I consider this a bug and sent a bug report to MathWorks some years ago.
You wrote:
"I have also tried declaring tspan in two ways"
tspan = linspace(t0,tf,100)
tspan = [t0 tf]
And what did you observe as effect? How did you call which integrator?
6 Kommentare
Akash Singh
am 14 Apr. 2020
Hey @Jan
Shouldn't it be ?
p = sin(y(2,:)); % <- (Instead of y(:,2))
dy = [2 .* t; p ./ y(1,:)];
Mohammad
am 22 Mai 2020
Bearbeitet: Mohammad
am 22 Mai 2020
I have the following code and I want to get F, G , U , xdot , x1 , x2 and any other variable in the code as outputs but I dont know how. I need them to make other functions and I need their exact dimensions because they are vectors and in some cases matrices . I appreciate it if you could help me out.
function [] = osc()
tspan = 0 : .1 : 20;
x0 = [3;-2];
[t,x] = ode45(@osc2d_2,tspan,x0);
x
plot(t,x)
function xdot = osc2d_2(t,x)
xdot = f(t,x) + g(t,x) * u(t,x)
end
function F = f(t,x)
F = [x(2) ; -x(1) * (pi/2 + atan(5*x(1))) - (5*x(1).^2/(2*(1+25*x(1).^2))) + 4*x(2)]
end
function G = g(t,x)
G = [0;3]
end
function U = u(t,x)
U = -3*x(2)
end
end
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Ordinary Differential Equations finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!