ODE solver- can't define a variable used in equation based on previous time steps output

2 views (last 30 days)
I have a second order differential equation set up using ODE45 to solve for displacement and velocity, but I want to put in a set of statements that define one of the variables in the equation depending on the values from the previous time step:
%The if statements to define the variable I think should be like this...
if (z(2) < 0)
P_int(round(t/0.1),1)= -5;
elseif (z(2) > 0)
P_int(round(t/0.1),1)= 5;
else
P_int(round(t/0.1),1)= 0;
end;
%and the general set up of the differential equations
z_dot(1)= z(2); %velocity of membrane
z_dot(2)= 1/mass*((...+...- P_int +..);
z_dot=z_dot';
But when I check the output of P_int it only gets saves the last entry.
Any help would be much appreciated.
  4 Comments
Jan
Jan on 12 Oct 2014
It is still not clear, why you define P_int as a vector and use round(t/0.1) as index.
There is no reason to apply the time consuming import of the CSV file in each iteration, when the contents is store in the global variable F1.
Jeff
Jeff on 13 Oct 2014
I'm fairly new to Matlab so that's just me not understanding properly, from what I can tell I need to use round(t/0.1) in the state space equations to read the correct F1 index for each time step as defined in tspan, I assumed I would also need to define this when creating P_int as an array.
Didn't even think to use CSVread before the loop starts, thankyou!

Sign in to comment.

Answers (3)

Jan
Jan on 12 Oct 2014
It is not meaningful to request the value "of the last time step". The function to be integrated is evaluated several times for each time step and as well the step-size control as the event detection can reject steps and reduce the step width. Therefore "previous time step" is not well defined.
Btw. with the shown code your function to be integrated is not smooth. This is a conflict with the specifications of Matlabs ODE45, see http://www.mathworks.com/matlabcentral/answers/59582#answer_72047 .

Star Strider
Star Strider on 12 Oct 2014
I’m not certain how ‘P_int’ interacts with time, but you can considerably simplify it, completely eliminating the if block:
P_int = @(z2) 5*sign(z2);
q = P_int([-1 0 1]) % Test ‘P_int’
You can simplify it further by eliminating the function expression of it, but the anonymous function form has utility you may want.
  2 Comments
Jeff
Jeff on 13 Oct 2014
Thanks, but when I check the values of P_int it's still only showing as one value instead of switching depending on z(2). Does the use of ODE solver allow for parameters to change like this?
Star Strider
Star Strider on 13 Oct 2014
My pleasure!
The ODE solvers allow parameters to change (but it prefers them to change so as not to introduce abrupt discontinuities). If you also run my ‘q’ line, you will see that it works correctly. (I’d not have posted it otherwise.)
What still mystifies me is the relationship ‘P_int’ has with time. It’s not a function of time, and I have no idea what you’re doing by defining it as such. To the best of my knowledge, in the ODE solvers, time is a discrete, single scalar value at each step. It is not a vector.
Also, as Jan Simon notes, if ‘P_int’ changes your equations in a stepwise fashion during your integration, it introduces discontinuities that make your ODE function not smooth. This causes the solver to behave strangely in some situations (see the link).

Sign in to comment.


Jan
Jan on 13 Oct 2014
There is a substantial misconception in your code. Defining P_int as a vector is free of sense. The values of tspan do not matter inside the function to be integrated and there are much more function evaluations than only to the times of tspan. Using round(t/0.1) as an index looks strange and I cannot believe that this has a connection to the mathematical definition of the problem.
The initial time t0 of your problem is 0.1 . Then round(t/0.1) is 0, such that you cannot use it as an index of the vector P_int at all. For a correct code, t0 must be greater than 5. But when the correctness of the code depends on the input values, a programming error is very likely. Notice that if your code works, P_int would be a vector of zeros except for the last element. But in this line:
z_dot(2)= 1/m_WEC*((F1_interp(round(t/0.1),1)-F_P_mean-P_int1 ...
the left-hand-side is a scalar and the right-hand-side is a vector - except for the fact that "P_int1" is not defined, but I assume this is a typo and "P_int" is meant.
The options are set by odeset(), but you did not provide them to the integrator.
So finally I think, that this code cannot be fixed, but should be rewritten from scratch. It is impossible to guess what you want to achieve by P_int, when we see not working code only. Therefore I recommend to update the question by adding the mathematical formula you want to implement.
  1 Comment
Jeff
Jeff on 14 Oct 2014
OK thanks, looks like I've misunderstood quite a bit. I'll look into how to use an array of values as a forcing function for my differential equations and then try again.

Sign in to comment.

Tags

Community Treasure Hunt

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

Start Hunting!