Challenge

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

Objective:

To simulate the isentropic flow through a 1D subsonic - supersonic nozzle using both conservative and non conservative forms of the governing equations and solving them using the Maccormack technique, and analyse the results.

Solution

Theory

We conside the isentropic flow through a convergent - divergent nozzle. The flow at the inlet comes from a reservoir. The cross sectional area of the reservoir is large and the velocity is correspondingly small.

The flow is subsonic (Mach number <1) at the convergent section,sonic at the throat (Mach numer = 1) and supersonic at the divergent section (M>1)

Considering a small control volume as shown below

The cross sectional area is A, and it is assumed that the flow properties are uniform across the section.

Although the area of the nozzle changes as a function of distance along X-direction, the flow field in reality is two dimensional. The flow varies along X and Y directions. We assume that the flow varies only along X - direction.

Non conservative form

The governing continuity, momentum and energy equations can be expressed in non-conservative form as

Continuity equation

`(delrho')/(delt') = -rho'((delV')/(delx')) - rho'V'((del(ln A'))/(delx')) - V'((delrho')/(delx'))`

Momentum equation

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

Energy equation

`(delT')/(delt') = -V'((delT')/(delx')) - (gamma -1)T'[(delV')/(delx') + V'(del(lnA'))/(delx')]`

Conservative form

Continuity equation

`(del(rho'A'))/(delt') + (del(rho'A'V'))/(delx') = 0`

Momentum equation

`(del(rho'A'V'))/(delt') + (del[rho'A'(V')^2 +(1/gamma)rho'A'])/(delx') = (1/gamma)rho'((delA')/(delx'))`

Energy equation

`(del[rho'((e')/(gamma-1) + (gamma/2)(V')^2)A'])/(delt') + (del[rho'((e')/(gamma-1) + (gamma/2)(V')^2)V'A' + rho'A'V'])/(delx') = 0`

For air at standard conditions, `gamma = 1.4`

Maccormack method

The steps involved are

1. Initial profile

The initial profile for all the flow field variables - velocity, density and temperature has to be determined.

2. Predictor step

`((delf)/(dt))_p = (f(i+1) - f(i))/(Deltax`

3. Solution update

`f_p = f_(Initial) + ((delf)/(delt))_p * Deltat`

`f_p =` Flow field variables after predictor step

`f_(Initial) =` flow field variable in the initial step

`Deltat =` time step size

4. Corrector step

`((delf_p)/(dt))_c = (f(i) - f(i-1))/(Deltax`

`((delf)/(dt))_(avg) = 0.5(((delf)/(dt))_p +((delf_p)/(dt))_c )`

5. Final solution update

`f_(sol) = f_(Initial) + ((delf)/(delt))_(avg) * Deltat`

`f_(sol) =` Final solution of the flow field variabes for first time step

Matlab code

Main program

clear all
close all
clc

L = 3;
n = [31 62 93];
nt = 1:1400;
cfl = 0.5;
for i = 1:length(n)
    x = linspace(0,L,n(i));
    [mfr_nc,mfr_throat_nc] = non_conservative(L,n(i),nt,cfl);
    [mfr_c,mfr_throat_c] = conservative(L,n(i),nt,cfl);
    
    figure(7)
    subplot(2,1,1)
    plot(nt,mfr_throat_c,'b',nt,mfr_throat_nc,'r','linewidth',1);
    xlabel('Time steps(nt)');
    ylabel('Mass flow rate');
    legend('Conservative form','Non conservative form');
    title('Mass flow rate - Conservative vs non conservative form at throat point');
    
    subplot(2,1,2)
    plot(x,mfr_c,'b',x,mfr_nc,'r','linewidth',1);
    xlabel('Length of nozzle');
    ylabel('Mass flow rate');
    legend('Conservative form','Non conservative form');
    title('Mass flow rate - Conservative vs non conservative form in the nozzle');
    
    figure(8)
    subplot(2,1,1)
    plot(nt,mfr_throat_c,'linewidth',1);
    hold on
    xlabel('Time steps(nt)');
    ylabel('Mass flow rate');
    legend('@31 nodes','@62 nodes','@93 nodes');
    title('Conservative form - Grid independency test at throat point');
    
    subplot(2,1,2)
    plot(nt,mfr_throat_nc,'linewidth',1);
    hold on
    xlabel('Time steps(nt)');
    ylabel('Mass flow rate');
    legend('@31 nodes','@62 nodes','@93 nodes');
    title('Non conservative form - Grid independency test at throat point');
    
    figure(9)
    subplot(2,1,1)
    plot(x,mfr_c,'linewidth',1);
    hold on
    xlabel('Length of nozzle');
    ylabel('Mass flow rate');
    legend('@31 nodes','@62 nodes','@93 nodes');
    title('Conservative form - Grid independency test along the nozzle');
    
    subplot(2,1,2)
    plot(x,mfr_nc,'linewidth',1);
    hold on
    xlabel('Length of nozzle');
    ylabel('Mass flow rate');
    legend('@31 nodes','@62 nodes','@93 nodes');
    title('Non conservative form - Grid independency test along the nozzle');
