Challenge

Simulation of a 1D Super-sonic nozzle flow simulation using McCormack Method(MATLAB)

Objective: Simulate the isentropic flow through a quasi 1D subsonic-supersonic nozzle.

Solution:

The Governing Continuity, Energy, and Momentum equations for the quasi-1D steady, isentropic flow can be expressed as;

Continuity: `rho_1 V_1A_1=rho_2V_2A_2`

Energy: `h_1+V_1/2=h_2+V_2/2`

Momentum: `P_1A_1+rho_1V_1^2A_1+int PdA=P_2A_2+rho_2V_2^2A_2`

There are different governing equations for Conservative and Non-conservative form;

For Conservation form:

Continuity: `(delp)/(delt)=-rho*(delv)/(delx) -rho*(vdel (LnA))/(delx)-(vdelp)/(delx)`

Energy: `(delv)/(delt)= -v* (delv)/(delx)-(1/gamma)*(((delT)/(delx)+(T/rho)*((delrho)/(delx)))`

Momentum: `(delT)/(delt)=-v(delT)/(delx)-(gamma-1)*T*((delv)/(delx)+v*(del LnA)/(delx))`

For Non-Conservation form:

Continuity: `del (rhoA)/ (delt)+del (rhoA)/(delx)=0`

Energy: `(del (rhoAv))/(delt)+(del(rhoAv^2+(1/gamma*rhoA)))/(delx)=1/gamma*p*(delA)/(delx)`

Momentum: `(del(rhoA(e/(gamma-1)+(gamma/2 *v^2))))/(delt)+(del(rhoAv(e/(gamma-1)+(gamma/2*v^2)+pAv)))/(delx)=0`

After getting the governing equations there are three steps to solve this problem;

  1. Mesh: A mesh is a barrier made up of connected strands of metal, fiber, or other flexible or ductile materials. A mesh is similar to a net or a web in that it has many attached strands. Here it is 1D problem so the x-axis is divided into n number of nodes. The 1st and last nodes are known as the values of boundary conditions and the remaining nodes are known as inner nodes.
  2. Discretise: For discretizing the inner nodes of the x-axis, using McCormack's explicit method.
  3. Solve: Finally, in the last step to solve the solution the boundary conditions for subsonic-supersonic flow and initial conditions for rho, T,v, and A are required.

Main Code:

clear all
close all
clc
%Inputs
n=31;
x=linspace(0,3,n);
throat= ((n-1)/2)+1;
nt=1400;

tic
%Function for non-conservative form
[rho,T,v,m,mach,dx,pr,rho_t,T_t,v_t,m_t,mach_t,pr_t]= non_conservative(x,n,throat);

%Simulation Time
non_conservative_simulation_time=toc

tic
%%Function for conservative form
[rho2,T2,v2,m2,mach2,pr2,dx,rho_t2,T_t2,v_t2,m_t2,mach_t2,pr_t2]= conservative(x,n,throat);

%Simulation Time
conservative_simulation_time=toc

figure(3)
plot(x,m,'r',"LineWidth",1.5)
hold on
plot(x,m2,'b',"LineWidth",1.5)
hold on
plot(x,linspace(0.579,0.579,n),'--','LineWidth',1.5)
xlabel('non-dimensional distance through nozzle(x)')
ylabel('non-dimensional mass flow rate')
s=legend('non-conservative','conservative','exact solution')
set(s,'location','northeast')
title('non-dimentional mass flow rate comparison')
grid on

xlim([0.00 3.00])
ylim([0.5780 0.5980])

figure(4)
a=subplot(4,1,1)
plot(x,mach)
hold on
plot(x,mach2,'*','color','r','markersize',3)
s=legend(a,{'non-conservative','conservative'})
set(s,'location','northeastoutside')
title('Variation of flow along x-axis')
grid on
pause(0.03)
ylabel('mach')

b=subplot(4,1,2)
plot(x,rho)
hold on 
plot(x,rho2,'*','Color','r','markersize',3)
s=legend(b,{'non-conservative','conservative'})
set(s,'location','northeastoutside')
grid on
pause(0.03)
ylabel('rho')

c=subplot(4,1,3)
plot(x,T,'b','LineWidth',1)
hold on
plot(x,T2,'*','Color','r','markersize',3)
pause(0.03)
s=legend(c,{'non-conservative','conservative'})
set(s,'location','northeastoutside')
grid on
ylabel('T')

