Challenge

Week 7 - Simulation of a 1D Super-sonic nozzle flow simulation using Macormack Method

AIM :

Simulate the isentropic flow through a quasi 1D subsonic-supersonic nozzle using the conservative and non-conservative forms of governing equations and solve them using the MacCormack's technique and compare the solutions of both the forms.

PROBLEM DEFINITION

A 1D converging - diverging nozzle (CD Nozzle) is used to solve the proble as shown in the figure.

  • It is assumed that there is only flow in x direction. The primitive variables are varying along the length of the nozzle as the flow occurs.
  • The flow in the convergent area is always subsonic and the flow in the divergent area is supersonic.
  • We are considering non-dimensionalied quanities for writing the governing equations and solving them.

The Governing equations in Non-conservative form are as follows

1. Continuity Equation.

`(delrho')/(delt') =-rho'(delv')/(delx')-rho'v'(dellnA')/(delx')-v'(delrho')/(delx')`

2. Momentum Equation

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

3. Energy Equation

`(delT')/(delt') =-v'(delT')/(delx')-(gamma-1)T'[(delv')/(delx')+v'(dellnA')/(delx')]`

Where `gamma=1.4`

  • Shape of the Nozzle ( Area function )

`A'=1+2.2(x-1.5)^2`

  • The initial condition for Non-conservative form at `t=0`;

`rho' = 1-0.3146x'`

`T' = 1-0.2314x'`

`v = (0.1+1.09x')T'^(1/2)`

  • Mass flow rate `m'=rho'A'v'`
  • Pressure `P'=rho'T'`
  • Mach Number `M = (v')/sqrt(T')`

The Governing equations in Conservative form are as follows

1. Continuity Equation

`(delU_1)/(delt') = -(delF_1)/(delx')`

2. Momentum Equation

`(delU_2)/(delt') = -(delF_2)/(delx')+J_2`

3. Energy Equation

`(delU_3)/(delt') = -(delF_3)/(delx')`

Where;

`F_1,F_2,F_3` are the flux vectors`

`U_1,U_2,U_3` are the solution vectors and `J_2` is the source term

Defined as;

`U1 = rho'A'`

`U2=rho'A'v'`

`U3=rho'A'[(T')/(gamma-1) + (gamma)/2v'^2]`

`F_1 = U_2`

`F_2=(U_2^2)/(U_1)+(gamma-1)/gamma[U_3-gamma/2(U_2^2)/U_1]`

`F_3=(gamma(U_2U_3)/U_1) - gamma((gamma-1)/2)(U_2^3/u_1^2)`

`J_2 = 1/gammarho'T'(delA')/(delx')`

  • Shape of the Nozzle ( Area function )

`A'=1+2.2(x-1.5)^2`

  • The initial condition for Non-conservative form at `t=0`;

`rho'=1` for `0<=x'<=0.5`

`rho' = 1-0.366(x'-0.5)` for `0.5<=x'<=1.5`

`rho' = 0.634-0.3879(x'-1.5)` for `1.5<=x'<=3.5`

`T'=1` for `0<=x'<=0.5`

`T' = 1-0.167(x'-0.5)` for `0.5<=x'<=1.5`

`T' = 0.833-0.13507(x'-1.5)` for `1.5<=x'<=3.5`

  • Density `rho'=U_1A'`
  • Pressure `P' = rho'T'`
  • Velocity `v'=U_2/U_1`
  • Temperature `T'=(gamma-1)(U_3/U_1-gamma/2v^2)`
  • Mach Number `M = (v')/sqrt(T')`
  • Mass flow rate `m' =U_2`

Methodology

The Governing equations in both the forms are solved by Macormack Method uaing Time marching

Macormack Method: In this method the governing equations are solved in two steps; First step is called Predictor method and second step is called corrector method.

1. Predictor step: Here the equations are solved using forward difference method

Solution Update: Here the solution is added with initial solutions and an updated solution is obtained.

2. Corrector Step: A backward differencing is carried out and asolution is obtained. Later an averaged result is obtaied by averaging predictor and corrector step.

Final solution Update: Final solution is update itn this step

The following matlab code is used to solve this 1D subsonic-supersonic nozzle problem.:

Main Program:

% Simulation of a 1D Super-sonic nozzle flow simulation using Macormack Method

