Solving nonlinear system of differential equations in matlab usin ODE45 - matlab

i am trying to solve a system of nonlinear differential equation using ODE45 MATLAB , i did that many times successfully , but this time i get the following error and i really don't know what is wrong i am confused compeletly. here are the codes.
%% this is the error:
Subscript indices must either be real positive integers or logicals.
Error in non_L_ss (line 6)
(-Fk*(ds0+x(3)-x(1))+Fk*ds0-Fc(x(4)-x(2)))/ms +Fa/ms ] ;
Error in odearguments (line 87)
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ode45 (line 115)
odearguments(FcnHandlesUsed,solver_name,ode, tspan,y0,optio varargin);
Error in solve (line 50)
[t X]=ode45(#non_L_ss,t_span,IC);
%% the equations be defined in a function:
function dX=non_L_ss(t,x)
global Fk Fc kt Fa q ds0 ms mu
dX=[ x(2);
(Fk*(ds0+x(3)-x(1))-Fk*ds0+Fc*(x(4)-x(2))-kt*x(1))/mu-Fa/m-kt*q/mu ;
x(4);
(-Fk*(ds0+x(3)-x(1))+Fk*ds0-Fc(x(4)-x(2)))/ms +Fa/ms ] ;
end
%% and here the function be called to solve by ODE45:
clear
clc
global Fk Fc kt Fa q ds0 ms mu qdot v2
mu = 100 ;
ms = 1242 ;
k1s = 80000 ;
k2s = 32000 ;
kt = 405000 ;
c1s = 4000 ;
c2s = 1600 ;
v = 20 ;
Gq = 256e-6 ;
ds0 = 0.1538 ;
a = 1 ;
b = 0.001 ;
n0 = 0.1 ;
f0 = 0.011*v ;
w = 0.5 ;
Fa = 2000 ;
q = 0.05 ;
xs = 0.1 ;
xu = 0.1 ;
dxs = 0.1 ;
dxu = 0.2 ;
Fk = k1s+k2s*(ds0+xs-xu).^2 ;
if dxs >= dxu
Fc = c1s ;
elseif dxs < dxu
Fc = c2s ;
end
t_span=[0 1];
IC=[2 3 2 2];
[t X]=ode45(#non_L_ss,t_span,IC);

Subscript indices must either be real positive integers or logicals.
Error in non_L_ss (line 6)
(-Fk*(ds0+x(3)-x(1))+Fk*ds0-Fc(x(4)-x(2)))/ms +Fa/ms ] ;
means that you use something as an indexed array with a non-integer index. Which probably means that the object is no array at all. I'd propose to replace
Fc(x(4)-x(2))
by
Fc*(x(4)-x(2))
to try to solve this issue.

Related

Implementing an Optimization problem using matlab

I am trying to implement an Optimization problem using matlab
Where N=100 , M=(N-1/k) and L=50.
N=100;
L = 50;
for K= 101:1:1000
M = (N-1)/K;
R=#(x) -((1./x(2)).*(N- (x(1).*M)-((min ( N./(L.*x(2)), K)-x(1))*(max(0,N-(L.*x(2).*x(1)))))/(x(1)+(min ( N./(L.*x(2)), K)-x(2)))) - (max(0,N-(L.*K*x(2)))));
LB = [1 1];
b=1:min((ceil(N/L)), K) ;
UB = [min((ceil(N./L)), K) ((N./(L*b))) ];
options = optimoptions('fmincon','Algorithm','interior-point'); % run interior-point algorithm
[xopt, vopt] = fmincon(R,1,[],[],[],[],LB,UB,[],options);
v(K) = -vopt;
end
plot(101:1000,v,'v-','LineWidth',2);
xlabel('Number of Users (K)');
ylabel('Delivery Rate (R)');
The following error appears:
Warning: Length of lower bounds is > length(x); ignoring extra bounds.
> In checkbounds (line 27)
In fmincon (line 318)
In R1 (line 19)
Warning: Length of upper bounds is > length(x); ignoring extra bounds.
> In checkbounds (line 41)
In fmincon (line 318)
In R1 (line 19)
Index exceeds array bounds.
Error in
R1>#(x)-((1./x(2)).*(N-(x(1).*M)-((min(N./(L.*x(2)),K)-x(1))*(max(0,N-(L.*x(2).*x(1)))))/(x(1)+(min(N./(L.*x(2)),K)-x(2))))-(max(0,N-(L.*K*x(2)))))
Error in fmincon (line 546)
initVals.f = feval(funfcn{3},X,varargin{:});
Error in R1 (line 19)
[xopt, vopt] = fmincon(R,1,[],[],[],[],LB,UB,[],options);
Caused by:
Failure in initial objective function evaluation. FMINCON cannot continue.
The output graph should be the one shown here:
(the lower bound curve)
Couples of mistakes
First, the initial guess should be an 1D array of length 2, kindly
replace 1 by [1, 1]
Better initialize the variable v first , it will speed up your
computation
The most important is the upper bound of l, as you can see it
depends on s and it's in the denominator, consider it as non linear
constraint then set UB = [] You will need to include nonlcon into
fmincon
The code is as follow
N=100;
L = 50;
t = 101:1:1000;
le = length(t);
v = zeros(1, le);
for K= 100:1:1000
M = (N-1)/K;
R = #(x) -(1./(x(1))).*(N-x(1).*((N-1)./K)-((min(ceil(N./(L.*x(2))), K)).*...
max(N -L.*x(1).*x(2), 0))./((x(1) +(min(ceil(N./(L.*x(2))), K))))...
-(max(N - K.*L.*x(2), 0)));
LB = [1 1];
options = optimoptions('fmincon','Algorithm','interior-point');
[xopt, vopt] = fmincon(R,[1, 1],[],[],[],[],LB,[],...
#(x)nonlincon(x(1), x(2),N, L, K ),options);
v(K-101+1) = -vopt;
end
plot(101:1000,v,'v-','LineWidth',2);
xlabel('Number of Users (K)');
ylabel('Delivery Rate (R)');
function [c, ceq] = nonlincon(s, l,N, L, K )
c(1) = l -N./(L.*s);
c(2) = s - min((ceil(N./L)), K) ;
ceq = [];
end

Integrating over a constant function

I am trying to integrate over a constant function in MATLAB 2017a, but I am stuck. First of all when I integrate using the following script, I get the right output. So the script works for a x0 which depends on t.
function E=sol(n,k)
x0 = #(t) t^(2);
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
E(j+1,1) = subs(sprintf('x%d',j+1))
j = j+1;
end
end
Where function po(j,k) is as follows,
function A_j = po(j,k) % Adomian polynomials
if j >0
x = sym('x',[1 j]);
syms p; % Assinging a symbolic variable for p
syms x0;
S = x0+ sum(p.^(1:j) .* x) ; % Sum of p*x up to order j
Q =f(S,k); % Taking the k-th power of S, i.e.
A_nc = diff(Q,p,j)/factorial(j); % Taking the j-th order derivative
A_j = subs(A_nc,p,0) ; % Filling in p=0
else
syms x0;
S = x0;
A_j =f(S,k); % Taking the k-th power of S,
end
end
And where f(x,k) is,
function F = f(x,k) % Nonlinear function of k power
F = x^k ;
end
Now when I cal sol(n,k) it does work. But when I try to change my x0 function in sol(n,k) in a constant function like,
function E=solcon(n,k)
x0 = #(t) 2.*ones(size(t));
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
E(j+1,1) = subs(sprintf('x%d',j+1))
j = j+1;
end
end
It does not work, As you can see I added *ones(size(t)); just to make it a function of t. But unfortunately it still doesn't work when I call,
K = matlabFunction(subs(po(j,k))) ;
I get,
#()4.0
And then I get an error when I call,
eval(sprintf('x%d = integral(K,0,1);',j+1))
Could anyone help me out trying to integrate over a constant?
The error I get when I call solcon(10,2) is
Error using symengine>#()4.0
Too many input arguments.
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 132)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 75)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 88)
Q = integralCalc(fun,a,b,opstruct);
Error in solcon1 (line 7)
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
EDIT 2
I used the following script,
function E=solcon(n,k)
x0 = #(t) 2.*ones(size(t));
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr= func2str(K)
if fstr(3) == ')';
x{j+1} = K*(1-0)
else x{j+1} = integral(K,0,1)
end
E(j+1,1) = subs(x{j+1},1);
j = j+1
end
end
But the following error occurs,
Undefined operator '*' for input arguments of type 'function_handle'.
Error in solcone1 (line 9)
x{j+1} = K*(1-0);
I am going to ignore the terrible choice of using eval, especially when you can do
x{j+1} = integral(K,0,1);
Read more on why dynamic variables and eval are terrible
Your problem is that matlabFunction is a smartass. When it detects that your function does not have any dependency to x, it gives you a function with empty input arguments #()4.0. As you see, integral does not like that.
A way of solving the problem is detecting this before calling integral. You could check if it has input arguments, and if it does not, then evaluate the integral "by hand"
...
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr=func2str(K);
if fstr(3)==')'
x{j+1}=K()*(1-0); % evaluate the integral yourself
else
x{j+1} = integral(K,0,1);
end
E(j+1,1) = subs(x{j+1});
j = j+1;
end
...
The problem is considerably more difficult that I though I was. Either rewrite the entire thing, or using eval:
...
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr=func2str(K);
if j==0
eval(sprintf('x%d = K()*(1-0);;',j+1)) ;
else
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
end
E(j+1,1) = subs(sprintf('x%d',j+1));
j = j+1;
end
...

