CFD || Simulation of a 1D Super-sonic Nozzle Flow using Macormack Method
OBJECTIVE
Write code solve the 1D supersonic nozzle flow equations using the Macormack Method.
- Implement both the conservative and non-conservative forms of the governing equations
- Perform grid dependence test
OVERVIEW
Conside steady,isentropic flow through a convergent-divergent nozzle as shown in Fig.The flow expands isentropically to supersonic speeds at the nozzle exit. The flow is locally subsonic in the convergent section of the nozzle, sonic at the throat and supersonic at the divergent section.We assume thatthe flow properties vary only with x; ie uniform flow properties any given c/s.Such flow is called quasi-1D flow.
- Maccromack's Technique
Maccromack,s method is an explicit finite-difference technique which is second order in both space and time.Here a two-step predictor corrector sequence is usedwith forward differences on the predictor and with reward difference on the corrector.It is much easier to apply because there is no need to evaluate the second time derivatives.(For more info check "Computational Fluid Dynamics The Basic with application" by John D Anderson)
- Governing Equations
- Conservative Equations
`(partial(rho'A'))/(partialt')+(partial(rho'A'V'))/(partialx') = 0` (Continuity Eqn)
`(partial(rho'A'V'))/(partialt')+(partial(rho'A'V'^2+(p'A')/gamma))/(partialx')=(p')/gamma(partialA')/(partialx')` (Momentum Eqn)
`(partial[rho'((e')/(gamma-1)+gamma/2V'^2)A'])/(partialt')+(partial[rho'((e')/(gamma-1)+gamma/2V'^2)A'V'+p'A'V'])/(partialx')=0` (Energy Eqn)
2. Non-conservative Equations
`(partialrho')/(partialt')=-rho'(partialV')/(partialx')-rho'V'partial/(partialx')(lnA')-V'(partialrho')/(partialx')` (Continuity Eqn)`
`(partialV')/(partialt')=-V'(partialV')/(partialx')-1/gamma((partialT)/(partialx')+(T')/(rho')(partialrho')/(partialx'))` (Momentum Eqn)`
`(partialT)/(partialt')=-V'(partialT')/(partialx')-(gamma-1)T'[(partialV')/(partialx')+V'partial/(partialx')(lnA')]` (Energy Eqn)`
Here the flow field are non-dimensionalized, where the flow variable are referenced to their reservior values.
`T'=T/T_0 ; rho'=rho/rho_0 ; x'=x/L ; V'=V/a_0 ; t' = t/(L/a_0) ; A' = A/A^*`
PROGRAM
- Main function
%%%%%%%%%%%MAIN FUNCTION%%%%%%%%%%%
clear all
close all
clc
n=31;
x=linspace(0,3,n);
dx=x(2)-x(1);
gama=1.4;
a=1+2.2*(x-1.5).^2;
nt=1000;
C = 0.5; % Courant Number
throat = (n-1)/2;
%Solution for NON_CONSERVATIVE FROM
tic
[m,M,v,t,rho,p,t_throat,rho_throat,p_throat,M_throat]=Non_conservative(n,x,dx,gama,a,nt,C,throat);
timencons=toc;
%Plotting for non conservative
figure(2)
subplot(4,1,1);
plot(1:nt,rho_throat,\'b\');
xlabel(\'No.of Time steps\');
ylabel(\'rho/rho_{0}\')
legend(\'Density ratio\')
grid on;
grid minor;
subplot(4,1,2);
plot(1:nt,t_throat,\'r\');
xlabel(\'No.of Time steps\');
ylabel(\'T/T_{0}\');
legend(\'Temperature ratio\')
grid on;
grid minor;
subplot(4,1,3);
plot(1:nt,p_throat,\'m\');
xlabel(\'No.of Time steps\');
ylabel(\'P/P_{0}\');
legend(\'Pressur ratio\')
grid on;
grid minor;
subplot(4,1,4);
plot(1:nt,M_throat,\'g\');
xlabel(\'No.of Time steps\');
ylabel(\'M\');
legend(\'Mach number\')
grid on;
grid minor;
%Solution for conservative form
tic
[m_c,M_c,v_c,t_c,rho_c,p_c,t_throat_c,rho_throat_c,p_throat_c,M_throat_c]=conservative(n,x,dx,gama,a,nt,C,throat);
timecons=toc;
%Plotting for conservative
figure(4)
subplot(4,1,1);
plot(1:nt,rho_throat_c,\'b\');
xlabel(\'No.of Time steps\');
ylabel(\'rho/rho_{0}\')
legend(\'Density ratio\')
grid on;
grid minor;
subplot(4,1,2);
plot(1:nt,t_throat_c,\'r\');
xlabel(\'No.of Time steps\');
ylabel(\'T/T_{0}\');
legend(\'Temperature ratio\')
grid on;
grid minor;
subplot(4,1,3);
plot(1:nt,p_throat_c,\'m\');
xlabel(\'No.of Time steps\');
ylabel(\'P/P_{0}\');
legend(\'Pressur ratio\')
grid on;
grid minor;
subplot(4,1,4);
plot(1:nt,M_throat_c,\'g\');
xlabel(\'No.of Time steps\');
ylabel(\'M\');
legend(\'Mach number\')
grid on;
grid minor;
%Comparison of mass flow rate plot
figure(5)
plot(x,m,\'r\')
hold on
plot(x,m_c,\'g\')
hold on
line([0 3], [0.579 0.579])
xlabel(\'Non dimensional distance through nozzle(x/L)\')
ylabel(\'Non dimensional mass flow\')
title(\'Comparision of mass flow rate\')
legend(\'Non Conservative Soln\',\'Conservative Soln\',\'Exact Soln\')
- Conservative equation
function [m_c,M_c,v_c,t_c,rho_c,p_c,t_throat_c,rho_throat_c,p_throat_c,M_throat_c]=conservative(n,x,dx,gama,a,nt,C,throat)
%Intial profile
for i=1:length(x)
if x(i) >=0 && x(i)< 0.5
rho_c(i) = 1;
t_c(i) = 1;
else if x(i) >=0.5 && x(i)< 1.5
rho_c(i) = 1.0 - 0.366*(x(i)-0.5);
t_c(i) = 1.0 - 0.167*(x(i)-0.5);
else if x(i) >=1.5 && x(i)<= 3.5
rho_c(i) = 0.634 - 0.3879*(x(i)-1.5);
t_c(i) = 0.833 - 0.3507*(x(i)-1.5);
end
end
end
end
v_c = 0.59./(rho_c.*a);
p_c = rho_c.*t_c;
%initializing solution vector
u1 = rho_c.*a;
u2 = rho_c.*a.*v_c;
u3 = rho_c.*a.*((t_c./(gama-1)) + ((gama/2)*(v_c.^2)));
% Time Iteration Loop
for k = 1:nt
% Saving the old solution vectors:
u1_old = u1;
u2_old = u2;
u3_old = u3;
%Time-step control:
dt = min(C.*dx./(sqrt(t_c) + v_c));
% Defining the flux vectors:
f1 = u2;
f2 = (u2.^2./u1) + ((gama-1)/gama)*(u3 - (gama*u2.^2)./(2*u1));
f3 = ((gama*u2.*u3)./u1) - (gama*(gama-1)/2)*(u2.^3./u1.^2);
for i=2:n-1
%Source Term
j2(i)=(1/gama).*rho_c(i).*t_c(i).*((a(i+1)-a(i))/dx);
%predictor step
du1dt_p(i) = -(f1(i+1) - f1(i))/dx;
du2dt_p(i) = -(f2(i+1) - f2(i))/dx + j2(i);
du3dt_p(i) = -(f3(i+1) - f3(i))/dx;
%Update
u1(i) = u1(i) + du1dt_p(i)*dt;
u2(i) = u2(i) + du2dt_p(i)*dt;
u3(i) = u3(i) + du3dt_p(i)*dt;
end
%Primitrive value and flux vector update
rho_c = u1./a;
v_c = u2./u1;
t_c = (gama -1)*((u3./u1) - ((gama/2)*v_c.^2));
p_c = rho_c.*t_c;
f1 = u2;
f2 = (u2.^2./u1) + ((gama-1)/gama)*(u3 - (gama*u2.^2)./(2*u1));
f3 = ((gama*u2.*u3)./u1) - (gama*(gama-1)/2)*(u2.^3./u1.^2);
%Corrector step
for i=2:n-1
%Source Term
j2(i) = (1/gama)*rho_c(i).*t_c(i)*((a(i)-a(i-1))/dx);
du1dt_c(i) = -(f1(i) - f1(i-1))/dx;
du2dt_c(i) = -(f2(i) - f2(i-1))/dx + j2(i);
du3dt_c(i) = -(f3(i) - f3(i-1))/dx;
end
%Average value
du1dt=0.5*(du1dt_p+du1dt_c);
du2dt=0.5*(du2dt_p+du2dt_c);
du3dt=0.5*(du3dt_p+du3dt_c);
%FInal solution
for j=2:n-1
u1(j)= u1_old(j) + du1dt(j)*dt;
u2(j)= u2_old(j) + du2dt(j)*dt;
u3(j)= u3_old(j) + du3dt(j)*dt;
end
%Boundary condition
%u1(1)=rho_c(1)*a(1);
u2(1)= 2*u2(2) - u2(3);
%u3(1)=u1(1)*(t_c(1)/(gama-1) + (gama*(v_c.^2))/2);
u1(n)=2*u1(n-1) - u1(n-2);
u2(n)=2*u2(n-1) - u2(n-2);
u3(n)=2*u3(n-1) - u3(n-2);
%Final solution of primitive variables
rho_c = u1./a;
v_c = u2./u1;
t_c = (gama -1).*((u3./u1) - ((gama/2).*v_c.^2));
p_c = rho_c.*t_c;
m_c= rho_c.*a.*v_c;
M_c=v_c./sqrt(t_c);
%Capturing throat values
t_throat_c(k)=t_c(throat);
p_throat_c(k)=p_c(throat);
rho_throat_c(k)=rho_c(throat);
M_throat_c(k)=M_c(throat);
%MASS FLOW RATE AT DIFFERENT TIME OF THROAT
figure(3)
hold on;
if k==100
plot(x,m_c,\'b\')
else if k==200
plot(x,m_c,\'r\')
else if k==700
plot(x,m_c,\'g\')
end
end
end
end
title(\'Non dimensional mass flow at different time(CONSERVATIVE)\');
xlabel(\'Non dimensional distance through nozzle(x/L)\');
ylabel(\'Non dimensional mass flow\');
legend(\'100 dt\',\'200 dt\',\'700 dt\');
grid on;
grid minor;
end
- Non-conservative equation
function [m,M,v,t,rho,p,t_throat,rho_throat,p_throat,M_throat]=Non_conservative(n,x,dx,gama,a,nt,C,throat)
%intial Profile
rho=1-0.3146*x;
t=1-0.2314*x;
v=(0.1+1.09*x).*t.^0.5;
%MACROMEK METHOD
for k=1:nt
%SAving intial value
rho_old=rho;
t_old=t;
v_old=v;
%Time control
dt=min((C.*dx)./(sqrt(t)+v));
for i=2:n-1
dvdx=(v(i+1)-v(i))/dx;
drhodx=(rho(i+1)-rho(i))/dx;
dlogadx=(log(a(i+1))-log(a(i)))/dx;
dtdx=(t(i+1)-t(i))/dx;
%Predictor Method
drhodt_p(i)=-rho(i)*dvdx -rho(i)*v(i)*dlogadx -v(i)*drhodx;
dvdt_p(i)=-v(i)*dvdx -((1/gama)*(dtdx + (t(i)/rho(i))*drhodx));
dtdt_p(i)=-v(i)*dtdx -((gama-1)*t(i)*(dvdx + v(i)*dlogadx));
%Update
rho(i)=rho(i) + drhodt_p(i)*dt;
v(i)=v(i) + dvdt_p(i)*dt;
t(i)=t(i) + dtdt_p(i)*dt;
end
%Corrector Method
for i=2:n-1
dvdx=(v(i)-v(i-1))/dx;
drhodx=(rho(i)-rho(i-1))/dx;
dlogadx=(log(a(i))-log(a(i-1)))/dx;
dtdx=(t(i)-t(i-1))/dx;
drhodt_c(i)=-rho(i)*dvdx - rho(i)*v(i)*dlogadx - v(i)*drhodx;
dvdt_c(i)=-v(i)*dvdx - ((1/gama)*(dtdx+(t(i)/rho(i))*drhodx));
dtdt_c(i)=-v(i)*dtdx - ((gama-1)*t(i)*(dvdx+v(i)*dlogadx));
end
%Average value
drhodt=0.5*(drhodt_p + drhodt_c);
dvdt=0.5*(dvdt_p + dvdt_c);
dtdt=0.5*(dtdt_p + dtdt_c);
%final Solution
for j=2:n-1
rho(j)=rho_old(j)+drhodt(j)*dt;
v(j)=v_old(j)+dvdt(j)*dt;
t(j)=t_old(j)+dtdt(j)*dt;
end
%Apply BC
%Inlet
v(1)=2*v(2)-v(3);
%Outlet
v(n)=2*v(n-1)-v(n-2);
rho(n)=2*rho(n-1)-rho(n-2);
t(n)=2*t(n-1)-t(n-2);
p=rho.*t;
m=rho.*a.*v;
M=v./sqrt(t);
%Capturing throat values
t_throat(k)=t(throat);
p_throat(k)=p(throat);
rho_throat(k)=rho(throat);
M_throat(k)=M(throat);
%MASS FLOW RATE AT DIFFERENT TIME OF THROAT
figure(1)
hold on;
if k==50
plot(x,m,\'b\')
else if k==100
plot(x,m,\'r\')
else if k==150
plot(x,m,\'g\')
else if k==200
plot(x,m,\'m\')
else if k==700
plot(x,m,\'-\')
end
end
end
end
end
end
title(\'Non dimensional mass flow at different time(NON CONSERVATIVE)\');
xlabel(\'Non dimensional distance through nozzle(x/L)\');
ylabel(\'Non dimensional mass flow\');
legend(\'50 dt\',\'100 dt\',\'150 dt\',\'200 dt\',\'700 dt\');
grid on;
grid minor;
end
RESULT
- Non-conservative
The above fig represent the time-wise variation of density,temperature,pressure and mach number at the throat
- Conservative
The above fig represent the time-wise variation of density,temperature,pressure and mach number at the throat
Time taken for non-conservative=5.48 sec
Time taken for conservative=6.67 sec
- Grid independency test
The above values are at the throat of the nozzle
CONCLUSION
- The conservative form does a better job in mass flow distribution.
- The conservative form requires more time compared to non-conservative form;this is due to decoding the primitive variables from flux variable which is not required while using non conservative form.
- The number of grid points n=31 is enough to produce valid accurate result and when increased further doesn't produce a large variation in the result compared to exact results.