Challenge

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

Aim:

To simulate 1D Super-sonic nozzle flow using the MacCormack Method with both the conservation and non-conservation forms of the governing equations

Problem Description:

The flow in a nozzle is to be simulated and get the values of primitives which are Velocity, Pressure, Temperature, Density, Mach number and Mass flow rate.

Formulation:

  • For Non-Dimensional variables:

Main Code:

close all
clear all
clc
%% Initalization
l = 3; % length of the nozzle
n = [31 61]; % Number of grid points
c = 0.5; % CFL number
nt = 1:1400; % Time step

for i = 1:length(n)
    %% Solving using Conservative and Non-Conservative form
    x=linspace(0,l,n(i));
    [m_non_con,m_throat_non_con]=non_conservative(l,n(i),nt,c);
    [m_con,m_throat_con]=conservative(l,n(i),nt,c);
    
    figure(7)
    subplot(2,1,1)
    plot(x,m_con,x,m_non_con)
    xlabel('Length of nozzle')
    ylabel('Mass flow rate')
    legend('Conservative form','Non-Conservative form')
    title('Mass flow rate in the nozzle')
    
    subplot (2,1,2)
    plot(nt,m_throat_con,nt,m_throat_non_con)
    xlabel('Time steps')
    ylabel('Mass flow rate')
    legend('Conservative form','Non-Conservative form')
    title('Mass flow rate at throat')
    %% Grid independency test
    figure(8)
    subplot (2,1,1)
    plot(x,m_con)
    hold on
    xlabel('Length of nozzle')
    ylabel('Mass flow rate')
    legend('With 31 nodes','With 61 nodes')
    title('Grid independence test along the nozzle for conservative')
    subplot (2,1,2)
    plot(x,m_non_con)
    hold on
    xlabel('Length of nozzle')
    ylabel('Mass flow rate')
    legend('With 31 nodes','With 61 nodes')
    title('Grid independence test along the nozzle for non-conservative')
    
    figure(9)
    subplot (2,1,1)
    plot(nt,m_throat_con)
    hold on
    xlabel('Time steps')
    ylabel('Mass flow rate')
    legend('With 31 nodes','With 61 nodes')
    title('Grid independence test at throat point for conservative')
    subplot (2,1,2)
    plot(nt,m_throat_non_con)
    hold on
    xlabel('Time steps')
    ylabel('Mass flow rate')
    legend('With 31 nodes','With 61 nodes')
    title('Grid independence test at throat point for non-conservative')
end

Non-Conservative form:

Formulation:

Conditions:

Function Code:

function [m_non_con,m_throat_non_con]=non_conservative(l,n,nt,c)

%% Creating grid
x=linspace(0,l,n);
dx=x(2)-x(1);
% initial conditions rho, a, v, T, mfr, M, p
%% Initialization
a= 1+2.2*(x-1.5).^2;     % Area of nozzle
throat = find(a==1);     % To find node where area is unity
g = 1.4;                 % Gamma value
rho = 1-0.3146*x;
t= 1-0.2314*x;
v=(0.1+1.09*x).*t.^0.5;
a= 1+2.2*(x-1.5).^2;
M= v./(t.^0.5); % Mach number
m = rho.*a.*v; % Mass flow rate
p=rho.*t;
% Finding dt value
for z=1:31
    u=(t(z))^(1/2);
    dt(z) = c*dx/(u + v(z));
end
dt=min(dt);