Minimizing expected value using a multivariate normal distribution Matlab

I am trying to minimise the expected value of this function w.r.t the variable Q :
where f(D) is the probability density function of a multivariate normal distribution, c0 and cu parameters.
This is what I have done so far :
syms X1
syms X2
syms X3
c0 = 1 ;
cu = 1 ;
x = [X1; X2; X3] ;
mu = [3; 5; 7 ] ;
sigma = [4,3,6;3,8,5;6,5,10] ;
s = mvnpdf(x,mu,sigma)
syms Q
syms D
f = (Q-D).*s ;
z = c0.*int(f,D,0,Q) ;
anon_z = matlabFunction(z) ;
g = (D-Q).*s ;
t = cu.*int(g,D,Q,inf) ;
anon_t = matlabFunction(t) ;
tot = #(Q) anon_z(Q) + anon_t(Q) ;
[x fx] = fminsearch(tot,0)
It gives me this error :
Error in
symengine>#(Q,X1,X2,X3)Q.^2.*exp(conj(X1).conj(X3).(3.0./2.0)).*exp(conj(X2).conj(X3).(1.0./1.1e1)).exp(conj(X1).-3.0).exp(conj(X2).(3.0./1.1e1)).exp(conj(X3).(2.6e1./1.1e1)).exp(conj(X1).^2.(-5.0./4.0)).exp(conj(X2).^2.(-1.0./1.1e1)).exp(conj(X3).^2.(-2.3e1./4.4e1)).exp(-8.75688228083863).(1.0./2.0)
Error in #(Q)anon_z(Q)+anon_t(Q)
Error in fminsearch (line 189) fv(:,1) = funfcn(x,varargin{:});
Error in multi_3giocatori (line 19) [x fx] = fminsearch(tot,0)
Can you help me fix this?

