Simulation of a 1D Super-sonic nozzle flow simulation using Macormack Method
Simulation of 1D Super-sonic nozzle flow simulation using Macormack method:
The equations which are used to simulate the flow can be found in computational fluid dynamics by John D Anderson.
Main Code :
% MATLAB program to simulate 1D supersonic nozzle flow using macormack method
clear all
close all
clc
% inputs
n = 31;
x = linspace(0,3,n);
dx = x(2)-x(1);
gamma = 1.4;
% area
a = 1+2.2*(x-1.5).^2;
% courant number
C = 0.5;
nt = 1400;% number of time steps
% conservative solver
tic
[rho_con,rho_con_throat,T_con,T_con_throat,v_con,p_con,p_throat,mass_flow_con,M_con,M_con_throat] = conserve(x,gamma,nt,n,C,dx,a)
time_c = toc;
fprintf(\'computationla time %f\',time_c);
% time wise variation of density, temperature, mach number,pressure for conservative form
time_var_con = figure(3);
subplot(4,1,1)
plot(rho_con_throat,\'b\');
title(\' time-wise variation of properties at the nozzle throat(conservative form)\');
ylabel(\'rho/rho_{0}\');
axis([0 1400 0.5 1]);
legend(\'density\');
grid minor;
subplot(4,1,2)
plot(T_con_throat,\'r\');
ylabel(\'T/T_{0}\');
axis([0 1400 0.6 1.2]);
legend(\'temperature\');
grid minor;
subplot(4,1,3)
plot(p_throat);
ylabel(\'p/p_{0}\');
axis([0 1400 0.4 1]);
legend(\'pressure\');
grid minor;
subplot(4,1,4)
plot(M_con_throat);
ylabel(\'M\');
legend(\'mach number\');
axis([0 1400 0.8 1.4])
grid minor;
xlabel(\'number of iterations\');
% properties profiles in 1D Supersonic nozzle flow
qualitative = figure(4);
hold on
subplot(4,1,1)
plot(x,rho_con);
title(\'properties profile in the 1D Supersonic Nozzle flow(conservative form)\');
ylabel(\'rho/rho_{0}\');
legend(\'density\');
grid minor;
subplot(4,1,2)
plot(x,p_con);
ylabel(\'p/p_{0}\');
legend(\'pressure\');
grid minor;
subplot(4,1,3)
plot(x,T_con);
ylabel(\'T/T_{0}\');
legend(\'temperature\');
grid minor;
subplot(4,1,4)
plot(x,M_con);
ylabel(\'M\');
legend(\'mach number\');
grid minor
% non conservative solver
tic
[rho,T,v,M_non,p_non,massflow_non,M_non_throat,p_non_throat,rho_throat,T_non_throat] = non_conservative(x,n,gamma,nt,C,dx,a);
time_non = toc;
fprintf(\'computationla time %f/n\',time_non);
% time wise variation of density, temperature, mach number,pressure for non conservative form
time_var_con = figure(5);
subplot(4,1,1)
plot(rho_throat,\'b\');
title(\'time-wise properties at the nozzle throat (non conservative form)\');
ylabel(\'rho/rho_{0}\');
axis([0 1400 0.5 1]);
legend(\'density\');
grid minor;
subplot(4,1,2)
plot(T_non_throat,\'r\');
ylabel(\'T/T_{0}\');
axis([0 1400 0.6 1.2]);
legend(\'temperature\');
grid minor;
subplot(4,1,3)
plot(p_non_throat);
ylabel(\'p/p_{0}\');
axis([0 1400 0.4 1]);
legend(\'pressure\');
grid minor;
subplot(4,1,4)
plot(M_non_throat);
ylabel(\'M\');
legend(\'mach number\');
axis([0 1400 0.8 1.4])
grid minor;
xlabel(\'number of iterations\');
% properties profiles
figure(6)
subplot(4,1,1)
plot(x,M_non,\'-r\');
title(\'properties profiles of 1D Supersonic nozzle flow( non conservative form)\');
ylabel(\'M\');
legend(\'mach number\');
grid minor;
subplot(4,1,2)
plot(x,p_non);
ylabel(\'p/p_{0}\');
legend(\'pressure\');
grid minor;
subplot(4,1,3)
plot(x,T);
ylabel(\'T/T_{0}\');
legend(\'temperature\');
grid minor;
subplot(4,1,4)
plot(x,rho);
ylabel(\'rho/rho_{0}\');
legend(\'density\');
grid minor;
% comparision of mass flow rates by conservative and non conservative forms
mass_comparision = figure(7);
hold on
plot(x,massflow_non);
plot(x,mass_flow_con);
legend(\'Conservative\',\'Non conservative\');;
grid minor;
xlabel(\'x/L\');
ylabel(\'rhova/rho_{0}v_{0}a_{0}\');
title(\'mass flow comparision between conservative and non conservative forms\');
Conservative code:
function [rho_con,rho_con_throat,T_con,T_con_throat,v_con,p_con,p_throat,mass_flow_con,M_con,M_con_throat] = conserve(x,gamma,nt,n,C,dx,a)
% initial profiles
for i = 1:length(x)
if x(i)>=0 && x(i)<=0.5
rho_con(i) = 1;
T_con(i) = 1;
elseif x(i)>=0.5 && x(i)<=1.5
rho_con(i) = 1-0.366*(x(i)-0.5);
T_con(i) = 1-0.167*(x(i)-0.5);
elseif x(i)>=1.5 && x(i)<=3.5
rho_con(i) = 0.634-0.3879*(x(i)-1.5);
T_con(i) = 0.833-0.3507*(x(i)-1.5);
endif
endfor
v_con = 0.59./(rho_con.*a);
p_con = rho_con.*T_con;
% calculating initial solution vector
U1 = rho_con.*a;
U2 = rho_con.*a.*v_con;
U3 = rho_con.*a.*((T_con./(gamma-1))+(gamma/2)*(v_con.^2));
for k = 1:nt
% copy of old solution vectors
U1_old = U1;
U2_old = U2;
U3_old = U3;
% calculating flux vectors
F1 = U2;
F2 = (U2.^2./U1)+((gamma-1)/gamma)*(U3-(gamma.*U2.^2./(2.*U1)));
F3 = (gamma.*U2.*U3./U1)-(gamma*(gamma-1)/2)*(U2.^3./U1.^2);
% calculating time step
a_con = sqrt(T_con);
timestep = C*dx./(a_con+v_con);
dt = min(timestep);
% predictor step
for j = 2:n-1
J2(j) = (1/gamma).*rho_con(j).*T_con(j).*((a(j+1)-a(j))/dx);
dU1dt_p(j) = -(F1(j+1)-F1(j))/dx;
dU2dt_p(j) = -((F2(j+1)-F2(j))/dx)+J2(j);
dU3dt_p(j) = -(F3(j+1)-F3(j))/dx;
% updating solution vector
U1(j) = U1(j)+dU1dt_p(j)*dt;
U2(j) = U2(j)+dU2dt_p(j)*dt;
U3(j) = U3(j)+dU3dt_p(j)*dt;
endfor
% updating variables and flux vectors
rho_con = U1./a;
v_con = U2./U1;
T_con = (gamma-1)*(U3./U1-(gamma/2)*(U2./U1).^2);
p_con = rho_con.*T_con;
F1 = U2;
F2 = (U2.^2./U1)+((gamma-1)/gamma)*(U3-(gamma*U2.^2./(2.*U1)));
F3 = (gamma*U2.*U3./U1)-(gamma*(gamma-1)/2)*(U2.^3./U1.^2);
% corrector method
for j = 2:n-1
J2_c(j) = (1/gamma)*rho_con(j).*T_con(j).*((a(j)-a(j-1))/dx);
dU1_dt_c(j) = -(F1(j)-F1(j-1))/dx;
dU2_dt_c(j) = -((F2(j)-F2(j-1))/dx)+J2_c(j);
dU3_dt_c(j) = -(F3(j)-F3(j-1))/dx;
endfor
% calculating average time derivative
U1_avg = 0.5*(dU1dt_p + dU1_dt_c);
U2_avg = 0.5*(dU2dt_p + dU2_dt_c);
U3_avg = 0.5*(dU3dt_p + dU3_dt_c);
% final solution update
for i = 2:n-1
U1(i) = U1_old(i)+U1_avg(i)*dt;
U2(i) = U2_old(i)+U2_avg(i)*dt;
U3(i) = U3_old(i)+U3_avg(i)*dt;
endfor
% boundary conditions
% inlet
rho_con(1) = 1;
T_con(1) = 1;
U1(1) = rho_con(1).*a(1);
U2(1) = 2*U2(2)-U2(3);
v_con(1) = U2(1)./U1(1);
U3(1) = U1(1)*(T_con(1)/(gamma-1))+(gamma/2)*v_con(1).^2;
% outlet
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);
% updating variables
rho_con = U1./a;
v_con = U2./U1;
T_con = (gamma-1)*(U3./U1-(gamma/2)*(U2./U1).^2);
p_con = rho_con.*T_con;
% mass flow rate
mass_flow_con = rho_con.*v_con.*a;
M_con = v_con./sqrt(T_con); % mach number
p_con = rho_con.*T_con;
% properties at throat
rho_con_throat(k) = rho_con(((n-1)/2)+1);
p_throat(k) = p_con(((n-1)/2)+1);
T_con_throat(k) = T_con(((n-1)/2)+1);
M_con_throat(k) = M_con(((n-1)/2)+1);
% comparision of non dimensional mass flow rate for different time steps
mass = figure(1);
hold on
if k == 100
plot(x,mass_flow_con,\'b\');
elseif k == 200
plot(x,mass_flow_con,\'g\');
elseif k == 700
plot(x,mass_flow_con,\'v\');
end
endfor
title(\'transient non dimensional mass flow (conservative form)\');
xlabel(\'x/L\');
ylabel(\'conservative mass flow rate\');
legend(\'100 time step\',\'200 time step\',\'700 time step\');
endfunction
Non Conservative Code:
function [rho,T,v,M_non,p_non,massflow_non,M_non_throat,p_non_throat,rho_throat,T_non_throat] = non_conservative(x,n,gamma,nt,C,dx,a)
% calculate input profles
rho = 1-0.3146*x;
T = 1-0.2314*x;
v = (0.1+1.09*x).*T.^(1/2);
% time steps
a_non = sqrt(T);
timestep_non = C*dx./(a_non+v);
dt = min(timestep_non);
for k2 = 1:nt
rho_old = rho;
v_old = v;
T_old = T;
% predictor method
for j = 2:n-1
% drho_dt_p = -rho(j)*(v(j+1)-v(j))/dx-rho(j)*v(j)*(log(A(j+1))-log(A(j)))/dx-v(j)*(rho(j+1)-rho(j))/dx;
dvdx = (v(j+1)-v(j))/dx;
drhodx = (rho(j+1)-rho(j))/dx;
dlogadx = (log(a(j+1))-log(a(j)))/dx;
dTdx = (T(j+1)-T(j))/dx;
% continuty equation
drho_dt_p(j) = -rho(j)*dvdx -rho(j)*v(j)*dlogadx -v(j)*drhodx;
% momentum equation
dv_dt_p(j) = - v(j)*dvdx -(1/gamma)*(dTdx+(T(j)/rho(j))*drhodx);
% energy equation
dT_dt_p(j) = -v(j)*dTdx -(gamma-1)*T(j)*(dvdx+v(j)*dlogadx);
% solution update
rho(j) = rho(j)+drho_dt_p(j)*dt;
v(j) = v(j)+dv_dt_p(j)*dt;
T(j) = T(j)+dT_dt_p(j)*dt;
end
% correcto step
for j = 2:n-1
dvdx = (v(j)-v(j-1))/dx;
drhodx = (rho(j)-rho(j-1))/dx;
dlogadx = (log(a(j))-log(a(j-1)))/dx;
dTdx = (T(j)-T(j-1))/dx;
% continuty equation
drho_dt_c(j) = -rho(j)*dvdx -rho(j)*v(j)*dlogadx -v(j)*drhodx;
% momentum equation
dv_dt_c(j) = - v(j)*dvdx -(1/gamma)*(dTdx+(T(j)/rho(j))*drhodx);
% energy equation
dT_dt_c(j) = -v(j)*dTdx -(gamma-1)*T(j)*(dvdx+v(j)*dlogadx);
end
% calculating average time derivative
drho_dt_avg = 0.5*(drho_dt_p+drho_dt_c);
dv_dt_avg = 0.5*(dv_dt_p+dv_dt_c);
dT_dt_avg = 0.5*(dT_dt_p+dT_dt_c);
% next time step
for i = 2:n-1
rho(i) = rho_old(i)+drho_dt_avg(i)*dt;
v(i) = v_old(i)+dv_dt_avg(i)*dt;
T(i) = T_old(i)+dT_dt_avg(i)*dt;
end
% apply boundary conditions
% inlet
v(1) = 2*v(2)-v(3);
% outlet
rho(n) = 2*rho(n-1)-rho(n-2);
v(n) = 2*v(n-1)-v(n-2);
T(n) =2*T(n-1)-T(n-2);
% mass flow rate
massflow_non = rho.*v.*a;
p_non = rho.*T;
M_non = v./sqrt(T);
% throat values
p_non_throat(k2) = p_non(((n-1)/2)+1);
M_non_throat(k2) = M_non(((n-1)/2)+1);
T_non_throat(k2) = T(((n-1)/2)+1);
rho_throat(k2) = rho(((n-1)/2)+1);
% comparision of non dimensional mass flow rate for different time steps
mass2 = figure(2);
hold on
if k2 == 50
plot(x,massflow_non,\'r\');
elseif k2 == 100
plot(x,massflow_non,\'b\');
elseif k2 == 150
plot(x,massflow_non,\'g\');
elseif k2 == 200
plot(x,massflow_non,\'c\');
elseif k2 == 700
plot(x,massflow_non,\'y\');
endif
endfor
title(\'transient non dimensional mass flow (non conservative form)\');
xlabel(\'x/L\');
ylabel(\'non conservative mass flow rate\');
legend(\'50 timestep\',\'100 time step\',\'150 timestep\',\'200 time step\',\'700 time step\');
endfunction
RESULTS:
(i) Time wise properties at nozzle throat
(a) Conservative form
(b) non conservative form
Non dimensionalized parameters like density,pressure,temperature and mach number are plotted at throat point against the time step to check at which time step steady state reaches for both conservative and non conservative forms. Initially for non conservative it shows greater variations but soon it stable and simillarly for conservative also it shows small variations and even it also reaches steady state soon. from the above results we can observe that for both non conservative and conservative steady state reaches after 700 iterations approx.
(ii) Properties profiles of 1D Supersonic Nozzle flow with length
(a) Conservative form
(b) Non conservative form
we can observe from the plots that for both conservative and non conservative the density, pressure and temperature are dropping at the exit of the nozzle and the mach number is increasing as the acceleration is increasing. These results are almost identical to the profiles in the textbook (John D Anderson).
(iii) Non dimensional mass flow rate with various time steps
(a) Conservative form:
(b) Non conservative form:
It can be seen from both figures that the mass flow rate becomes steady after 700 time steps for both conservative and non conservative .
(iv) comparision of non dimensional mass flow rates of both forms
from the plot we can observe that non conservative form has more fluctuations when compared to conservative form thus non conservative is less satisfactory when compared to conservative
Grid Dependence test:
At throat point the values non dimensionalized parameters for both conservative and non conservative are given below
for n = 31 Pressure Mach number Temperature density
conservative 0.545 0.981 0.838 0.650
non-conservative 0.534 0.999 0.836 0.638
exact 0.528 1.000 0.833 0.634
for n = 61 Pressure Mach number Temperature density
conservative 0.531 0.9993 0.833 0.638
non-conservative 0.532 0.9997 0.835 0.637
exact 0.528 1.000 0.833 0.634
as we can see there is not much difference between the parameters when the grid value changes from n = 31 to 61 and also the percentage of error is also small between the numerical and exact solution.
Conservative runs faster when compared to non conservative
computational time for conservative is 15.788 seconds whereas the computational time for non conservative is 18.810 seconds