end

Non - conservative function

function [mfr_nc,mfr_throat_nc] = non_conservative(L,n,nt,cfl)

% inputs

x = linspace(0,3,n);
dx = x(2) - x(1);


% initial profiles
rho = 1-0.3146*x;
t = 1-0.2314*x;
v = (0.1+0.9*x).*t.^0.5;

% area
a = 1+2.2*(x-1.5).^2;
M = v./(t.^0.5);
mfr = rho.*a.*v;
p = rho.*t;

% Time steps

for z = 1:31
    u = (t(z))^(1/2);
    dt(z) = cfl*dx/(u+v(z));
end
dt = min(dt);
gamma = 1.4;

% Outer loop - time
for k = 1:length(nt)
    
    rho_old = rho;
    v_old = v;
    t_old = t;
    
    % Predictor
   
    for j = 2:n-1
        dv_dx = (v(j+1) - v(j))/dx;
        drho_dx = (rho(j+1)-rho(j))/dx;
        dt_dx = (t(j+1) - t(j))/dx;
        dloga_dx = (log(a(j+1)) - log(a(j)))/dx;
        
        % Continuity eqn
        drho_dt_p(j) = -rho(j)*dv_dx - rho(j)*v(j)*dloga_dx - v(j)*drho_dx;
        
        % Momentum eqn
        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)*dloga_dx);
        
        % Solution update
        rho(j) = rho_old(j) + drho_dt_p(j)*dt;
        v(j) = v_old(j) + dv_dt_p(j)*dt;
        t(j) = t_old(j) + dt_dt_p(j)*dt;
        
    
    
    % Corrector method
    
        dv_dx = (v(j) - v(j-1))/dx;
        drho_dx = (rho(j)-rho(j-1))/dx;
        dt_dx = (t(j) - t(j-1))/dx;
        dloga_dx = (log(a(j)) - log(a(j-1)))/dx;
        
        % Continuity eqn
        drho_dt_c(j) = -rho(j)*dv_dx - rho(j)*v(j)*dloga_dx - v(j)*drho_dx;
        
        % Momentum eqn
        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)*dloga_dx);
        
        
end
    
    % Average time derivative
    
    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 soltion update
    
    for i = 2:n-1
        rho(i) = rho_old(i) + drho_dt(i)*dt;
        v(i) = v_old(i) + dv_dt(i)*dt;
        t(i) = t_old(i) + dt_dt(i)*dt;
    end
    
    % Boundary condition
    
    % 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);
    
    %Primitives update
    p = rho.*t;
    M = v./t.^0.5;
    error(i) = abs(v(i) - v(i-1));
    mfr = rho.*a.*v;
    
    %values at throat point
    t_throat(k) = t(16);
    rho_throat(k) = rho(16);
    v_throat(k) = v(16);
    p_throat(k) = p(16);
    M_throat(k) = M(16);
    error_throat(k) = error(16);
    mfr_throat(k) = mfr(16);
    
    if n==31
        for p = [1:50:201 700]
            if p == k
                figure(1)
                plot(x,mfr,'linewidth',2);
                hold on
                title('Non conservative form - Varitation of mass flow rate at different time steps');
                xlabel('Length of nozzle');
                ylabel('Mass flow rate');
            elseif k == 1400
                plot(x,mfr,'*r');
                legend('@1','@51','@101','@151','@201','@700','@1400');
            end
        end
    end
