How do I pass inputs into external functions from ode45?
8 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Joshua
el 28 de Abr. de 2023
Comentada: Walter Roberson
el 29 de Abr. de 2023
I'm trying to run an ode45 function, but the differential equations are constrained by other equations, which I made functions for, and referenced in the ode function (func) , but I keep getting the error "Not enough input arguments." There may be other errors, but I can't get past this one. I need the domain of the ode45 (pi to 3pi) to be passed into the other functions as input theta. My main goal is to plot theta against pressure/work but I can't get it to intialize. Thanks in advance
global r gamma thetas thetab l S b V0 T1 Tw Qin R
gamma = 1.4;
r = 8.4;
thetas = (3*pi)/2;
thetab = pi;
% meters
l = 0.012;
S = 0.08;
b = 0.09;
% cm squared
V0 = 50;
% Kelvin
T1 = 300;
Tw = 300;
% J/kg
Qin = 2.8e6;
% J/kg/k
R = 287;
% sol = ode45(@func,[pi 3*pi],[1.013e5 0]);
[theta,sol] = ode45(@(theta,y) func,[pi 3*pi],[1.013e5 0]);
function referenced by ode45 and all the dependent functions
function E2 = func(theta,y)
global gamma b Tw Qin R
%y(1)=Pressure
%y(2)=Work
%mass blow by
he = 0;
%heat transfer to cylinder wall
% C = 0;
%instantaneous surface area
Aw =(4*V(theta))/b;
%temperature
T = (y(1)*V(theta))/(mass(theta)*R);
%Pressure and work derivatives, respectively
E2 = [-gamma*(y(1)/V(theta))*(V_prime(theta))+(gamma-1)*((mass(theta)*Qin)/V(theta))*(x_prime(theta))-((gamma-1)*he*Aw*(T-Tw))/(V*w)+((gamma*mass_prime(theta))/mass(theta))*y(1);
y(1)*V_prime(theta);];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Volume function
function Vtheta = V(theta)
global r l S
sigma = S/(2*l);
Vtheta = 1 + ( (r-1) / (2*sigma) )*( 1+sigma*(1-cos(theta)-sqrt(1-sigma^2*sin(theta)^2)));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% x derivative function
function dxdtheta = x_prime(theta)
global thetas thetab
if pi <= theta && theta < thetas
dxdtheta = 0;
elseif thetas <= theta && theta <= (thetas+thetab)
dxdtheta = -(pi/( 2* thetab))*cos( ( pi*( theta-thetas ) ) / thetab);
elseif thetas+thetab < theta && theta < 3*pi
dxdtheta = 0;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%mass function
function M = mass(theta)
M0 = 1;%initial mass
C =0 ;%heat transfer to cylinder
omega = 1;%rotational velocity
M = M0*exp( (-C/omega) * (theta-pi) );
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Mass derivative
function dMdTheta = mass_prime(theta)
%constants
omega_prime = 0;%rotational acceleration - zero bc/ angular velocity was zeero
M0 = 1;%initial mass
C =0 ;%heat transfer to cylinder
dMdTheta = ( -(C*omega_prime)-(pi*omega_prime) )*M0*exp( (-C/omega)*(theta-pi) );
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Volume derivative
function dVdTheta = V_prime(theta)
global r l S
sigma = S/(2*l);
dVdTheta = ( 2*r*sqrt( 1-( sigma^2 ) * sin( theta )^2 )* sin( theta ) + r*sigma*sin(2*theta)-2*sqrt( 1-(sigma^2)*( sin(theta) )^2 )*sin( theta ) )/( 4*sqrt( 1 - (sigma^2)*( sin( theta ) )^2 ) );
end
4 comentarios
Walter Roberson
el 28 de Abr. de 2023
If you are not going to parameterize to get rid of the globals, then Yes, @func would be faster than @(theta,y)func(theta,y)
Respuesta aceptada
Walter Roberson
el 29 de Abr. de 2023
Parameterized version -- no globals.
Note: I had to guess what V*w meant.
p.gamma = 1.4;
p.r = 8.4;
p.thetas = (3*pi)/2;
p.thetab = pi;
% meters
p.l = 0.012;
p.S = 0.08;
p.b = 0.09;
% cm squared
p.V0 = 50;
% Kelvin
p.T1 = 300;
p.Tw = 300;
% J/kg
p.Qin = 2.8e6;
% J/kg/k
p.R = 287;
%other
p.omega = 1;%rotational velocity
p.omega_prime = 0;%rotational acceleration - zero bc/ angular velocity was zeero
% sol = ode45(@func,[pi 3*pi],[1.013e5 0]);
[theta,sol] = ode45(@(theta,y) func(theta,y,p),[pi 3*pi],[1.013e5 0]);
function E2 = func(theta,y,p)
%y(1)=Pressure
%y(2)=Work
%mass blow by
he = 0;
%heat transfer to cylinder wall
% C = 0;
%instantaneous surface area
Aw =(4*V(theta,p))/p.b;
%temperature
T = (y(1)*V(theta,p))/(mass(theta,p)*p.R);
%Pressure and work derivatives, respectively
E2 = [-p.gamma*(y(1)/V(theta,p))*(V_prime(theta,p))+(p.gamma-1)*((mass(theta,p)*p.Qin)/V(theta,p))*(x_prime(theta,p))-((p.gamma-1)*he*Aw*(T-p.Tw))/(V(theta,p)*p.Tw)+((p.gamma*mass_prime(theta,p))/mass(theta,p))*y(1);
y(1)*V_prime(theta,p);];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Volume function
function Vtheta = V(theta,p)
sigma = p.S/(2*p.l);
Vtheta = 1 + ( (p.r-1) / (2*sigma) )*( 1+sigma*(1-cos(theta)-sqrt(1-sigma^2*sin(theta)^2)));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% x derivative function
function dxdtheta = x_prime(theta,p)
if pi <= theta && theta < p.thetas
dxdtheta = 0;
elseif p.thetas <= theta && theta <= (p.thetas+p.thetab)
dxdtheta = -(pi/( 2* p.thetab))*cos( ( pi*( theta-p.thetas ) ) / p.thetab);
elseif p.thetas+p.thetab < theta && theta < 3*pi
dxdtheta = 0;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%mass function
function M = mass(theta,p)
M0 = 1;%initial mass
C =0 ;%heat transfer to cylinder
M = M0*exp( (-C/p.omega) * (theta-pi) );
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Mass derivative
function dMdTheta = mass_prime(theta,p)
%constants
M0 = 1;%initial mass
C =0 ;%heat transfer to cylinder
dMdTheta = ( -(C*p.omega_prime)-(pi*p.omega_prime) )*M0*exp( (-C/p.omega)*(theta-pi) );
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Volume derivative
function dVdTheta = V_prime(theta,p)
sigma = p.S/(2*p.l);
dVdTheta = ( 2*p.r*sqrt( 1-( sigma^2 ) * sin( theta )^2 )* sin( theta ) + p.r*sigma*sin(2*theta)-2*sqrt( 1-(sigma^2)*( sin(theta) )^2 )*sin( theta ) )/( 4*sqrt( 1 - (sigma^2)*( sin( theta ) )^2 ) );
end
2 comentarios
Walter Roberson
el 29 de Abr. de 2023
I had to guess about what V*w was intended to mean, and I might have guessed wrong, so I might have made the equations mostly unsolvable over the range you want.
But if I did happen to guess correctly about what it was intended to mean, then you have a problem that your current equations lead to a singularity at just over 6 seconds.
if pi <= theta && theta < p.thetas
The mathematics of ode45 and related functions requires that the second derivatives of the functions be continuous during any one call to ode45. Any time you see an if statement in your code that calculates the function, you should strongly suspect that you have failed to provide continuous second derivatives. Your code should probably be creating event functions for the two differerent crossings, with the event functions configured to terminate the function, after which you would restart with the new conditions.
Más respuestas (1)
Torsten
el 28 de Abr. de 2023
Editada: Torsten
el 28 de Abr. de 2023
This code works without syntax errors, but you should pass all your parameters to "func" and distribute them from there among the other functions called instead of using globals.
Take a look here on how to do this:
global r gamma thetas thetab l S b V0 T1 Tw Qin R
gamma = 1.4;
r = 8.4;
thetas = (3*pi)/2;
thetab = pi;
% meters
l = 0.012;
S = 0.08;
b = 0.09;
% cm squared
V0 = 50;
% Kelvin
T1 = 300;
Tw = 300;
% J/kg
Qin = 2.8e6;
% J/kg/k
R = 287;
% sol = ode45(@func,[pi 3*pi],[1.013e5 0]);
[theta,sol] = ode45(@func,[pi 3*pi],[1.013e5 0]);
plot(theta,sol)
function referenced by ode45 and all the dependent functions
function E2 = func(theta,y)
global gamma b Tw Qin R
%y(1)=Pressure
%y(2)=Work
%mass blow by
he = 0;
%heat transfer to cylinder wall
% C = 0;
%instantaneous surface area
Aw =(4*V(theta))/b;
%temperature
T = (y(1)*V(theta))/(mass(theta)*R);
%Pressure and work derivatives, respectively
E2 = [-gamma*(y(1)/V(theta))*(V_prime(theta))+(gamma-1)*((mass(theta)*Qin)/V(theta))*(x_prime(theta))-((gamma-1)*he*Aw*(T-Tw))/(V(theta)*Aw)+((gamma*mass_prime(theta))/mass(theta))*y(1);
y(1)*V_prime(theta);];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Volume function
function Vtheta = V(theta)
global r l S
sigma = S/(2*l);
Vtheta = 1 + ( (r-1) / (2*sigma) )*( 1+sigma*(1-cos(theta)-sqrt(1-sigma^2*sin(theta)^2)));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% x derivative function
function dxdtheta = x_prime(theta)
global thetas thetab
if pi <= theta && theta < thetas
dxdtheta = 0;
elseif thetas <= theta && theta <= (thetas+thetab)
dxdtheta = -(pi/( 2* thetab))*cos( ( pi*( theta-thetas ) ) / thetab);
elseif thetas+thetab < theta && theta < 3*pi
dxdtheta = 0;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%mass function
function M = mass(theta)
M0 = 1;%initial mass
C =0 ;%heat transfer to cylinder
omega = 1;%rotational velocity
M = M0*exp( (-C/omega) * (theta-pi) );
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Mass derivative
function dMdTheta = mass_prime(theta)
%constants
omega_prime = 0;%rotational acceleration - zero bc/ angular velocity was zeero
omega=1;
M0 = 1;%initial mass
C =0 ;%heat transfer to cylinder
dMdTheta = ( -(C*omega_prime)-(pi*omega_prime) )*M0*exp( (-C/omega)*(theta-pi) );
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Volume derivative
function dVdTheta = V_prime(theta)
global r l S
sigma = S/(2*l);
dVdTheta = ( 2*r*sqrt( 1-( sigma^2 ) * sin( theta )^2 )* sin( theta ) + r*sigma*sin(2*theta)-2*sqrt( 1-(sigma^2)*( sin(theta) )^2 )*sin( theta ) )/( 4*sqrt( 1 - (sigma^2)*( sin( theta ) )^2 ) );
end
4 comentarios
Walter Roberson
el 29 de Abr. de 2023
Editada: Walter Roberson
el 29 de Abr. de 2023
You have
E2 = [-gamma*(y(1)/V(theta))*(V_prime(theta))+(gamma-1)*((mass(theta)*Qin)/V(theta))*(x_prime(theta))-((gamma-1)*he*Aw*(T-Tw))/(V*w)+((gamma*mass_prime(theta))/mass(theta))*y(1);
y(1)*V_prime(theta);];
Notice the
/(V*w)
That is a problem in that statement because V is not a variable: it is a function of theta.
Also, there is no w anywhere in your code -- only Tw
Ver también
Categorías
Más información sobre Matrix Computations en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
