Reading a file that corresponds to time step in solving ODE - matlab

I'm trying to solve an ODE in Matlab and I have the following problem:
my code is as bellow:
xinit=[0.19;25;0;7];
t=0:768:76800; %% 101 cells
[t1,y]=ode45(#Model_Bio,t,xinit);
In the function #Model_Bio I have a parameter that I need to read its corresponding values for each time step (101 values)!
So, My #Model_Bio is somehow as bellow:
load 'mydata'
a=mydata;
.....
the problem is that, when I execute the ode45(#Model_Bio,t,xinit), it calls my function with an automated time step (for example 50 times!) and my problem is that I cannot assign the values for each of my time step (101)!
Also, I think its not a good idea to change the time step of the ode the same as my 101 steps!
Anyone that help me on this is really appreciated!

It seems like you need to provide a wrapper of your data that interpolates it for arbitrary t, for example
my_interp = #(t) interp1(my_data_t, my_data_x, t)
http://se.mathworks.com/help/matlab/ref/interp1.html
and then implement your RHS (#Model_Bio) in terms of my_interp

Related

How to get the zeros of the given equation using fzero in MATLAB?

I have the following function that I wish to solve using fzero:
f = lambda* exp(lambda^2)* erfc(lambda) - frac {C (T_m - T_i)}/{L_f*sqrt(pi)}
Here, C, T_m, T_i, and L_f are all input by the user.
On trying to solve using fzero, MATLAB gives the following error.
Undefined function or variable 'X'.
(where X are the variables stated above)
This error is understandable. But is there a way around it? How do I solve this?
This is answered to the best of my understanding after reading your question as it's not really clear what you are exactly trying and what you want exactly.
Posting the exact lines of code helps a big deal in understanding(as clean as possible, remove clutter). If then the output that matlab gives is added it becomes a whole lot easier to make sure we answer your question properly and it allows us to try it out. Usually it's a good idea to give some example values for data that is to be entered by the user anyway.
First of to make it a function it either needs a handle.
Or if you have it saved it as a matlab file you generally do not want other inputs in your m file then the variable.
So,
function [out]=yourfun(in)
constants=your values; %you can set a input or inputdlg to get a value from the user
out= something something, your lambda thingy probably; %this is the equation/function you're solving for
end
Now since that is not all that convenient I suggest the following
%declare or get your constants here, above the function makes it easier
syms lambda
f = lambda* exp(lambda^2)* erfc(lambda) - frac {C (T_m - T_i)}/{L_f*sqrt(pi)};
hf=matlabFunction(f); %this way matlab automatically converts it to a function handle, alternatively put #(lambda) in front
fzero(hf,x0)
Also this matlab page might help you as well ;)

Matlab ode45 internal step

I'm having doubts at how to use ode45 since I know it uses an internal variable step size. For instance, in my particular case I have a model of ODE's and I use a sampling time of 5 minutes. Hence, inside my main simulation loop I have the following line to obtain the output of my model by solving it using ode45:
[T,X] = ode45(#(t,x) model(t,x,u,data),[t t+scenario.Ts],x0);
Where u are inputs of the model, data is a structure with parameters, x0 are the initial conditions at the current time step and [t t+scenario.Ts] is the initial and final time. My doubt is that between t and t+scenario.Ts the ode45-solver uses variable time steps and thus the way I introduce my input actions u may be affected. Hence, I understand that a value of a particular input u is kept constant through the internal time steps between [t t+scenario.Ts]. Then, if I have for instance a flux, i.e. water into a tank, the time step has a direct effect to this u.
Let me explain this a little more with an example. If over [t t+scenario.Ts] I know that u(1) = 10. Then the real input I should use is u(1)=10/(# of time steps between [t0 tend]). However, since the internal step is variable which input do I have to use?
I hope you understand my problem and can help me out.
You should formulate the inputs such that it is independent of the time- discretization. This shouldn't be a problem if your equations are formulated in continuous time. If the control variable is not constant, then you should be make it explicitly dependent of t and write a function u(t).
If my answer is not sufficient to help you out, please add more details about your application, especially the dynamical model that you are simulating. Then we can help you further.

Using a Jacobian with MatCont

I am trying to solve a very large non-linear problem using the MatCont package. Due to the large number of dimensions, and the non-linear nature, I believe that supplying the Jacobian for my system to the MatCont algorithm will speed things up immensely. However, I cannot get it to recognise that it has a Jacobian to use!
As a minimal working example, I have modified the circle finder from the help documentation to include a Jacobian:
function out = curve()
out{1}=#curvefunc;
out{2}=#defaultprocessor;
out{3}=#options;
out{4}=#jacobian;
out{13}=#adapt;
end
function f=curvefunc(x)
f=x(1)^2+x(2)^2-1;
end
function J=jacobian(x)
disp('USE JACOBIAN')
J=[2*x(1) , 2*x(2)];
end
function varargout=defaultprocessor(varargin)
if nargin>2
varargout{3}=varargin{3};
end
varargout{2}=[0];
varargout{1}=0;
end
function option=options()
option=contset;
end
function [res,x,v]=adapt(x,v)
res=[];
end
I then try to run this program from the command line using
[x,v,s,h,f] = cont(#curve,[1;0]);
However, the response is
first point found
tangent vector to first point found
elapsed time = 0.2 secs
npoints curve = 300
Since I told it to output 'USE JACOBIAN' every time the Jacobian function was called, it is clear that MatCont is not using it.
How do I get the Jacobian to be used?
I solved my own problem! Seems I was quite close to getting it working. The below is a bit of a botch, so if anyone knows how to do it with options please post an answer also.
Firstly I edit the options settings so that when it performs the continuation it only locates the first point:
function option=options()
option = contset;
option = contset(option,'MaxNumPoints',1);
end
its fine for it to do this using numerical Jacobians, the first point is known very well in most problems. This is then called from a script or a function using the following:
[x,v,s,h,f] = cont(#curve,[1;0]);
global cds
cds.options.MaxNumPoints=[];
cds.symjac=1;
[x,v,s,h,f] = cont(x,v,s,h,f,cds);
The first line finds the initial point using numerical Jacobians, as it was set up to do. The continuer is then manually adjusted to firstly have no limit on the maximal number of points (this can be set to any appropriate number) and then the use of the user provided Jacobian is set to 1 (true). The continuer is then resumed with the new settings and uses the Jacobain properly.

how do i use dde23 in MATLAB

Recently I'm working on a genetic circuits modeling which include a delay differential equation:
∂A/∂t=CA*[1−(d/d0)^4]*P(α,τ)− γa*A/(1+f*(A+ I))
∂I/∂t=CI*[1−(d/d0)4]*P(α,τ)− γi*I/1+f*(A+ I)
∂Hi/∂t=bI/(1+kI)−γh*A*Hi/(1+g*A)+D(He−Hi)
∂He/∂t=(−d/1−d)*D*(He−Hi)−µ*He
P(α,τ)= (δ+α*H(t)^2)/(1+k1*H(t)^2)
H(t)=Hi(t−τ)
the polt of the Hi is supposed to oscillate, however the MATLAB code I wrote doesn't seem to work that way. Can anyone please take a look what's wrong with my code?
history=[0;0;0;0];
tau=10;
sol=dde23(#ddex2de,[tau], zeros(4,1),[0,200]);
figure
plot(sol.x,sol.y(3,:),'--r',sol.x,sol.y(2,:),'-b')
function dydt=ddex2de(t,y,Z)
ylag1=Z(:,1);
H=ylag1(3);
x1=y(1);%A
x2=y(2);%I
x3=y(3);%Hi
x4=y(4);%He
dx1dt=CA*(1-(d/d0)^4)*(delta+alpha*(H.^n1))/(1+k1*(H.^n1)) - gammaA*x1/(1+f*(x1+x2));
dx2dt=CI*(1-(d/d0)^4)*(delta+alpha*power(H, n1))/(1+k1*power(H, n1)) - gammaI*x2/(1+f*(x1+x2));
dx3dt=(b*x2/(1+k*x2))-(gammaH*x1*x3/(1+g*x1))+D*(x4-x3);
dx4dt=(-d/(1-d))*D*(x4-x3)-mu*x4;
dydt=[dx1dt,dx2dt,dx3dt,dx4dt]';
end
In your sample code most of the variables are undefined, what are the values of: d d0 CA CI delta alpha ... ? It might be that some of these parameters has a wrong value.
Alternatively try to change time interval tspan, as your input value is [0,200] to something longer, say [0,10000] or more, as your oscillation might take more time than 200 units for one cycle.

MATLAB: alternatives to calling feval in ode45

I hope I am on topic here. I'm asking here since it said on the faq page: a question concerning (among others) a software algorithm :) So here it goes:
I need to solve a system of ODEs (like $ \dot x = A(t) x$. The Matrix A may change and is given as a string in the function call (Calc_EDS_v2('Sys_EDS_a',...)
Then I'm using ode45 in a loop to find my x:
function [intervals, testing] = EDS_calc_v2(smA,options,debug)
[..]
for t=t_start:t_step:t_end)
[Te,Qe]=func_int(#intQ_2_v2,[t,t+t_step],q);
q=Qe(end,:);
[..]
end
[..]
with func_int being ode45 and #intQ_2_v2 my m-file. q is given back to the call as the starting vector. As you can see I'm just using ode45 on the intervall [t, t+t_step]. That's because my system matrix A can force ode45 to use a lot of steps, leading it to hit the AbsTol or RelTol very fast.
Now my A is something like B(t)*Q(t), so in the m-file intQ_2_v2.m I need to evaluate both B and Q at the times t.
I first done it like so: (v1 -file, so function name is different)
function q=intQ_2_v1(t,X)
[..]
B(1)=...; ... B(4)=...;
Q(1)=...; ...
than that is naturally only with the assumption that A is a 2x2 matrix. With that setup it took a basic system somewhere between 10 and 15 seconds to compute.
Instead of the above I now use the files B1.m to B4.m and Q1.m to B4.m (I know that that's not elegant, but I need to use quadgk on B later and quadgk doesn't support matrix functions.)
function q=intQ_2_v2(t,X)
[..]
global funcnameQ, funcnameB, d
for k=1:d
Q(k)=feval(str2func([funcnameQ,int2str(k)]),t);
B(k)=feval(str2func([funcnameB,int2str(k)]),t);
end
[..]
funcname (string) referring to B or Q (with added k) and d is dimension of the system.
Now I knew that it would cost me more time than the first version but I'm seeing the computing times are ten times as high! (getting 150 to 160 seconds) I do understand that opening 4 files and evaluate roughly 40 times per ode-loop is costly... and I also can't pre-evalute B and Q, since ode45 uses adaptive step sizes...
Is there a way to not use that last loop?
Mostly I'm interested in a solution to drive down the computing times. I do have a feeling that I'm missing something... but can't really put my finger on it. With that one taking nearly three minutes instead of 10 seconds I can get a coffee in between each testrun now... (plz don't tell me to get a faster computer)
(sorry for such a long question )
I'm not sure that I fully understand what you're doing here, but I can offer a few tips.
Use the profiler, it will help you understand exactly where the bottlenecks are.
Using feval is slower than using function handles directly, especially when using str2func to build the handle each time. There is also a slowdown from using the global variables (and it's a good habit to avoid these unless absolutely necessary). Each of these really adds up when using them repeatedly (as it looks like here). Store function handles to each of your mfiles in a cell array and either pass them directly to the function or use nested function for the optimization so that the cell array of handles is visible to the function being optimized. Personally, I prefer the nested method, but passing is better if you will use those mfiles elsewhere.
I expect this will get your runtime back to close to what the first method gave. Be sure to tell us if this was the problem or if you found another solution.