end

if n == 31
    figure(2)
    plot(x,v,'b',x,p,'r',x,t,'k',x,rho,'m',x,M,'g',x,mfr,'c');
    ylim([-0.1 3.7]);
    title(sprintf('Time step = %d',i));
    xlabel('Length of nozzle');
    ylabel('Non dimensional parameters');
    legend('Velocity','Pressure','Temperature','Density','Mach number','Mass flow rate');
    title('Non conservative form - Steady state distriubution of primitive variables inside the nozzle');
    
    figure(3)
    plot(nt,rho_throat)
    hold on
    plot(nt,v_throat,'linewidth',1);
    plot(nt,p_throat,'linewidth',1);
    plot(nt,t_throat,'linewidth',1);
    plot(nt,M_throat,'linewidth',1);
    plot(nt,mfr_throat,'linewidth',1);
    xlabel('Time steps(nt)');
    ylabel('Non dimensional parameters');
    legend('Density','Velocity','Pressure','Temperature','Mach number','Mass flow rate');
    title('Non conservative form - Time wise variation of primitive variables at throat i = 16');
end

mfr_nc = mfr;
mfr_throat_nc = mfr_throat;
end

Conservative function

function [mfr_c,mfr_throat_c] = conservative(L,n,nt,cfl)

x = linspace(0,L,n);
dx = x(2) - x(1);

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

a = 1+2.2*(x-1.5).^2;
gamma = 1.4;

% Solution vectors u1, u2 and u3

u1 = rho.*a;
u2 = 0.59*ones(1,n);
v = u2./u1;
u3 = u1.*((T./(gamma-1))+(gamma/2).*v.^2);

M = v./(T.^0.5);
mfr = rho.*a.*v;
p = rho.*T;

for z = 1:31
    u = (T(z))^(1/2);
    dt(z) = cfl*dx/(u+v(z));
end
dt = min(dt);

for k = 1:length(nt)
    %Initial values
    u1_old = u1;
    u2_old = u2;
    u3_old = u3;
    
    for j = 2:n-1
        % 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));
        
        % Source term
        j1 = (1/gamma)*rho(j)*T(j)*((a(j+1) - a(j))/dx);
        
        % Predictor step
        
        du1_dt_p(j) = -(f1(j+1) - f1(j))/dx;
        du2_dt_p(j) = -(f2(j+1) - f2(j))/dx + j1;
        du3_dt_p(j) = -(f3(j+1) - f3(j))/dx;
        
        % Updating 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;
        
        % Updating primitives
        rho = u1./a;
        T = (gamma - 1).*(u3./u1-(gamma/2).*(u2./u1).^2);
        
        % Updating flux terms
        f1 = u2;
        f2 = u2.^2./u1 + ((gamma-1)/gamma).*(u3 - (gamma/2)*u2.^2./u1);
        f3 = gamma.*u2.*u3./u1 - 0.5*gamma*(gamma-1).*u2.^3./u1.^2;
        
        % Source term for corrected step
        j2 = (1/gamma)*(rho(j)*T(j)*(a(j) - a(j-1))/dx);
        
        % Corrector step
        du1_dt_c(j) = -(f1(j) - f1(j-1))/dx;
        du2_dt_c(j) = -(f2(j) - f2(j-1))/dx + j2;
        du3_dt_c(j) = -(f3(j) - f3(j-1))/dx;
        
    end
    
    % Average time derivatives
    
    du1_dt_avg = 0.5*(du1_dt_p + du1_dt_c);
    du2_dt_avg = 0.5*(du2_dt_p + du2_dt_c);
    du3_dt_avg = 0.5*(du3_dt_p + du3_dt_c);
    
    % Final corrected values
    
    for i = 2:n-1
        u1(i) = u1_old(i) + du1_dt_avg(i)*dt;
        u2(i) = u2_old(i) + du2_dt_avg(i)*dt;
        u3(i) = u3_old(i) + du3_dt_avg(i)*dt;
    end
    
    % Boundary conditions
    % Inlet
    
    u1(1) = a(1);
    u2(1) = 2*u2(2) - u2(3);
    u3(1) = u1(1)*(T(1)/(gamma-1) + (gamma*(u2(1)/u1(1))^2)/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);
    
    % Final update of primitives
    rho = u1./a;
    v = u2./u1;
    T = (gamma-1).*(u3./u1 - (gamma/2).*(u2./u1).^2);
    p = rho.*T;
    M = v./T.^0.5;
    error(i) = abs(v(i) - v(i-1));
    mfr = u2;
    
      %values at throat point
    t_throat(k) = T(16);
    rho_throat(k) = rho(16);
    v_throat(k) = v(16);
    M_throat(k) = M(16);
    p_throat(k) = p(16);
    error_throat(k) = error(16);
    mfr_throat(k) = mfr(16);
    
    if n==31
        for p = [1:50:201 700]
            if p == k
                figure(4)
                plot(x,mfr,'linewidth',2);
                hold on
                title('conservative form - Varitation of mass flow rate at different time steps');
                xlabel('Length of nozzle');
                ylabel('Mass flow rate');
            elseif k == 1400
                plot(x,mfr,'*r');
                legend('@1','@51','@101','@151','@201','@700','@1400');
            end
        end
    end