d=subplot(4,1,4)
plot(x,pr)
hold on
plot(x,pr2,'*','Color','r','markersize',3)
pause(0.03)
s=legend(d,{'non-conservative','conservative'})
set(s,'location','northeastoutside')
grid on
xlabel('non-dimensional length')
ylabel('pr')

subplot(4,1,4)
xlim([0.00 3.00])
ylim([0.00 1.00])

figure(5)
subplot(4,1,1)
plot(linspace(1,nt,nt),rho_t)
hold on
plot(linspace(1,nt,nt),rho_t2,"Color",'r')
hold on
plot(linspace(nt-400,nt+200,600),linspace(0.634,0.634,600),"Color",'k')
hold on
title('Timewise variation flow at the nozzle throat')
xlabel('no. of time steps')
ylabel('rho')
s=legend({'non-conservative','conservative','analytical solution'})
set(s,'location','northeastoutside')
grid on

subplot(4,1,2)
plot(linspace(1,nt,nt),T_t)
hold on
plot(linspace(1,nt,nt),T_t2,'Color','r')
hold on
plot(linspace(nt-400,nt+200,600),linspace(0.833,0.833,600),'Color','k')
hold on
xlabel('no. of time steps')
ylabel('T')
s=legend({'non-conservative','conservative','analytical solution'})
set(s,'location','northeastoutside')
grid on

subplot(4,1,3)
plot(linspace(1,nt,nt),pr_t)
hold on
plot(linspace(1,nt,nt),pr_t2,"Color",'r')
hold on
plot(linspace(nt-400,nt+200,600),linspace(0.528,0.528,600),'Color','k')
hold on
xlabel('no. of time steps')
ylabel('pr')
s=legend({'non-conservative','conservative','analytical solution'})
set(s,'location','northeastoutside')
grid on

subplot(4,1,4)
plot(linspace(1,nt,nt),mach_t)
hold on
plot(linspace(1,nt,nt),mach_t2,"Color",'r')
hold on
plot(linspace(nt-400,nt+200,600),linspace(1,1,600),'Color','k')
hold on
xlabel('no. of time steps')
ylabel('mach')
s=legend({'non-conservative','conservative','analytical solution'})
set(s,'location','northeastoutside')
grid on 

Function for non-conservation:

function [rho,T,v,m,mach,dx,pr,rho_t,T_t,v_t,m_t,mach_t,pr_t]= non_conservative(x,n,throat)
n=31;
x = linspace(0,3,n);
dx=x(2)-x(1);
throat= ((n-1)/2)+1;

%Initial values
rho=1-0.3146*x;
T =1-0.2314*x; %T=temperature
v =(0.1+1.09*x).*T.^0.5;
a= 1+2.2*(x-1.5).^2; %a=area
gamma=1.4;

%Time Steps
nt= 1400;
dt=0.01;

%Outer time loop
for k= 1:nt
    
    rho_old=rho;
    v_old=v;
    T_old=T;
%Predictor methods
for i= 2:n-1
    dvdx= (v(i+1)-v(i))/dx;
    drhodx= (rho(i+1)-rho(i))/dx;
    dTdx=(T(i+1)-T(i))/dx;
    dlogadx= (log(a(i+1))-log(a(i)))/dx;
%Continuity equation
drhodt_p(i)= -rho(i)*(dvdx)-rho(i)*v(i)*dlogadx-v(i)*(drhodx);
% Momentum equation
dvdt_p(i)= -v(i)*dvdx - (1/gamma)*(dTdx + (T(i)/rho(i))*(drhodx));
%Energy equation
dTdt_p(i)= -v(i)*dTdx - (gamma-1)*T(i)*(dvdx+v(i)*(dlogadx));

%solution 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 methods
for i= 2:n-1
    dvdx= (v(i)-v(i-1))/dx;
    drhodx= (rho(i)-rho(i-1))/dx;
    dTdx=(T(i)-T(i-1))/dx;
    dlogadx= (log(a(i))-log(a(i-1)))/dx;
%Continuity equation
drhodt_c(i)= -rho(i)*(dvdx)-rho(i)*v(i)*dlogadx-v(i)*(drhodx);
% Momentum equation
dvdt_c(i)= -v(i)*dvdx - (1/gamma)*(dTdx + (T(i)/rho(i))*(drhodx));
%Energy equation
dTdt_c(i)= -v(i)*dTdx - (gamma-1)*T(i)*(dvdx+v(i)*(dlogadx));
end
%Average
drhodt= 0.5*(drhodt_p+drhodt_c);
dvdt= 0.5*(dvdt_p+dvdt_c);
dTdt= 0.5*(dTdt_p+dTdt_c);

