Can anyone tell me how to implement these timevarying state space equations in matlab
Mostra commenti meno recenti
Risposta accettata
Più risposte (6)
Bilal
il 22 Ott 2014
0 voti
26 Commenti
Yes, I'm pretty sure we can keep adding to the answer once you accept it. Worst case, email me afterwards.
Thanks for the paper. But you do add Emin, Emax, and tc as known constants, correct? So tn is nothing else than t/Tmax, meaning that instead of writing E(t) = (Emax-Emin)*En(tn)+Emin, write it as a function of t, i.e.
E = @(t) ((Emax - Emin) * En(t/Tmax))+Emin;
Of course, if you really want, you could define
tn =@(t)t/Tmax
as well an use it like this, but I see no reason to do this. The only reason they introduce tn is that it makes the formula of En(tn) more compact for the paper.
*EDIT* Just realized this may not have come across clearly: We are only talking about ode45 here. If you want to plot the functions, you of course have to tell 'plot' at which points you want your functions evaluated. But let's maybe stick to solving the ode first, and then we can tackle the plotting part.
Ced
il 22 Ott 2014
yes, exactly.
Bilal
il 22 Ott 2014
Bilal
il 22 Ott 2014
Ced
il 22 Ott 2014
Yes, the error message is not so intuitive. The problem is that in your definitions of En(t), C(t), etc., which are functions of "t", you are using "tn". You did define "tn" as a function, which is fine, but this means that you have to pass an argument when you use it. In short: just replace "tn" by "tn(t)" in your definitions of En, E, C, etc., and you're good to go.
I'll have to pass for today, but I'll be back tomorrow.
Cheers
Bilal
il 22 Ott 2014
Ced
il 23 Ott 2014
Yes, that's unfortunate :D. My best guess at the moment: Your initial conditions are still set as "randn" as far as I can tell. 'randn' takes random values from the normal distribution. If nothing is known, this is usually as good a guess as any other, but since you have a biological system, there may be some limitations to what makes sense.
Things you could do:
- Check all equations (in particular, signs)
- Check if the initial conditions are given somewhere in the paper.
- check if there are any upper/lower bounds on the values of x (e.g. a negative pressure makes little sense to me), make sure the initial conditions fulfil them
- There is most likely a division by zero somewhere. Try to find out where. To do this, you can e.g. write 'keyboard' in your code. The run will then pause there, and you can evaluate the code one line at a time by pressing f10. There are lots of other debugging tools for matlab, you can check the documentation for a list.
- your time scale seems to be similar to the ones in the paper, so that's good, and since the curve is very smooth and does not have high frequency noise or so, I don't think it's the solver tolerance. You could however try another solver (look at 'doc ode45' for what other versions are available), but since your solution is already NaN after 1 timestep, I don't think it's the solver.
Bilal
il 23 Ott 2014
Ced
il 23 Ott 2014
Glad it works! Not sure I understand, no. What do you mean by "plot here"? Since E, C, and dC are only functions of time, they are not dependent on your solution from the ode, so I'm not sure what exactly you want to check.
But you can plot them whenever you like using "plot", e.g.
plot(t_sim,E(t_sim))
Bilal
il 23 Ott 2014
Bilal
il 23 Ott 2014
Sounds good. Yes, solutions can look strange sometimes because they apply weird "simplifications". You could also simply derive it by hand, the first derivative is still fairly simple, and then compare the plot to the one from your online solution. Let me know if you need help with that.
Bilal
il 25 Ott 2014
Ced
il 26 Ott 2014
I will have some time in a few hours, I'll let you know!
ok, had a look. A new version is in the attachments, but a couple of (hopefully) useful comments:
The error you are (were) getting is:
Error using vertcat Dimensions of matrices being concatenated are not consistent.
Error in tmp>ode_sys (line 60) Ac = [ -dC/C 0 0 0 0 ;
Error in tmp>@(t,x)ode_sys(t,x,C(t),dC(t),p(x))
[ ... ]
Error in tmp (line 45) [ Tout, Xout ] = ode45(dx,t_sim,x0);
Generally speaking, the first line tells you what kind of error it is, and then goes on telling you where this error was produced. In this case, the error is that "dimensions of matrices being concatenated are not consistent", and it happens in (line 60).
This is quite a common error which means that you are trying to concatenate two matrices/vectors (meaning "insert" them into the same array), but that there dimensions don't match. This usually happens when you messed up indices somewhere in a for loop or so. Unfortunately, in your case, there's a bigger problem. What you are doing with "diff" is that you are approximating the derivative by finite differences. But ode45 evaluates your function at a single timestep, and with only one value of C given, computing a finite difference is impossible.
I somewhat fixed your code with a hack which I think should work, but I would really encourage you to use the "real" derivative. I'll see if I find some time tomorrow and set it to you.
A couple of useful side notes:
1) The last index can be reach through "end", e.g.
x(1:end-1) % x without last element
which is a bit easier than your t(1:length(t)-1) construct :).
2) I wouldn't implement a function C referring to a previous version of C. I'm actually surprised this even worked. I simply omitted dC and plugged C directly into CC. If for some reason, you ever had to do that, I would use two different names, e.g. C0 and C1
Cheers
Bilal
il 27 Ott 2014
Ced
il 27 Ott 2014
Hi
Sorry it took me so long. I wanted to check our equations, but am running into big problems, nothing seems to match. Probably some stupid typo somewhere. Anyway... to your question: Tout is a vector of time, Xout is a matrix containing your states. So x1, x2, ... are in Xout. dy in our code is x_dot.
if your run the function from the matlab command line (you need to comment out "clear all" first in the function, otherwise it won't work), each xi will be in one column, i.e.:
[ t_out, x_out ] = run_ode;
x1 = x_out(:,1);
x2 = x_out(:,2);
etc.
Bilal
il 27 Ott 2014
Bilal
il 27 Ott 2014
Ced
il 28 Ott 2014
Ah, yes. Two things:
1. When computing the derivative with finite differences, you need to take the same "step size" on the top and bottom, e.g. for f([t t+dt1])/dt2, both dt1 and dt2 have to be the same (my mistake, sorry).
Replace the following lines in your code, this should solve the problem:
CC = @(t,ts) diff(C(t))./(C(t(1:end-1))*ts); % dC./C
[...]
plot(t(1:end-1),-CC(t,ts));
[...]
Ts = 0.0025;
dx = @(t,x)ode_sys(t,x,C(t),CC([t t+Ts],Ts),p(x)); % Reverse order!
2. Then, concerning the non-changing data: Have a look at your time step Ts and the end time. You are only simulating for 1e-10 seconds! During this time interval, nothing changes. You could e.g. set Ts = 0.0025 and t_end = 1 for one cycle, but that depends on what you want.
Bilal
il 28 Ott 2014
Bilal
il 28 Ott 2014
Bilal
il 28 Ott 2014
Ced
il 28 Ott 2014
I'm sorry, I don't understand your question(s). Why don't you just plot it? That way, you'll see how many cycles appear? So... just to e.g.
plot(Tout,Xout(3,:))
And if it's not enough/too many cycles, adapt your end time accordingly (or simply only plot a particular section of the results).
Bilal
il 29 Ott 2014
0 voti
4 Commenti
Ced
il 29 Ott 2014
Yes, of course. Since you know Xout, you can also compute p, r, and everything else. If you want to have them as "standard outputs" like Xout, you could do something like :
Nt = length(Tout);
Pout = zeros(Nt,2);
Rout = r(Xout);
for i = 1:Nt
Pout(i,:) = p(Xout(i,:));
end
after Tout and Xout have been computed and add them to the output, i.e.
function [Tout, Xout, Pout, Rout] = run_odebq
IMPORTANT: You will need to change your ramp function to an element-wise evaluation, otherwise you get some errors. Meaning it should look like this (note the '.'):
r = @(x)x.*(-x<0); % Ramp function
Once you have Pout, Rout, you can plot them, do some analysis or whatever (you can of course also plot them directly in the function without passing them as outputs)
Bilal
il 29 Ott 2014
Ced
il 30 Ott 2014
No, I'm afraid I'm a bit caught up in work myself at the moment. I'll have a look at it if I find the time. I haven't read the paper in detail, but maybe they have something like mod(t,HR) or so? Maybe you can try to find out what function is not periodic, and if not, why.
Bilal
il 31 Ott 2014
0 voti
Ced
il 31 Ott 2014
I mean, that would certainly work. simply replace every instance of "t" by "mod(t,60/HR)" when calling ode_sys, so
dx = @(t,x)ode_sys(mod(t,60/HR),x,C(mod(t,60/HR)), ...
The question is if this makes sense. That's something you could ask your professor or discuss with some phd student. Skimming the paper, I cannot find any reference that they artificially periodicized (that's a word now ^^) their solutions. But then again, little details are often omitted (or forgotten) when describing simulations in papers.
12 Commenti
Bilal
il 31 Ott 2014
Bilal
il 31 Ott 2014
Bilal
il 31 Ott 2014
Bilal
il 31 Ott 2014
Ced
il 2 Nov 2014
Great!
What you want the ramp function r(x) to do is the following: If the value x is greater or equal than zero, set r(x) = x, else set r(x) = 0. The
(-x<0)
part returns a logical value, which is 1 if (0 <= x) and zero else (if used in an algebraic expression, the logical is automatically interpreted as a double). I wrote it as -x<0 to have an inequality instead of a <=.
So, x*(-x<0) is x*1 if 0 <= x and 0 else, which is just what the ramp function does.
Now, to the changing period: This is a little strange. To be fair, the first period in the paper is also slightly different than the others. Check if the mod(...) arguments are the same everywhere in your code. Unfortunately, it could be that the equations are very sensitive to changes in the derivative, and since our dC is approximated, that could explain the differences. You could test this by changing the magnitude of the step in the finite difference computation (the second argument of dC). If that does not change anything, let me know, and I'll think a bit harder :)
Bilal
il 3 Nov 2014
Bilal
il 3 Nov 2014
Ced
il 3 Nov 2014
hm... looks fishy to me, but I can't really put my finger on the reason. One thing I would certainly change is that you should not use randn for your initial conditions, since your pressure should not be negative.
And then, although I don't think that the derivative is really the problem, there is a strong dependency on it, as the solution changes when I change the discretization. That should not happen. If you could find the algebraic derivative, that would certainly help a lot. If you can't figure out the correct derivative by hand, you could try using the symbolic math toolbox, e.g.
syms t_smb real % define symbolic variables
f = t_smb.^2 + 3; % define symbolic expression (would be your function)
df = diff(f,t_smb); % compute derivative wrt t_smb
df_fun = matlabFunction(df); % transform into matlab function
Note that here, "diff" is overloaded and computes the algebraic derivative and not the finite difference, since your input is symbolic.
Also, I actually find it a bit weird to have mod(t,60/HR). It would make more sense to have mod(t,Tmax) since t is "normalized" by Tmax. However, this diverges. Do you have anyone you can ask (supervisor or so) about this periodicity and normalization who is working in that field? While I know how ode works, I don't really know anything about heart simulations.
Bilal
il 4 Nov 2014
Bilal
il 6 Nov 2014
Bilal
il 7 Nov 2014
Bilal
il 13 Nov 2014
0 voti
Categorie
Scopri di più su Mathematics in Centro assistenza e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!