for i = 1:length(nt)
    % To store initial values
    rho_old = rho;
    T_old = t;
    v_old = v;
    for j=2:n-1
        %% Predictor step
        drho_dx = (rho(j+1)-rho(j))/dx;
        dv_dx = (v(j+1)-v(j))/dx;
        dT_dx = (t(j+1)-t(j))/dx;
        da_dx = (log(a(j+1))-log(a(j)))/dx;
        drho_dt_p(j) = -rho(j)*dv_dx - rho(j)*v(j)*da_dx - v(j)*drho_dx;
        dv_dt_p(j) = -v(j)*dv_dx - (1/g)*(dT_dx + (t(j)/rho(j))*drho_dx);
        dT_dt_p(j) = -v(j)*dT_dx - (g-1)*t(j)*(dv_dx + v(j)*da_dx);
        %updating primitives
        v(j) = v_old(j) + dv_dt_p(j)*dt;
        rho(j) = rho_old(j) + drho_dt_p(j)*dt;
        t(j) = T_old(j) + dT_dt_p(j)*dt;
        %% Corrector step
        drho_dx = (rho(j)-rho(j-1))/dx;
        dv_dx = (v(j)-v(j-1))/dx;
        dT_dx = (t(j)-t(j-1))/dx;
        da_dx = (log(a(j))-log(a(j-1)))/dx;
        drho_dt_c(j) = -rho(j)*dv_dx - rho(j)*v(j)*da_dx - v(j)*drho_dx;
        dv_dt_c(j) = -v(j)*dv_dx - (1/g)*(dT_dx + (t(j)/rho(j))*drho_dx);
        dT_dt_c(j) = -v(j)*dT_dx - (g-1)*t(j)*(dv_dx + v(j)*da_dx);
    end
    %% Caclulating avg gradient
    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);
    
    for k = 2:n-1
        rho(k) = rho_old(k) + drho_dt_avg(k)*dt;
        v(k) = v_old(k) + dv_dt_avg(k)*dt;
        t(k) = T_old(k) + dT_dt_avg(k)*dt;
    end
    %% Boundary conditions
    v(1) = 2*v(2)-v(3); % entry
    v(n) = 2*v(n-1)-v(n-2); %exit
    rho(n) = 2*rho(n-1)-rho(n-2);
    t(n) = 2*t(n-1)-t(n-2);
    
    %% Getting Final Primitives
    p = rho.*t;
    M= v./t.^0.5;
    error(k) =  abs(v(k)-v(k-1));
    m= rho.*a.*v;
    
    %% To find values at throat point
    m_thr(i)=m(throat);
    t_thr(i) = t(throat);
    rho_thr(i) = rho(throat);
    M_thr(i) = M(throat);
    v_thr(i) = v(throat);
    p_thr(i) = p(throat);
    error_thr(i)=error(throat);
    
    if n==31
        for h=[1:50:201 700]
            if h==i
                figure(1)
                plot(x,m)
                hold on
                title ('Variation of Mass flow rate distribution inside the nozzle at different time steps for non-conservative')
                xlabel('Length of nozzle')
                ylabel('Mass flow rate')
            elseif i==1400
                plot(x,m)
                legend('1','51','101','151','201','700','1400')
            end
        end
    end
    
end
if n==31
    figure(2)
    plot(x,v,x,p,x,t,x,rho,x,M,x,m)
    xlabel('Length of nozzle')
    ylabel('Non dimensional parameters')
    legend('Velocity','Pressure','Temperature','Density','Mach number','Mass flow rate')
    title('Steady-state distribution of primitive variables inside the nozzle for non conservative')
    
    figure (3)
    hold on
    plot(nt,rho_thr)
    plot(nt,v_thr)
    plot(nt,p_thr)
    plot(nt,t_thr)
    plot(nt,M_thr)
    plot(nt,m_thr)
    xlabel('Time steps')
    ylabel('Non dimensional parameters')
    legend('Density','Velocity','Pressure','Temperature','Mach number','Mass flow rate')
    title('Time-wise variation of the primitive variables at throat for non conservative')
end
m_non_con=m;
m_throat_non_con=m_thr;
end

Conservative form:

Formulation:

Conditions:

Function Code:

function [m_con,m_throat_con]=conservative(l,n,nt,c)

%% Creating grid
x=linspace(0,l,n);
dx=x(2)-x(1);
%% Initialization
a= 1+2.2*(x-1.5).^2;     % Area of nozzle
throat = find(a==1);     % To find node where area is unity
g = 1.4;                 % Gamma value
for k=1:length(x)
    if (x(k)<=0.5)
        rho(k) = 1;
        t(k) = 1;
    elseif (x(k)>0.5) && (x(k)<=1.5)
        rho(k) = 1-0.366*(x(k)-0.5);
        t(k)= 1-0.167*(x(k)-0.5);
    elseif (x(k)>1.5) && (x(k)<=3.5)
        rho(k) = 0.634-0.3879*(x(k)-1.5);
        t(k)= 0.833-0.3507*(x(k)-1.5);
    end
end