%Final Solution update
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

%Boundary Condition
%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);

%calculate solution
m=rho.*v.*a;
pr= rho.*T;
mach= v./((T).^0.5);

%throat values
rho_t(k)= rho(throat);
T_t(k)= T(throat);
v_t(k)= v(throat);
m_t(k)= m(throat);
mach_t(k)= mach(throat);
pr_t(k)= pr(throat);

figure(1)
if k==50
   plot(x,m,'r','LineWidth',1.5)
   hold on
elseif k==100
   plot(x,m,'b','LineWidth',1.5)
   hold on
elseif k==250
   plot(x,m,'y','LineWidth',1.5)
   hold on
elseif k==500
   plot(x,m,'k','LineWidth',1.5)
   hold on
elseif k==800
   plot(x,m,'c','LineWidth',1.5)
   hold on  
elseif k==1000
   plot(x,m,'g','LineWidth',1.5)
   hold on 
elseif k==1400
   plot(x,m,'m','LineWidth',1.5)
   hold on  
   grid on
 title('Mass flow rate(non-conserative form) along x,at different time steps')
     xlabel('non-dimensional distance through nozzle');
     ylabel('non-dimensional mass flow rate');
     legend({'50 time steps','100 time steps','250 time steps','500 time steps','800 time steps','1000 time steps','1400 time steps'})
end
end

Function for conservation:

function [rho2,T2,v2,m2,mach2,pr2,dx,rho_t2,T_t2,v_t2,m_t2,mach_t2,pr_t2]=conservative(x,n,throat)
dx=x(2)-x(1);
%Calculate initial values
for i=1:n
    if (x(i)>=0 && x(i)<=0.5)
        rho2(i)=1;
        T2(i)=1;  %T=Temperature
    elseif (x(i)>=0.5 && x(i)<=1.5)
        rho2(i)= 1-0.366*(x(i)-0.5);
        T2(i)= 1-0.167*(x(i)-0.5);
    elseif (x(i)>=1.5 && x(i)<=3.5)
        rho2(i)= 0.634-0.3879*(x(i)-1.5);
        T2(i)= 0.833-0.3507*(x(i)-1.5); 
    end
end
a=1+2.2*(x-1.5).^2; %a=area
v2= 0.59./(rho2.*a);
gamma=1.4;

% vector parameter
u1= rho2.*a;
u2 = rho2.*a.*v2;
u3= u1.*((T2./(gamma-1))+((gamma/2)*(v2.^2)));

%Time
nt=1400;