end

if n == 31
    figure(5)
    plot(x,v,'b',x,p,'r',x,T,'k',x,rho,'m',x,M,'g',x,mfr,'c');
    ylim([-0.1 3.7]);
    title(sprintf('Time step = %d',i));
    xlabel('Length of nozzle');
    ylabel('Non dimensional parameters');
    legend('Velocity','Pressure','Temperature','Density','Mach number','Mass flow rate');
    title('Conservative form - Steady state distriubution of primitive variables inside the nozzle');
    
    figure(6)
    plot(nt,rho_throat)
    hold on
    plot(nt,v_throat,'linewidth',1);
    plot(nt,p_throat,'linewidth',1);
    plot(nt,t_throat,'linewidth',1);
    plot(nt,M_throat,'linewidth',1);
    plot(nt,mfr_throat,'linewidth',1);
    xlabel('Time steps(nt)');
    ylabel('Non dimensional parameters');
    legend('Density','Velocity','Pressure','Temperature','Mach number','Mass flow rate');
    title('Conservative form - Time wise variation of primitive variables at throat i = 16');
end

mfr_c = mfr;
mfr_throat_c = mfr_throat;
end

Results

Non Conservative form

1. Mass flow rate

It can be observed that the mass flow rate stabilizes as the number of time steps are increased

2. Non dimensional parameters

The figure above shows the variation of all the calculated flow field variables over the length of the nozzle.

3. Primitive variables - Time wise variation

The primitive variables calculated in the flow field stabilize and achieve convergence at around 500 steps. It can be seen, that the values remain constant thereafter.

Conservative form

1. Mass flow rate

It can be observed that the mass flow rate stabilizes as the number of time steps are increased

2. Non dimensional parameters

The figure above shows the variation of all the calculated flow field variables over the length of the nozzle.

3. Primitive variables - Time wise variation

The primitive variables calculated in the flow field stabilize and achieve convergence at around 500 steps. It can be seen, that the values remain constant thereafter.

Comparison of mass flow rate

It can be seen, that the non conservative form takes a longer time to reach stable convergence, compared to conservative form at the throat point.

Over the length of the nozzle, the mass flow rate is constant for conservative form. There is some variation in the mass flow rate of the non conservative form, but it is very minor (order of 10^-3).

Grid independence test

The simulations are carried out with three different grid sizes - 31,62 and 93 points in order to illustrate the independence of the solution on the grid size.

The results can be seen in the images below.

Nozzle

It can be seen, that a stable result is obtained for all three grid sizes. There is some variation in the actual mass flow rate. As the size of the grid increases, the mass flow rate reduces slightly for both conservative and non conservative flows

Throat point

The mass flow rates for all three grid sizes reach the same constant value, therefore ensuring stability. The simulation takes more time steps to reach this convergence, as the grid size increases. Overall, a stable solution is reached for all three grid sizes.

Conclusion

Thus, the 1D supersonic flow over a nozzle has been simulated for both conservative and non conservative forms, and the results have been analyzed and compared.

The matlab m files have been attached below

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.