%% Source terms
u1 = rho.*a;
u2 = 0.59*ones(1,n);
v=u2./u1;
u3 = u1.*((t./(g-1))+(g/2).*v.^2);

M= v./(t.^0.5);  % Mach number
m = rho.*a.*v;   % Mass flow rate
p=rho.*t;        % Pressure
% Finding dt value
for z=1:31
    u=(t(z))^(1/2);
    dt(z) = c*dx/(u + v(z));
end
dt=min(dt);

for i = 1:length(nt)
    % To store initial values
    u1_old = u1;
    u2_old = u2;
    u3_old = u3;
    
    for j=2:n-1
        
        f1 = u2;
        f2 = ((u2.^2)./u1)+((g-1)/g)*(u3-((g/2)*(u2.^2)./u1));
        f3 = ((g.*u2.*u3)./u1) - ((g*(g-1)/2)*(u2.^3)./(u1.^2));
        
        j1 = (1/g)*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;
        
        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;
        
        rho=u1./a;
        t=(g-1).*(u3./u1-(g/2).*(u2./u1).^2);
        
        f1=u2;
        f2=u2.^2./u1+((g-1)/g).*(u3-(g/2)*u2.^2./u1);
        f3=g.*u2.*u3./u1-0.5*g*(g-1).*u2.^3./u1.^2;
        
        j2 = (1/g)*(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
    %% Caclulating avg gradient
    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);
    
    for k = 2:n-1
        u1(k) = u1_old(k) + du1_dt_avg(k)*dt;
        u2(k) = u2_old(k) + du2_dt_avg(k)*dt;
        u3(k) = u3_old(k) + du3_dt_avg(k)*dt;
    end
    
    u1(1) = a(1);
    u2(1) = 2*u2(2)-u2(3);
    u3(1) = u1(1)*(t(1)/(g-1) + (g*(u2(1)/u1(1))^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);
    
    %% Getting Final Primitives
    rho = u1./a;
    v = u2./u1;
    t=(g-1).*(u3./u1-(g/2).*(u2./u1).^2);
    p = rho.*t;
    M= v./t.^0.5;
    error(k) =  abs(v(k)-v(k-1));
    m= u2;
    %% To find values at throat point
    m_throat(i)=m(throat);
    t_throat(i) = t(throat);
    rho_throat(i) = rho(throat);
    M_throat(i) = M(throat);
    v_throat(i) = v(throat);
    p_throat(i) = p(throat);
    error_throat(i)=error(throat);
    
    %% Ploting only for 31 nodes configuration
    if n==31 % This can be changed to get plots at different no of nodes
        for k=[1:50:201 700]
            if k==i
                figure(4)
                plot(x,m)
                hold on
                title ('Variation of Mass flow rate distribution inside the nozzle at different time steps for conservative')
                xlabel('Length of nozzle')
                ylabel('Mass flow rate')
            elseif i==1400
                plot(x,m)
                legend('1','51','101','151','201','700','1400')
            end
        end
    end
    
end
if n==31
    figure(5)
    plot(x,v,x,p,x,t,x,rho,x,M,x,m)
    xlabel('Length of nozzle')
    ylabel('Non dimensional parameters')
    legend('Velocity','Pressure','Temperature','Density','Mach number','Mass flow rate')
    title('Steady-state distribution of primitive variables inside the nozzle for conservative')
    
    figure (6)
    plot(nt,rho_throat)
    hold on
    plot(nt,v_throat)
    plot(nt,p_throat)
    plot(nt,t_throat)
    plot(nt,M_throat)
    plot(nt,m_throat)
    xlabel('Time steps')
    ylabel('Non dimensional parameters')
    legend('Density','Velocity','Pressure','Temperature','Mach number','Mass flow rate')
    title('Time-wise variation of the primitive variables at throat for conservative')
end
m_con=m;
m_throat_con=m_throat;

end

Screenshots:

Results:

Non-Conservative form:

Conservative form:

Comparison of Normalized mass flow rate distributions of both forms:

Grid Independence Test:

Conclusion:

  • All the plots requested are obtained.
  • There is a difference between solutions obtained with conservative and non-conservative forms.
  • Also, grid size must also be taking into consideration as there is a slight difference in the solution whereas it also affects the computing time and resources.
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.