%Outer Time loop
for k=1:nt
    dt= min(0.5.*(dx./((T2.^0.5)+v2)));
    
    u1_old=u1;
    u2_old=u2;
    u3_old=u3;
    %Flux terms
    f1=u2;
    term= (((gamma-1)/gamma)*(u3-((gamma/2)*(u2.^2./u1))));
    f2= ((u2.^2./u1)+term);
    f3=((gamma*u2.*u3)./u1)-(gamma*(gamma-1)*(u2.^3))./(2*u1.^2);
    
    %predictor method
    for i= 2:n-1
        df1dx(i)= (f1(i+1)-f1(i))/dx;
        df2dx(i)= (f2(i+1)-f2(i))/dx;
        df3dx(i)= (f3(i+1)-f3(i))/dx; %dlogadx(i)= (log(a(i+1))-log(a(i)))/dx
        
    %Source term
    dadx(i)= (a(i+1)-a(i))/dx;
    j2(i) = (1/gamma)*(rho2(i)*T2(i))*dadx(i);
    
    % continuity equation
    du1dt_p(i)= -df1dx(i);
    % momentum equation
    du2dt_p(i)= -df2dx(i)+ j2(i);
    %energy equation
    du3dt_p(i)= -df3dx(i);
    
    %solution 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
 %decoding primitive terms to initialize the corrector step
 rho2= u1./a;
 v2= u2./u1;
 T2= (gamma-1)*((u3./u1)-((gamma*v2.^2)/2));
 
  %Flux terms
    f1=u2;
    term= (((gamma-1)/gamma)*(u3-((gamma/2)*(u2.^2./u1))));
    f2= ((u2.^2./u1)+term);
    f3=((gamma*u2.*u3)./u1)-(gamma*(gamma-1)*(u2.^3))./(2*u1.^2);
    
    %corector method
    for i= 2:n-1
        df1dx(i)= (f1(i)-f1(i-1))/dx;
        df2dx(i)= (f2(i)-f2(i-1))/dx;
        df3dx(i)= (f3(i)-f3(i-1))/dx; %dlogadx(i)= (log(a(i+1))-log(a(i)))/dx
        
    %Source term
    dadx(i)= (a(i)-a(i-1))/dx;
    j3(i) = (1/gamma)*(rho2(i)*T2(i))*dadx(i);
    
    % continuity equation
    du1dt_c(i)= -df1dx(i);
    % momentum equation
    du2dt_c(i)= -df2dx(i)+ j3(i);
    %energy equation
    du3dt_c(i)= -df3dx(i); 
    end
    %average derivative
    du1dt= 0.5*(du1dt_p + du1dt_c);
    du2dt= 0.5*(du2dt_p + du2dt_c);
    du3dt= 0.5*(du3dt_p + du3dt_c);
    
    % Final solution update
    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 Conditions
    %Inlet
    u1(1) = rho2(1)*a(1);
    u2(1) = 2*u2(2)-u2(3);
    v2(1) = u2(1)/u1(1);
    u3(1) = u1(1)*((T2(1)/(gamma-1))+((gamma/2)*v2(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);
    
    %decoding term
    rho2 = u1./a;
    v2 = u2./u1;
    T2 = (gamma-1)*((u3./u1)-((gamma*v2.^2)/2));
    m2 = rho2.*v2.*a;
    mach2 = v2./((T2).^0.5);
    pr2 = rho2.*T2; %pressure ratio
    
    %throat values
    rho_t2(k) = rho2(throat);
    T_t2(k)= T2(throat);
    v_t2(k)= v2(throat);
    m_t2(k)= m2(throat);
    mach_t2(k)= mach2(throat);
    pr_t2(k)= pr2(throat);
    
    figure(2)
    if k==50
        plot(x,m2,'r','LineWidth',1.5)
        hold on
    elseif k==100
        plot(x,m2,'b','LineWidth',1.5)
        hold on
    elseif k==250
        plot(x,m2,'y','LineWidth',1.5)
        hold on
    elseif k==500
        plot(x,m2,'k','LineWidth',1.5)
        hold on
    elseif k==800
        plot(x,m2,'c','LineWidth',1.5)
        hold on  
    elseif k==1000
        plot(x,m2,'g','LineWidth',1.5)
        hold on 
    elseif k==1400
        plot(x,m2,'m','LineWidth',1.5)
        hold on  
        grid on
     title('Mass flow rate(conserative form) along x,at different time steps')
     xlabel('non-dimensional distance through nozzle');
     ylabel('non-dimensional mass flow rate');
     legend({'50 time steps','100 time steps','250 time steps','500 time steps','800 time steps','1000 time steps','1400 time steps'})
    end
    end
      
    

PLOTS:

1. Variation of Mass flow rate distribution inside the nozzle at different time steps during the time-marching process.

1.1 For non-conservative form:

  • From the above plot, it can be observed that mass flow rate curves are almost overlapping for time step 800, 1000 & 1400. It is seen that after 800-time steps, steady-state is obtained for non-conservative form.

1.2 For non-conservative form:

  • From the above plot, it can be observed that mass flow rate curves are almost overlapping for time step 500, 800, 1000 & 1400. When compared to the non-conservative plot, the fluctuations are less compared to the conservative plot.

2. Comparison of Non-dimensional mass flow rate:

  • The conservative form of the equation gives better results for mass flow rate than the non-conservative form.

3. Distribution of primitive variables inside the nozzle:

  • The above plot shows the variation of flow along the x-axis with different primitive variables. It is seen that after 1400 time-steps carried out by time marching, both the forms show similar plots.

4.Time-wise variation of the primitive variables:

  • The above plot shows, Time-wise variation of the primitive variables. From the above plot, it is seen that steady-state is obtained almost after 600-time steps.

Conclusion:

  • In this project, we have successfully simulated isentropic flow through a quasi 1D subsonic-supersonic nozzle. Here, we have derived both the conservation and non-conservation forms of the governing equations and solved them using MacCormack's technique.
  • Differences between the two forms of governing equations were compared with their solutions.

References:

1.Computations Fluid Dynamics: The Basics and Applications- John D. Anderson

2.https://skill-lync.freshdesk.com/support/solutions/articles/43000560114-conservation-vs-non-conservation-forms-of-governing-equations

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.