clc
clear all
close all

%  inputs, definig the spacial grid
n = [31 61];

gamma = 1.4;
C = 0.5;   % CFL number

% Time step
nt = 1:1400;
% dt = 0.01;

for nn = 1:length(n)
    
x = linspace(0,3,n(nn));

% Solving non-conservative equation
[m1,m1_throat,dt] = non_conservative(n(nn),nt,gamma,C);

% Soving conservative equation
[m2,m2_throat,dt] = conservative(n(nn),nt,gamma,C);

% Comparison of Normalized mass flow rate distributions of both forms
if n(nn)==31
figure(7)
subplot(2,1,1)
plot(nt,m1_throat,nt,m2_throat,'Linewidth',2)
title({['Mass flow rate distribution at throat'],['Non-conservative vs conservtive']})
legend('Non-conservative','Conservative')
xlabel('Timestep')
ylabel('Mass flow rate')

subplot(2,1,2)
plot(x,m1,x,m2,x,0.579,'*','Linewidth',2)
title({['Mass flow rate distribution in nozzle'],['Non-conservative vs conservtive']})
legend('Non-conservative','Conservative','Actual')
xlabel('Nozzle length')
ylabel('Mass flow rate')
end

% Grid independency test at throat
figure(8)
subplot(2,1,1)
plot(nt,m1_throat,'Linewidth',2)
xlabel('Timestep')
ylabel('Mass flow rate')
legend('31 nodes','61 nodes')
title('Conservative: Grid independency at throat')
hold on

subplot(2,1,2)
plot(nt,m2_throat,'Linewidth',2)
xlabel('Timestep')
ylabel('Mass flow rate')
legend('31 nodes','61 nodes')
title('Non-Conservative: Grid independency at throat')
hold on

end


Funcion file: Non-Conservative form:

function [m1,m1_throat,dt] = non_conservative(n,nt,gamma,C)

%  inputs defining spacial grid
x = linspace(0,3,n);
dx = x(2) - x(1);


% Initial connditions
rho = 1-0.3146*x;   % density
T = 1-0.2314*x;     % Temperature
v = (0.1+1.09*x).*T.^0.5; %Velocity

% Area profile
A = 1+2.2*(x-1.5).^2;  % Area 

% Time loop
for i = 1:length(nt)
    
%     Defiining dt using CFL number
    for z=1:n
        dt(z) = C*dx/(sqrt(T(z))+v(z));
    end
    
    dt = min(dt);
    
    rho_old = rho;
    T_old = T;
    v_old = v;
    
    % Predictor step
    for j = 2:n-1
        
        % Forward differencing
        drho_dx = (rho(j+1)-rho(j))/dx;
        dv_dx = (v(j+1)-v(j))/dx;
        dlnA_dx = (log(A(j+1))-log(A(j)))/dx;
        dT_dx = (T(j+1)-T(j))/dx;
        
        % continuity equation
        drho_dt_p(j) = -rho(j)*dv_dx-rho(j)*v(j)*dlnA_dx-v(j)*drho_dx;
        
        % momentum equation
        dv_dt_p(j) = -v(j)*dv_dx-(1/gamma)*(dT_dx+(T(j)/rho(j))*drho_dx);
        
        % Energy equation
        dT_dt_p(j) = -v(j)*dT_dx - (gamma-1)*T(j)*(dv_dx+v(j)*dlnA_dx);
        
        % Solution updated
        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
    
    % corrector step
    for j = 2:n-1
        
        % Backward differencing
        drho_dx = (rho(j)-rho(j-1))/dx;
        dv_dx = (v(j)-v(j-1))/dx;
        dlnA_dx = (log(A(j))-log(A(j-1)))/dx;
        dT_dx = (T(j)-T(j-1))/dx;
        
        % continuity equation
        drho_dt_c(j) = -rho(j)*dv_dx-rho(j)*v(j)*dlnA_dx-v(j)*drho_dx;
        
        % momentum equation
        dv_dt_c(j) = -v(j)*dv_dx-1/gamma*(dT_dx+T(j)/rho(j)*drho_dx);
        
        % Energy equation
        dT_dt_c(j) = -v(j)*dT_dx - (gamma-1)*T(j)*(dv_dx+v(j)*dlnA_dx);                 
      
    end
    
        % Averaged solution
        drho_dt = 0.5*(drho_dt_p+drho_dt_c);
        dv_dt = 0.5*(dv_dt_p+dv_dt_c);
        dT_dt = 0.5*(dT_dt_p+dT_dt_c);
        
        % final solution update
        for k=2:n-1
        rho(k) = rho_old(k)+drho_dt(k)*dt;
        v(k) = v_old(k)+dv_dt(k)*dt;
        T(k) = T_old(k)+dT_dt(k)*dt;
        
        end
        
       % Pressure calculation
        P = rho.*T;  
        
        % Mach number
        M = v./sqrt(T);
        
        % mass flow rate
        m1 = rho.*A.*v;
        
        % Applying new boundary conditions
        % 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);
        
        % Throat section properties
        rho_throat(i) = rho(16);
        v_throat(i) = v(16);
        T_throat(i) = T(16);
        P_throat(i) = P(16);
        M_throat(i) = M(16);
        m1_throat(i) = m1(16);
        