Odes15 sub plotting, differential equations

So I have three differential equations relating to diabetes, I have to plot the 2 out of the three, them being G and I in a subplot. For some reason when I attempt to run it the command window prints out: "Not enough input arguments" This is the criteria for it:
function dx = problem1(t,x)
P1 = 0.028735 ;
P2 = 0.028344 ;
P3 = 5.035 * 10^(-5) ;
Vi = 12 ;
n = 5/54 ;
D_t = 3*exp(-0.05*t) ;
U_t = 3 ;
Gb = 4.5;
Xb = 15;
Ib = 15;
G = x(1);
X = x(2);
I = x(3);
dx = zeros(3,1);
dx(1) = -P1*(G-Gb) - (X-Xb)*G + D_t ;
dx(2) = -P2*(X-Xb) + P3*(I-Ib) ;
dx(3) = -n*I + U_t/Vi ;
[T,X] = ode15s(#problem1,[0 60*24],[4.5 15 15]) ;
subplot(3,1,1);
plot(T,X(:,1)); % Plot G
subplot(3,1,2); % Second subplot
plot(T,X(:,2)); % Plot I
The error is thrown when you run the function and MATLAB attempts to evaluate D_t = 3*exp(-0.05*t);. Since no value of t was given, MATLAB throws an error saying that the up-to-that-point unused t variable must be specified.
The main problem with the code is in the function's design. Namely, ode15s needs a function that accepts a t and an x and returns dx; however, as it is currently laid out, the call to ode15s is embedded within problem1 which itself requires a t and x. It is a chicken-or-egg problem.
All of the input is correct aside from this design problem and can easily be corrected using a separate function for the ODE's definition:
function problem1
[T,X] = ode15s(#ODE,[0 60*24],[4.5 15 15]) ;
subplot(3,1,1);
plot(T,X(:,1)); % Plot G
subplot(3,1,2); % Second subplot
plot(T,X(:,2)); % Plot I
end
function dx = ODE(t,x)
P1 = 0.028735 ;
P2 = 0.028344 ;
P3 = 5.035 * 10^(-5) ;
Vi = 12 ;
n = 5/54 ;
D_t = 3*exp(-0.05*t) ;
U_t = 3 ;
Gb = 4.5;
Xb = 15;
Ib = 15;
G = x(1);
X = x(2);
I = x(3);
dx = zeros(3,1);
dx(1) = -P1*(G-Gb) - (X-Xb)*G + D_t ;
dx(2) = -P2*(X-Xb) + P3*(I-Ib) ;
dx(3) = -n*I + U_t/Vi ;
end
Notes:
The first line function problem1 is short-hand for function [] = problem1(). I prefer the latter form myself, but I'm in the minority.
The function handle passed to ode15s #ODE is short-hand for #(t,x) ODE(t,x). I prefer the latter form myself, but it is no less or more valid as long as you are not parametrizing functions.
You can also use a nested function and give the problem1 function access to the model constants, but I opted for a separate function here.

Use Fzero in BC function of pdepe with Matlab

I have to solve some parabolic PDE system with pdepe in Matlab.
is't possible and secure to call Fzero function inside boundary conditions function in Pdepe solver like this?
function [pl,ql,pr,qr] = pdex5bc(~,ul,~,ur,~)
kappa = nref*Dref*q/L;
jcell0 = 0;
k0 = 0.1;
options = optimset('Display','iter'); % show iterations
jcell = fzero(#curOc,k0,options); % Call solver
pl = [jcell0 ; -1/(2*epsilonp)*jcell0/kappa ; 3/(2*epsilonp)*jcell0/kappa ;...
jcell ; -1/(2*epsilonp)*jcell/kappa ; 3/(2*epsilonp)*jcell/kappa];
ql = [kappa ; 1 ; 1 ; kappa ; 1 ; 1];
pr = [0 ; -1/(2*epsilonp)*jcell0/kappa ; 3/(2*epsilonp)*jcell0/kappa ;...
0 ; -1/(2*epsilonp)*jcell/kappa ; 3/(2*epsilonp)*jcell/kappa];
qr = [1 ; 1 ; 1 ; 1 ; 1 ; 1];
function F = curOc(z)
deltaVint = (Rtco+Rext)*(Rp/(Rext+Rtco+Rp))*A*z*J0;
Eta = Pot+Vt/2*log(ur(2)/ur(3)^3)+Vt*log(ul(4)/Ncb)- deltaVint ;
F = z - (ur(5)/ur(2)*exp(beta*Eta/Vt)- ur(6)/ur(3)*exp(-(1-beta)*Eta/Vt));
end
end
Let me expose my problem : When I execute this code, following error occurs:
*Error using fzero (line 289)
FZERO cannot continue because user supplied function_handle ==>
pdeDSSC_new8bis/pdex5bc/curOc
failed with the error below.
User function 'pdeDSSC_new8bis/pdex5bc/curOc' returned a complex value
when evaluated at 20;*
FZERO cannot continue.
At some time integration of pdepe,fsolve returns a complex root. This happens when ul and ur become negatives.
Does someone can explain to me the problem?