ode45 not passing arguments (MATLAB) - matlab

I'm implementing a filtering algorithm in matlab and having some difficulty with parameter passing.
my dynamics are controlled by the function:
function zdot = VortexDynamics(t, z, vorticity)
for ii=1:length(vorticity),
zdot(ii,1) = 1i/(2*pi) * sum( vorticity([1:ii-1,ii+1:end]) .* ( z(ii) - z([1:ii-1,ii+1:end]) ) ./ (abs(z(ii) - z([1:ii-1,ii+1:end]) ).^2 ) ) ;
end
end
I initially compute the trajectories with ode45, with no issue
[t_true,z_true]=ode45(#VortexDynamics, tspan ,z0_true, OPTIONS, vorticity) ;
To implement the filter, I call a function for each time step:
[z_a , Gam, z_ens] = EnKF_nonlinear(num_tracers, Func_Observation, Observations(:,ii),vorticity, [prev_t t], z_ens, Gam, W,R, VortexDynamics, H, N) ;
EnKF_nonlinear is defined by:
function [z_a, Gam_a, z_ens] = EnKF_nonlinear(num_tracers, Func_Observation, Observations,vorticity, tspan, z0_est, Gam0_est, W,R, dynFunc, H,N )
Within EnKF_nonlinear, I need to integrate the dynamics again with ode45:
for ii = 1:N
[t_out, z_out] = ode45(dynFunc, tspan, z0_est(:,ii), vorticity);
z_ens(:,ii) = z_out(end,:) ;
end
but I get the error:
Error using VortexEnKF>VortexDynamics (line 85)
Not enough input arguments.
Error in VortexEnKF (line 63)
[z_a , Gam, z_ens] = EnKF_nonlinear(num_tracers, Func_Observation,
Observations(:,ii),vorticity, [prev_t t], z_ens, Gam, W,R, VortexDynamics, H,
N) ;
but VortexDynamics only requires t,z,vorticity as parameters. I call ode45 the same way in both functions, but I only get the error when I call it through EnKFnonlinear.
I don't see how its not calling with the right number of parameters. Any ideas?

silly me,
I forgot to include a [] in the ode45 call as a placeholder for the precision options.
ode45(dynFunc, tspan, z0_est(:,ii), [], vorticity);
passes the vorticity parameter to dynFunc, and it works fine.

Related

How can I iterate using ode45?

I'm trying to write some matlab code. Why won't my new variable w get accepted so that my function can take another parameter? I want to iterate over the variable that is now 7.8 and use iteration instead.
function dZ=sys(x,Z,w)
c=#(z)4800 - 20.2090 + (17.3368)*z/1000+ (272.9057)*exp(-z*0.7528/1000); % c(z)
c=c(2000);
deg=w;
% Z(1):=z
% Z(2):=u
dZ=zeros(2,1); % a column vector
dZ(1)=Z(2);
dZ(2)=-(c/cosd(7.8))^2*(((-272.9057*0.7528/1000)*exp(-Z(1)*0.7528/1000)) + 17.3368/1000)/...
(4800 - 20.2090 + (17.3368)*Z(1)/1000+ (272.9057)*exp(-Z(1)*0.7528/1000))^3;
end
I get an error message when trying to use the new variable in my function that worked before.
Error using sys (line 4)
Not enough input arguments.
Error in odearguments (line 88)
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ode45 (line 114)
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs, odeFcn, ...
Error in underwater (line 2)
[X,Z]=ode45(#sys,x,[2000 tand(7.8)], 7.8);
I would write the function as follows (although w doesn't appear to be used):
function dZ=sys(t,Z,w)
z = 2000;
c = 4800 - 20.2090 + (17.3368)*z/1000+ (272.9057)*exp(-z*0.7528/1000);
deg=w; % not used?
dZ=zeros(2,1); % a column vector
dZ(1)=Z(2);
dZ(2)=-(c/cosd(7.8))^2*(((-272.9057*0.7528/1000)*exp(-Z(1)*0.7528/1000)) + 17.3368/1000)/...
(4800 - 20.2090 + (17.3368)*Z(1)/1000+ (272.9057)*exp(-Z(1)*0.7528/1000))^3;
end
and then call the ode solver as follows:
[T,Z_sol] = ode45(#(t,Z) sys(t,Z,w),x,[2000 tand(7.8)]);
where w and x are defined in your base or caller workspace.
The ODE solver is expecting a function of two variables. It is looking for a function in the form of:
y' = f(t, y)
So, if you are passing #sys to ode45, it must be a function of only two variables.
In the comments below you reference another question. They use the following call:
[t,N] = ode45(#(t,y) rateEquations(t,y,F), timeSpan, initialConditions)
Using #(t,y) makes a generic function which is a function of two variables. In this example the function rateEquations is called with a fixed F value. So ODE is in fact expecting a function of two variables. If you have a function of more than two variables you can recast it as a function of two variables by copying the technique used in the example you reference. Hope this helps!

MATLAB function fminunc generates errors

I am facing an error when using the function fminunc in the context of a maximum-likelihood estimation. I am afraid that it is very straight forward however my experience with MATLAB is very limited.
The function "normal" contains the log-likelihood function. I seek to estimate the expectation and std. deviation of a normal distribution given the observations stored in the variable x.
function f = normal(X, theta)
mean = theta(1);
sigma = theta(2);
z = (X-mean)./sigma;
f = -(sum(-log(sigma) -(1/2).*z.^2 ));
I basically execute the following code:
theta = [1,1]
f = #(theta)normal(x, theta)
[est, fval, exitflag, output, grad, hessian] = fminunc('normal', x, theta)
The error is the following:
Warning: Struct field assignment overwrites a value with class "double". See MATLAB R14SP2 Release
Notes, Assigning Nonstructure Variables As Structures Displays Warning, for details.
In createOptionFeedback at 34
In prepareOptionsForSolver at 31
In fminunc at 157
Warning: Struct field assignment overwrites a value with class "double". See MATLAB R14SP2 Release
Notes, Assigning Nonstructure Variables As Structures Displays Warning, for details.
In fminunc at 203
Error using feval
Undefined function 'normal' for input arguments of type 'double'.
Error in fminunc (line 254)
f = feval(funfcn{3},x,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. FMINUNC cannot continue.
Unfortunately the manual did not help me to fix the code. Calling
[est, fval, exitflag, output, grad, hessian] = fminunc(f, x, theta)
did not help either. What am I doing wrong?
Thank you in advance!
You have called fminunc with the wrong sintax, please refer to the documentation.
A way to fix your code is by defining the function normal to accept only one parameter: theta.
function f = normal(theta)
global X
mean = theta(1);
sigma = theta(2);
z = (X-mean)./sigma;
f = -(sum(-log(sigma) -(1/2).*z.^2 ));
and call fminunc with
global X
X = randn(100, 1); % A possible time series.
theta0 = [1,1];
[est, fval, exitflag, output, grad, hessian] = fminunc(#normal, theta0);

Matlab fit function error : Function value and YDATA sizes are not equal

I'm trying to use the fit function to estimate a 4 parameters model(P B A R) and meet the error following message and I dont know what does it mean.
Error using fit>iFit (line 367)
Function value and YDATA sizes are not equal.
Error in fit (line 108)
[fitobj, goodness, output, convmsg] = iFit( xdatain, ydatain, fittypeobj, ...
The basic function is
function c1 = c1(x,T,P,B,A,R)
if T == 0
c1=0;
else
G = #(t) 0.5*erfc((P./(4*B*R*t)).^0.5.*(B*R*x-t))...
-1/2*(1+P*x+P*t/(B*R))*exp(P*x).*erfc((P./(4*B*R*t)).^0.5.*(B*R*x+t))...
+(P*t/(pi*B*R)).^0.5.*exp(-P*(B*R*x-t).^2./(4*B*R*t)); %first term in the solution
u = #(t) A*t/(B*R);%.
v = #(t) A*(T-t)/(1-B)/R; %.
e = #(t) 2*(u(t.*v(t))).^0.5; %.
H1 = #(t) exp(-u(t)-v(t)).*(besseli(0,e(t))/B+besseli(1,e(t)).*((u(t)./v(t)).^0.5)/(1-B));
GH = #(t) G(t).*H1(t);
c1 = G(T).*exp(-A*T/(B*R))+A/R*integral(GH,0,T); %int((g*H1),0,T);
end
and another function that based on the foregoing function c1 is
function cm = cm(x,time,P,B,A,R,T1)
for i=1:length(time);
if time(i)<T1
cm(i)=c1(x,time(i),P,B,A,R);
else
cm(i)=c1(x,time(i),P,B,A,R)-c1(x,time(i)-T1,P,B,A,R);
end
end
This function mainly divide the data into two parts for different calculation.
I tried to give a reasonable arbitrary four parameters to run cm to obtain a set of time-c data, use the following code
x=2;
time=0.1:0.1:10;
T1=2;
c=cm(x,time,0.8,0.8,0.8,0.8,T1);
and it works well
after that I tried to use fit function to fit the set of data to obtain the four parameters, using the following code
ft = fittype('cm(x,time,P,B,A,R,T1)','independent','time','problem','x'); % independent variable is time, fixed parameter x
>> [f, gof] = fit( time', c', ft, 'Lower', [0, 0, 0, 1,2], 'Upper', [1, 1, 1, 1,2],'problem',x);
thats when I met the error
Error using fit>iFit (line 367)
Function value and YDATA sizes are not equal.
I checked the input time-c data that obtained from function cm, they have the same size, so I don'k see anything wrong with the input data. I suspect it is the problem with the function that fit function does not work.
Can anyone help me with this problem? Besides, what does it mean by YDATA?
Thank you in advance !

error in fmincon Matlab

`
function [LLF, LL, H ] = garchlike(data)
p=1;
q=1;
if isempty(q)
m=p;
else
m = max(p,q);
end
%this are the parameters
psi=[0.01;0.01];
gamma=[0;0.02;0.02;0];
lambda=[0;0.03;0.03;0];
A=[1;-0.04;-0.03;1];
stdestimate = std(data,1);
data = [stdestimate ; data];
T = size(data,1);
B=(reshape(A,2,2))^-1;
%I am squaring each element of the inverse of A
B2=((reshape(A,2,2))^-1).^2;
%getting the Bl matrix(squared interactions)
Bl=[B2(1,:);B(1,:).*B(2,:);B2(2,:)];
garchc=Bl*psi;
garcha=Bl*(reshape(gamma,2,2))*reshape(A.^2,2,2);
garchb= Bl*(reshape(lambda,2,2))*reshape(A.^2,2,2);
H(1,1).day=[0.001; 0; 0; 0.002; ];
%convert to matrix
H(1,1).day=ivech(H(1,1).day);
for t = (m + 1):T
H(1,t).day= ivech(garchc + garcha*(diag(H(1,t-1).day))+ garchb*(data((t-1),:).^2)');
end
% Getting the loglikelihood
LLF=zeros(1,T);
%the loklikelihood
for t = (m + 2):T
LLF(t)= log(det(H(1,t).day))+ data(t,:)/(H(1,t).day)*data(t,:)';
end
t=(m+2):T;
LLF=-LLF(t);
LL=sum(LLF);
`
I have this function from up and trying to minimize using fmincon:
` [parameters,LLF,EXITFLAG, OUTPUT,HESSIAN] = fmincon('garchlike', [psi;gamma;lambda;A],sumA ,sumB ,[] , [] , LB , UB,[],options, data, p , q);`
I don't know why is not working and gives me an error :
"Error using garchlike
Error using garchlike
Too many input arguments.
Error in fmincon (line 631)
initVals.f = feval(funfcn{3},X,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. FMINCON cannot continue."
"Error using garchlike Too many input arguments." is your problem.
fmincon is calling garchlike([psi;gamma;lambda;A],data, p , q), but your garchlike only takes 1 argument.
Pro tip: learn how to use the debugger. Start by setting dbstop if error.
EDIT: okay, here are some more details. Please read carefully.
Your garchlike takes 1 argument as input, while your fmincon is calling it with 4 arguments.
Either (1) you need to remove those 3 extra arguments (namely, data, p, q) from fmincon, or (2) make garchlike take 3 more arguments!!

ode23 in MatLab - using optional arguments as input

I am trying to learn MatLab on my own. I get most of the concepts regarding solving ODEs, but I am a little unsure about the use of optional arguments as input. I have created the following function:
function xdot = funn(t,x,mu);
if nargin < 3 | isempty(mu)
mu = 1;
end
xdot = t +mu*x;
In addition I have defined:
tspan = [0 2];
x0 = 0;
options = odeset('outputfcn','odeplot');
What I am unsure about is how to change the variable mu when I use the ode23 function. I understand that this should be possible through the input of optional arguments, but I can't get it to work. Say if I write:
[t y] = ode23('funn',tspan,x0,options)
Then everything computes correctly, and we automatically get mu = 1.
But if I want to change this, how do I proceed? I tried writing the following to set mu = 4:
[t y] = ode23('funn',tspan,x0,options,4)
But then I just get the following:
??? Error using ==> funn
Too many input arguments.
Error in ==> odearguments at 98
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ==> ode23 at 171
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs, odeFcn, ...
I did this based on how I understood the procedure as it is written in my textbook, but obviously I'm doing something wrong here. If anyone can explain how I go about changing the parameter mu, and in general how optional arguments p1, p2, ... are used with ode23 I would really appreciate it!
what you need to do is pass data in the function call using anonymous functions:
[t y] = ode23(#(t,y)funn(t,y,4),tspan,x0,options)
I think the problem has nothing to do with ode23. The problem seems to be in that you have not listed varargin in the function definition of funn. It should be:
function xdot = funn(t,x,mu,varargin)
This way funn accepts 3 or more arguments, and you should not get error "Too many input arguments".