% Ploting mass flow rate at different timestep

if n==31    
            if i == 1
            figure(1)
            plot(x,m1,'Linewidth',2)
            hold on         
            elseif i==50
                plot(x,m1,'Linewidth',2)
            elseif i==200
                plot(x,m1,'Linewidth',2)
            elseif i==500
                plot(x,m1,'Linewidth',2)
            elseif i==1400
                plot(x,m1,'*','Linewidth',2)
                legend('nt=1','nt=50','nt=200','nt=500','nt=1400')
                title({['Variation of Mass flow rate distribution inside the nozzle at different'],['time steps during the time-marching process:Non-conservative']})
                xlabel('Length of Nozzle')
                ylabel('Mass Flow rate - Non dimensionalized')
            end        
end
        
end
% Ploting distribution of primitive variable inside the nozzle
if n==31
    figure(2)
        plot(x,v,x,rho,x,T,x,P,x,M,x,m1,'Linewidth',2)
%       title(sprintf('Time step = %d',i))
        title('Distribution of primitive variables inside the Nozzle:Non-conservative')
        xlabel('Length of Nozzle')
        ylabel('Non-dimensionalised Variable')
        legend('Velocity','Density','Temperatture','Pressure','Mach Number','Mass flow rate','Location','northwest')

%  Variation of primitive parameters with Timestep       
        figure(3)        
        plot(nt,v_throat,nt,rho_throat,nt,T_throat,nt,P_throat,nt,M_throat,nt,m1_throat,'Linewidth',2)
        legend('Velocity','Density','Temperatture','Pressure','Mach Number','Mass flow rate','Location','northeast')
        title('Variation of primitive parameters with Timestep at throat:Non-Conservative')
        xlabel('Timestep')
        ylabel('Variable')
end   
end

Function file: Conservative form:

function[m2,m2_throat,dt] = conservative(n,nt,gamma,C)

%  inputs defining spacial grid
x = linspace(0,3,n);
dx = x(2) - x(1);

% defininig area profile
A = 1+2.2.*(x-1.5).^2;  % Area

% Initial connditions
for nx=1:length(x)
    if x(nx)<=0.5   
        rho(nx) = 1;
        T(nx) = 1;
    elseif (x(nx)>0.5) && (x(nx)<=1.5)
        rho(nx) = 1-(0.366*(x(nx)-0.5));
        T(nx) = 1- (0.167*(x(nx)-0.5));
    elseif (x(nx)>1.5) && (x(nx)<=3.5)
        rho(nx) = 0.634-(0.3879*(x(nx)-1.5));
        T(nx) = 0.833 - (0.3507*(x(nx)-1.5));
    end
end

v = 0.59./(rho.*A);

% Defining solution vectors
u1 = rho.*A;
u2 = rho.*A.*v;
u3 = rho.*A.*(T./(gamma-1) + (gamma./2.*v.^2));

%     Defiining dt using CFL number
for z=1:n
        dt(z) = C*dx/(sqrt(T(z))+v(z));
    end
     dt = min(dt);
     
