Suppose we have the following function:
function f=lorenz(t,x,a,b,c)
% solve differential equation like this
%dx/dt=a*(y-x)
%dy/dt=-x*z+b*x-y
%dz/dt=xy-c*z/3
f=zeros(3,1);% preallocate result
f(1)=a*(x(2)-x(1));
f(2)=-x(1)*x(3)+b*x(1)-x(2);
f(3)=x(1)*x(2)-c*x(3)/3;
end
For running this program, let us use the following test file:
% test program
x0=[-2 -3.5 21];% initial point
a=input(' enter first coefficient : ');
b=input(' enter second coefficient: ');
c=input(' enter third coefficient : ');
[t,x]=ode45(#(x) lorenz(x,a,b,c),[0 10],x0);
plot(t,x(:,1),'r');
title(' solution of x part');
grid on
I have tried passing arguments to the function handle,
test_program
enter first coefficient : 10
enter second coefficient: 28
enter third coefficient : -8
but it gives me the following error:
Error using #(x)lorenz(x,a,b,c)
Too many input arguments.
Error in odearguments (line 87)
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ode45 (line 113)
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs, odeFcn, ...
Error in test_program (line 6)
[t,x]=ode45(#(x) lorenz(x,a,b,c),[0 10],x0);
one solution involves using global variables, like this:
function f=lorenz(t,x)
% solve differential equation like this
%dx/dt=a*(y-x)
%dy/dt=-x*z+b*x-y
%dz/dt=xy-c*z/3
global a
global b
global c
f=zeros(3,1);% preallocate result
f(1)=a*(x(2)-x(1));
f(2)=-x(1)*x(3)+b*x(1)-x(2);
f(3)=x(1)*x(2)-c*x(3)/3;
end
but then it takes too long to run.
How else can I fix this issue? What I want is to pass different arguments, if I write inside code something like this
a=input('enter the coefficient : ')
then this will be repeated several times.
Don't use global variables.
The fix is very simple, add the t as input too:
[t,x] = ode45(#(t,x) lorenz(t,x,a,b,c),[0 10],x0);
Related
I am trying to solve this system of ODEs related to micro algae growth kinetics, I attach my function and script. I am getting some error related to the arguments. Please let me know where my error is thank you :) the system is composed of 7 ODEs and 7 corresponding state variables with 25 parameters
Function
function dx=odesys(t,var)
%dxdt=var(1);
%dldt=var(2);
%dsdt=var(3);
%dndt=var(4);
%gadt=var(5);
%Fadt=var(6);
%dhdt=var(7);
mumax=var(1);
Kxs=var(2);
Kixs=var(3);
Kxn=var(4);
Kixn=var(5);
qlmax=var(6);
Kls=var(7);
Kils=var(8);
Kinl=var(9);
Yxs=var(10);
Yxn=var(11);
Kh=var(12);
Yls=var(13);
Kxl=var(14);
Kixl=var(15);
Kli=var(16);
Kili=var(17);
sigma=var(18);
k1=var(19);
Kgas=var(20);
Kgan=var(21);
Kigan=var(22);
k2=var(23);
Kfas=var(24);
Kfan=var(25);
%Variable
%oilfree biomass--x(1)
%lipid production rate--x(2)
%Substrate consumption rate--x(3)
%N consumption rate--x(4)
%Byproduct GA--x(5)
%Byproduct FA--x(6)
%pH change--x(7)
%Rate equations
S=2.01; %g/L
N=0.098; %g/L
X=0.001; %g/L
Io=125*10-6; %E/m^2*s
l=1;
Il=Io*exp(-sigma*X*l);
mux=mumax*(S/(S+Kxs+(S^2/Kixs)))*(N/(N+Kxn+(N^2/Kixn)))*(Il/(Il+Kxl+(Il^2/Kixl)));
mul=(qlmax)*(S/(S+Kls+(S^2/Kils)))*(Kinl/(N+Kinl)*(Il/(Il+Kli+(Il^2/Kili))));
%ODE
dx(1)=(mux*X);
dx(2)=(mul*X);
dx(3)=(-(1/Yxs)*dx(1))-((1/Yls)*dx(2));
dx(4)=(-(1/Yxn)*dx(1));
dx(5)=(k1*(S/(S+Kgas))*(N/(N+Kgan+(N^2/Kigan))));
dx(6)=(k2*(S/S+Kfas)*(N/N+Kfan));
dx(7)=-Kh*dx(3);
% The function return value is always a vector length equal to number of
% equations in model, and has to be a column vector
dx=dx';
% dx=[dx(1);dx(2);dx(3);dx(4);dx(5);dx(6);dx(7)];
end
Script
clear all
clc
%Time span to solve ODE
tspan=[0 120];
int=[0,0,0,0,0,0,0];
%Conditions
var=[0.227;0.050;9.923;0.065;0.5;0.121;6.554;0.110;380.023;1.47;6.883;0.879;0.064;19.519;2053.924;15.023;2152.918;34.104;0.329;1.456;12.976;2.533;1.4055;12.976;2.533];
V = odesys(tspan(1), var);
iscolumn(V) % false
isrow(V) % true?
%Using ODE 45 to solve system
[t,X]=ode45(#odesys,tspan,int,var);
Error functions
Error in odearguments (line 90)
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ode45 (line 115)
odearguments(FcnHandlesUsed, solver_name, ode, tspan, y0, options, varargin);
Error in run (line 17)
[t,X]=ode45(#odesys,tspan,int,var);
An easy way to do this is to define the 'var' variable inside your odesys function not in the script:
function dx=odesys(t, x)
%dxdt=var(1);
%dldt=var(2);
%dsdt=var(3);
%dndt=var(4);
%gadt=var(5);
%Fadt=var(6);
%dhdt=var(7);
var=[0.227;0.050;9.923;0.065;0.5;0.121;6.554;0.110;380.023;1.47;6.883;0.879;0.064;19.519;2053.924;15.023;2152.918;34.104;0.329;1.456;12.976;2.533;1.4055;12.976;2.533];
mumax=var(1);
Kxs=var(2);
...
Note the changes in the function declaration.
You have to add the x parameter here in function declaration. This is the variable which you are differentiating with respect to. You are not using it in your equations so you can name it anything but it should be included.
And finally, no need for the 'var' variable in the script as in here:
V = odesys(tspan(1));
and here:
[t,X]=ode45(#odesys,tspan,int);
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!
I create this code to calculate something for me. At the end I need to compute the roots of Eq1 and Eq2, but because they are nonlinear I deside to compute their taylor expansion first and then compute their roots.
But I get error.
clc
clear
close all
format short g
syms x
%% Initilaizing
N=9;%input('Please enter the filter order: ');
Rl=20;%input('Please enter the value of Return Loss(RL) in dB: ');
IL=60;%input('Please enter the value of Insertion Loss(IL) in dB: ');
Fp=18;%input('Please enter the Band-Edge Frequency in GHz: ');
%% Definition Functions
Omega0=fminbnd(#(OM0)Func(OM0,Rl,IL,N),0,10,optimset('Tolx',1e-500));
epsilon=1/sqrt(10^(Rl/10)-1);
ILn=10^(0.1*IL);
TempFunc=#(x)real(1+epsilon^2*(cosh((N-3)*acosh(x*sqrt((Omega0^2 -1)/(Omega0^2 -x^2)))+3*acosh(x)))^2-ILn);
Omega1=fzero(TempFunc,1);
Frequency=[Omega0;Omega1;Omega0*Fp;Omega1*Fp;N];
Freq={'Infinite Attenuation(rad)';'Band-Edge Frequency(rad)';'Infinite Attenuation(GHz)';'Band-Edge Frequency(GHz)';'Order'};
Results=table(Freq,Frequency)
Eq1=#(x) 1+1j.*epsilon.*cosh((N-3).*acosh((x./1j).*sqrt((Omega0^2 -1)./(Omega0^2 -(x./1j).^2)))+3.*acosh(x./1j));
Eq2=#(x) 1-1j.*epsilon.*cosh((N-3).*acosh((x./1j).*sqrt((Omega0^2 -1)./(Omega0^2 -(x./1j).^2)))+3.*acosh(x./1j));
taylor(Eq1,'order',50)
This is the function that I use:
function Returned=Func(OM0,Rl,IL,N)
%% Main Section
epsilon=1/sqrt(10^(Rl/10)-1);
Omega=#(OM0) sqrt(OM0.^2+((N-3)/3).*OM0.*sqrt(OM0.^2 -1)) ;
Fn=#(OM0) real(cosh((N-3).*acosh(Omega(OM0).*sqrt((OM0.^2 -1)./(OM0.^2 -Omega(OM0).^2)))+3.*acosh(Omega(OM0))));
ILoss=#(OM0) real((1+epsilon^2.*Fn(OM0).^2));
[~,Temp]=fminbnd(ILoss,OM0,10,optimset('Tolx',1e-250));
Returned=abs(Temp-10^( IL/10));
end
This is the error:
Error using symengine (line 58)
Cannot compute a Taylor expansion of the input.
Error in sym/taylor (line 133)
tSym = mupadmex('symobj::taylor',f.s,x.s,a.s,options);
Error in OptimizingOmega0 (line 52)
taylor(Eq1,x,50)
Please help me how can I earn thr polynomial coefficients of Eq1,2 for computing roots.
I am trying to solve a system of 6 differential equations using matlab. I created a set of 6 differential equations as follows in a function m file named as Untitled.m
function ydot=Untitled(z,y)
ydot = zeros(6,1);
%y(1)=A
%y(2)=B
%y(3)=C
%y(4)=D
%y(5)=P
y(6)=T
A=0.50265
k11=(333/106.7)*1.15*1000*exp(-59660/(8.314*960))
k31=(333/40)*73.6*exp(-47820/(8.314*960))
k32=(333/14.4)*1.79*exp(-30950/(8.314*960))
k21=(106.7/40)*426*exp(-68830/(8.314*960))
k22=(106.7/14.4)*0.000599*exp(-57740/(8.314*960))
Pcat=1450
g=9.81
phi=exp(-al*tc)
al=59100*exp(-67210/(8.314*T))
tc=(0.50265*1450*33)/143.64
H11=393000
H31=795000
H32=1200000
H21=1150000
H22=151000
E=1-((285.765*17.56)/((6.1*1450)+(17.56*285.765)))
Fcat=143.64
Cpcat=1087
Cp=1000*(y(1)*3.3+y(2)*3.3+y(3)*3.3+y(4)*1.087)
F=19.95
ydot(1)= -(A*(1-E)*Pcat*(k11+k31+k32)*phi*y(1)*y(1))/F
ydot(2)= (A*(1-E)*Pcat*(k11*y(1)*y(1)-(k21+k22)*y(2))*phi)/F
ydot(3)= (A*(1-E)*Pcat*(k31*y(1)*y(1)+ k21*y(2))*phi)/F
ydot(4)= (A*(1-E)*Pcat*(k32*y(1)*y(1)+k22*y(2))*phi)/F
ydot(5)= -(Pcat*g*(1-E))
ydot(6) = ((phi*(1-E)*Pcat*A)*(y(1)*y(1)((k11*H11)+(k31*H31)+(k32*H32))+y(2)((k21*H21)+ (k22*H22)))/((F*Cp)+(Fcat*Cpcat)))
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
then i have created another file for using the ODE45 solver to solve the equations
function main
options = odeset('RelTol',1e-6); %,'AbsTol',[1e-5 1e-5 1e-5 1e-5 1e-5 1e-5 ]);
Y0=[1.0;0.0;0.0;0.0;180000.0;959.81]
zspan=0:0.5:33;
[z,y]= ode45(#Untitled,zspan,Y0,options);
figure
hold on
plot(z,y(:,1));
plot(z,y(:,2),':');
but I am getting errors
??? Error using ==> feval
Error: File: Untitled.m Line: 41 Column: 37
()-indexing must appear last in an index expression.
Error in ==> odearguments at 110
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ==> ode45 at 173
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs, odeFcn, ...
Error in ==> ode at 6
[z,y]= ode45(#Untitled,zspan,Y0,options);
could anyone please help me with this as it is really important for me and i am new to MATLAB
thanx in advance :)
Search for )( in your code, it's syntactically not allowed. Probably you missed a * in between.
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".