% Time loop
for i = 1:length(nt)    
    
    % Storing initial solutions 
     u1_old = u1;
     u2_old = u2;
     u3_old = u3;
     
      % Defining Flux vectors
        f1 = u2;
        f2 = u2.^2./u1 + ((gamma-1)/gamma).*(u3-gamma./2*(u2.^2)./u1);
        f3 = (gamma*u2.*u3./u1) - (gamma*(gamma-1)/2)*(u2.^3./u1.^2);
     
     % du1/dt = -df1/dx
     % du2/dt = -df2/dx+j2
     % du3/dt = -df3/dx
     % j2 = 1/gamma*rho*T*dA_dx;
     
     % Predictor step
     for j = 2:n-1       
           
        % Forward differencing
        df1_dx = (f1(j+1)-f1(j))/dx;
        df2_dx = (f2(j+1)-f2(j))/dx;
        df3_dx = (f3(j+1)-f3(j))/dx;
        dA_dx = (A(j+1)-A(j))/dx;
        
        % Source term
        j2_p(j) = 1./gamma*rho(j).*T(j).*dA_dx;
        
        % continuity equation
        du1_dt_p(j) = -df1_dx;
        
        % momentum equation
        du2_dt_p(j) = -df2_dx +j2_p(j);
        
        % Energy equation
        du3_dt_p(j) = -df3_dx;
%         
        % updated solution vectors
        u1(j) = u1_old(j) + du1_dt_p(j)*dt;
        u2(j) = u2_old(j) + du2_dt_p(j)*dt;
        u3(j) = u3_old(j) + du3_dt_p(j)*dt;
        
        % Upfating the variables
        rho =   u1./A;
        v = u2./u1;
        T = (gamma-1).*(u3./u1-gamma./2*v.^2);
         
        % Updating flux terms
        f1 = u2;
        f2 = u2.^2./u1 + ((gamma-1)/gamma)*(u3-gamma./2*(u2.^2)./u1);
        f3 = (gamma*u2.*u3./u1) - (gamma*(gamma-1)/2)*(u2.^3./u1.^2);
        
     end
     
     % corrector step
     for j = 2:n-1         
         
        % Backward differencing
        df1_dx = (f1(j)-f1(j-1))/dx;
        df2_dx = (f2(j)-f2(j-1))/dx;
        df3_dx = (f3(j)-f3(j-1))/dx;
        dA_dx = (A(j)-A(j-1))/dx;
        
        %Source term
        j2_c(j) = 1./gamma.*rho(j).*T(j).*dA_dx;
        
        % continuity equation
        du1_dt_c(j) = -df1_dx;
        
        % momentum equation
        du2_dt_c(j) = -df2_dx +j2_c(j);
        
        % Energy equation
        du3_dt_c(j) = -df3_dx;        
        
     end
     
        % Averaged solution
        du1_dt = 0.5*(du1_dt_p+du1_dt_c);
        du2_dt = 0.5*(du2_dt_p+du2_dt_c);
        du3_dt = 0.5*(du3_dt_p+du3_dt_c);
        
        % final solution update
        for k=2:n-1
        u1(k) = u1_old(k)+du1_dt(k)*dt;
        u2(k) = u2_old(k)+du2_dt(k)*dt;
        u3(k) = u3_old(k)+du3_dt(k)*dt;        
        end
        
        % Final variable update
        rho = u1./A;
        v = u2./u1;
        T = (gamma-1).*(u3./u1-gamma./2*v.^2); 
        P = rho.*T;
        M = v./sqrt(T);
        m2 = u2; 
        
        % Applying new boundary conditions
        % inlet
        u1(1) = A(1);
        u2(1) = 2*u2(2) - u2(3);
        u3(1) = u1(1)*(T(1)/(gamma-1) +gamma/2*v(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);
        
        
        % Throat section properties
        rho_throat(i) = rho(16);
        v_throat(i) = v(16);
        T_throat(i) = T(16);
        P_throat(i) = P(16);
        M_throat(i) = M(16);
        m2_throat(i) = m2(16);
        
%   Ploting mass flow rate at different timestep

if n==31
        
        if i == 1
            figure(4)
            plot(x,m2)
            hold on         
            elseif i==50
                plot(x,m2,'Linewidth',2)
            elseif i==200
                plot(x,m2,'Linewidth',2)
            elseif i==500
                plot(x,m2,'Linewidth',2)
            elseif i==1400
                plot(x,m2,'*')
                legend('nt=1','nt=50','nt=200','nt=500','nt=1400')
                title({['Variation of Mass flow rate distribution inside the nozzle at different'],['time steps during the time-marching process:Conservative']})
                xlabel('Length of Nozzle')
                ylabel('Mass Flow rate - Non dimensionalized')
            end
end
end
% Ploting distribution of primitive variable inside the nozzle
 if n==31
     figure(5)
        plot(x,v,x,rho,x,T,x,P,x,M,x,m2,'Linewidth',2)
%       title(sprintf('Time step = %d',i))
        title('Distribution of primitive variables inside the Nozzle:Conservative')
        xlabel('Length of Nozzle')
        ylabel('Non-dimensionalised Variable')
        legend('Velocity','Density','Temperatture','Pressure','Mach Number','Mass flow rate','Location','northwest')

% Variation of primitive parameters with Timestep        
        figure(6)        
        plot(nt,v_throat,nt,rho_throat,nt,T_throat,nt,P_throat,nt,M_throat,nt,m2_throat,'Linewidth',2)
        legend('Velocity','Density','Temperatture','Pressure','Mach Number','Mass flow rate','Location','northeast')
        title('Variation of primitive parameters with Timestepat throat:Conservative')
        xlabel('Timestep')
        ylabel('Variable')
 end
 
end

        
       

Results:

After executing the above program, following results were obltained.

1. Non-Conservative Form

  • Figure (1):Distribution of primitive variables inside the nozzle

Figure 1 shows the variation of primitive parameters inside the nozzle. It is clear that the massflow rate is constant through out the length of the nozzle. Velocity is increasing as the flow continues its path. Simultaneously a supersonic flow (M>1) is observed at the nozzle exit. All the variables obtained are matching with the Anderson text data.

  • Figure(2): Time-wise variation of primitive variables

Figure(2) shows the time-wise variation of primitive variables at the throat section. It is clear from the graph that the variables are unstable during the initial timesteps and as the step increases it became stable. after 500 timesteps the parameters became very stable.

  • Figure(3): Variation of Mass flow rate distribution inside the nozzle at different time steps during the time-marching process

Figure(3) represents the variation of mass flow rate at different timesteps during the time-marching process. We can observe the mass flow rate at time steps 1,50,200, 500 and 1400. It is clear that after 500 timestep the mass flow rate is converging to a particular value. We can see that after 1400 steps the mass flow rate almost constant.

2. Conservative Form

  • Figure(4): Distribution of primitive variables inside the nozzle

Figure(4) shows the variation of primitive parameters inside the nozzle. It is clear that the massflow rate is constant through out the length of the nozzle. Velocity is increasing as the flow continues its path. Simultaneously a supersonic flow (M>1) is observed at the nozzle exit. All the variables obtained are matching with the Anderson text data.

  • Figure(5): Time-wise variation of primitive variables

Figure(5) shows the time-wise variation of primitive variables at the throat section. It is clear from the graph that the variables are unstable during the initial timesteps and as the step increases it became stable. after 500 timesteps the parameters became very stable. The values are almost same as in Non-conervative form.

  • Figure(6): Variation of Mass flow rate distribution inside the nozzle at different time steps during the time-marching process

Figure(6) represents the variation of mass flow rate at different timesteps during the time-marching process. We can observe the mass flow rate at time steps 1,50,200, 500 and 1400. It is clear that after 500 timestep the mass flow rate is converging to a particular value. We can see that after 1400 steps the mass flow rate almost constant.

3. Comparison: Non-conservative vs Conservative form

The above plot gives a comparison of non-conservative and conservative forms.

The first subplot campares the massflow rate at the throat at different timestep. Eventhough both forms converged to same stable solution, the Conservative form becomes stable faster than the Non-conservative form.

The second subplot compares the massflow rate though out the nozzle. We can observe that Conservative form is giving a constant massflow rate through out the nozzle.

4. Grid independence test on the solution

The above figure shows the grid independence test on the solution at the throat section. In both non conservative and conservative forms, lesser number of node gave a faster stable solution than higher number of nodes.

Conclusion

  • From the study conducted above, it is clear that the Non-conservative as well as conservative forms of governing equation results almost same solutions.
  • Both the form needs a minimum number of timestep to reach a stable solutions. At throat conservative form converged with lesser number of timesteps.
  • Even after varying the number of nodes, alsmost same results were obtaned with less error.
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.