Challenge

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

Motivation

So far we have learnt some ideas on Governing equations, their forms (w/o knowing their actual means), FDM, Consistency of a Numerical scheme, Discretization (FDM), Time integration, Stability and more or less few. Now we put all of these together.

Governing equations

In Conservative form we consider control volume is staionary whereas in Non-Conservative form CV is moving. Both are mathematically same and can easily converted into another easily and excatlty. They have difference only in numerical discretization.

1D supersonic nozzel flow

The convergence(subsonic) section connected with reservoir, here mach number is less than one. At throat area, the thermodynamic properties will become critical property as Mach number equal to 1. The sonic flow at the throat means that the local velocity at this point is equal to the local speed of sound and at divergence section(supersonic) the flow expands isentropically to supersonic speed at the nozzle exit. The corresponding notations are clearly written in the figure itself.

The flow is locally subsonic in the convergence section of the nozzle, sonic at the throat and supersonic at the divergence section.

The governing continuity, momentum and energy equation for the quasi 1D steady isentropic flow can be expressed as

Non conservative form:

Conservative form:

Using Maccormack method, we can solve both of these sets of equations. In this method we use two rounds of iteration namely predictor and corrector steps which solve the premitive variables using FDS and BDS respectively, then we use arthimetic mean of both results. Following are the sets of Matlab programs with defined initial and boundary conditions as per Anderson book with separate functions for Non-conservative and conservative terms.

Main code:

clear all
close all
clc

%%Discretization
L=3;
n=31;
x=linspace(0,L,n);
dx=x(2)-x(1);
throat=(n+1)/2;
% profile of nozzel and parameters
a=1+2.2*(x-1.5).^2;

%fluid properties
gama=1.4;
C=0.5;
nt=1400;

tic
[m_Nc,m_Nc_t,M_Nc,M_Nc_t,rho_Nc,rho_Nc_t,P_Nc,P_Nc_t,T_Nc,T_Nc_t,V_Nc,V_Nc_t]=NonConservative(x,n,dx,gama,nt,a,C,throat);
t_non_conservative=toc;
fprintf('time consumed for non conservative form=%d\n',t_non_conservative);

tic
[m_c,m_c_t,M_c,M_c_t,rho_c,rho_c_t,P_c,P_c_t,T_c,T_c_t,V_c,V_c_t]=Conservative(x,n,dx,gama,nt,a,C,throat);
t_conservative=toc;
fprintf('time consumed for conservative form=%d',t_conservative);

%Grid dependence test
% % Calcualtinng primitive values at throat
terms={'Nondimensional density';'Nondimensional temperature';'Nondimensional pressure';'Mach number'};
exact_solution=[0.634;0.8333;0.528;1];
conservative_terms=[rho_c(throat);T_c(throat);P_c(throat);M_c(throat)];
non_conservative_terms= [rho_Nc(throat);T_Nc(throat);P_Nc(throat);M_Nc(throat)];
table(terms,exact_solution,conservative_terms,non_conservative_terms)

figure(3)
plot(x,m_Nc)
hold on
plot(x,m_c)
title('comparison of non dimensional mass flow rates')
legend('Non_conservative form', 'conservative form')
xlabel('x/L')
ylabel('Nondimensional mass flow rate')

figure(4)
subplot(4,1,1)
plot(x,M_Nc)
xlabel('x-axis')
ylabel('Mach number')
subplot(4,1,2)
plot(x,rho_Nc)
xlabel('x-axis')
ylabel('Density ratio')
subplot(4,1,3)
plot(x,P_Nc)
xlabel('x-axis')
ylabel('Pressure ratio')
subplot(4,1,4)
plot(x,T_Nc)
xlabel('x-axis')
ylabel('Temperature ratio')
subtitle('Solution for Non conservative form at steady state')

figure(5)
subplot(4,1,1)
plot(x,M_c)
xlabel('x-axis')
ylabel('Mach number')
subplot(4,1,2)
plot(x,rho_c)
xlabel('x-axis')
ylabel('Density ratio')
subplot(4,1,3)
plot(x,P_c)
xlabel('x-axis')
ylabel('Pressure ratio')
subplot(4,1,4)
plot(x,T_c)
xlabel('x-axis')
ylabel('Temperature ratio')
subtitle('Solution for Conservative form at steady state')

Function for Non conservative:

% Non conservative function
function[m_Nc,m_Nc_t,M_Nc,M_Nc_t,rho_Nc,rho_Nc_t,P_Nc,P_Nc_t,T_Nc,T_Nc_t,V_Nc,V_Nc_t]=NonConservative(x,n,dx,gama,nt,a,C,throat);
% initial condition along x
rho_Nc=1-0.3146.*x;
T_Nc=1-0.2314.*x;
V_Nc=(0.1+1.09*x).*T_Nc.^0.5;
throat=16;
%time step

% dt(i)=C.*(dx./((T(i)).^0.5+V(i)));
Dt=min(C*(dx./(T_Nc.^0.5+V_Nc)));
for k=1:1400
    % values at time t
    rho_old=rho_Nc;
    T_old=T_Nc;
    V_old=V_Nc;
    %a_old=a;
    
    % maccormack method
    for j=2:n-1
        dvdx=(V_Nc(j+1)-V_Nc(j))/dx;
        dlog_a_dx=(log(a(j+1))-log(a(j)))/dx;
        drhodx=(rho_Nc(j+1)-rho_Nc(j))/dx;
        dTdx=(T_Nc(j+1)-T_Nc(j))/dx;
        
        % continity equation
        drhodt_p(j)=-(rho_Nc(j)*dvdx)-(rho_Nc(j)*V_Nc(j)*dlog_a_dx)-(V_Nc(j)*drhodx);
        % Mommentum equation
        dvdt_p(j)=-V_Nc(j)*dvdx-(1/gama)*(dTdx+(T_Nc(j)/rho_Nc(j))*(drhodx));
        % Energy equation
        dTdt_p(j)=-V_Nc(j)*dTdx-(gama-1)*T_Nc(j)*(dvdx+(V_Nc(j)*dlog_a_dx));
        
        % solution update at time step 't+dt'
        rho_Nc(j)=rho_Nc(j)+drhodt_p(j)*Dt;
        V_Nc(j)=V_Nc(j)+dvdt_p(j)*Dt;
        T_Nc(j)=T_Nc(j)+dTdt_p(j)*Dt;
    end
    
    % corrector step
    for j=2:n-1
        dvdx=(V_Nc(j)-V_Nc(j-1))/dx;
        dlog_a_dx=(log(a(j))-log(a(j-1)))/dx;
        drhodx=(rho_Nc(j)-rho_Nc(j-1))/dx;
        dTdx=(T_Nc(j)-T_Nc(j-1))/dx;
        
        % continity equation
        drhodt_c(j)=-(rho_Nc(j)*dvdx)-(rho_Nc(j)*V_Nc(j)*dlog_a_dx)-(V_Nc(j)*drhodx);
        % Mommentum equation
        dvdt_c(j)=-V_Nc(j)*dvdx-(1/gama)*(dTdx+(T_Nc(j)/rho_Nc(j))*(drhodx));
        % Energy equation
        dTdt_c(j)=-V_Nc(j)*dTdx-(gama-1)*T_Nc(j)*(dvdx+(V_Nc(j)*dlog_a_dx));
        
    end
    % Arithmatic mean of pde
    drhodt_avg=0.5*(drhodt_p+drhodt_c);
    dvdt_avg=0.5*(dvdt_p+dvdt_c);
    dTdt_avg=0.5*(dTdt_p+dTdt_c);
    
    % Final update solution
    for i=2:n-1
        rho_Nc(i)=rho_old(i)+drhodt_avg(i)*Dt;
        V_Nc(i)=V_old(i)+dvdt_avg(i)*Dt;
        T_Nc(i)=T_old(i)+dTdt_avg(i)*Dt;
    end
    
    % BC
V_Nc(1)=2*V_Nc(2)-V_Nc(3);
V_Nc(n)=2*V_Nc(n-1)-V_Nc(n-2);
rho_Nc(n)=2*rho_Nc(n-1)-rho_Nc(n-2);
T_Nc(n)=2*T_Nc(n-1)-T_Nc(n-2);
%calculating
m_Nc=rho_Nc.*V_Nc.*a;
M_Nc=V_Nc./(T_Nc.^0.5);
P_Nc=rho_Nc.*T_Nc;

% flow parameter defining
P_Nc_t(k)=P_Nc(throat);
T_Nc_t(k)=T_Nc(throat);
V_Nc_t(k)=V_Nc(throat);
rho_Nc_t(k)=rho_Nc(throat);
m_Nc_t(k)=m_Nc(throat);
M_Nc_t(k)=M_Nc(throat);

% comparision of mass flow rates at differnt times
figure(1)
hold on
if k==50
    plot(x,m_Nc,'y','linewidth',1.5)
elseif k==100
    plot(x,m_Nc,'g','linewidth',1.5)
elseif k==200
    plot(x,m_Nc,'b','linewidth',1.5)
elseif k==700
    plot(x,m_Nc,'--','linewidth',1.5)
end
title('Variation off mass flow distribution in non-conservative form');
xlabel('non_dimensional length of the nozzle');
ylabel('mass flow rate');
grid on;
end
end

Function for conservative:

% function for conservative form
function[m_c,m_c_t,M_c,M_c_t,rho_c,rho_c_t,P_c,P_c_t,T_c,T_c_t,V_c,V_c_t]=Conservative(x,n,dx,gama,nt,a,C,throat);

for j=1:n
    if(x(j)>=0 && x(j)<=0.5)
        rho_c(j)=1;
        T_c(j)=1;
    elseif (x(j)>=0.5 && x(j)<=1.5)
        rho_c(j)=1-(0.366*(x(j)-0.5));
        T_c(j)=1-(0.167*(x(j)-0.5));
    elseif (x(j)>=1.5 && x(j)<=3.5)
        rho_c(j)=0.634-(0.3879*(x(j)-1.5));
        T_c(j)=0.833-(0.3507*(x(j)-1.5));
    end
end

V_c=0.59./(rho_c.*a);
m_c=rho_c.*a.*V_c;
u1=rho_c.*a;
u2=rho_c.*V_c.*a;
u3=u1.*((T_c/(gama-1))+(gama/2)*(V_c.^2));
% dt=0.002; %min(C.*(dx./((T.^0.5)+V))); % time step

for k=1:nt
    Dt=T_c.^0.5;
    dt=min(C*dx./(Dt+V_c));
    u1_old=u1;
    u2_old=u2;
    u3_old=u3;
    
    % flux vector
    f1=u2;
    f2_1=(u2.^2)./u1;
    f2_2=(u3-(gama/2)*f2_1);
    f2=f2_1+((gama-1)/(gama)*f2_2);
    f3_1=(u2.*u3)./u1;
    f3_2=(u2.^3)./(u1.^2);
    f3=gama*f3_1-(((gama*(gama-1))/2)*f3_2);

    % predictor step
    for i=2:n-1
        J2_p(i)=((1/gama)*(rho_c(i)*T_c(i))*(a(i+1)-a(i)))/dx;
        du1dt_p(i)=-(f1(i+1)-f1(i))/dx;
        du2dt_p(i)=-((f2(i+1)-f2(i))/dx)+J2_p(i);
        du3dt_p(i)=-(f3(i+1)-f3(i))/dx;
        
        %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
    
    % updating values
    rho_c=u1./a;
    V_c=u2./u1;
    T_c=(gama-1)*((u3./u1)-((gama/2)*(V_c.^2)));
% 
    f1=u2;
    f2_1=(u2.^2)./u1;
    f2_2=(u3-(gama/2)*f2_1);
    f2=f2_1+((gama-1)/(gama)*f2_2);
    f3_1=(u2.*u3)./u1;
    f3_2=(u2.^3)./(u1.^2);
    f3=gama*f3_1-(((gama*(gama-1))/2)*f3_2);

    
    % corrector step
    for i=2:n-1
        
        J2_c(i)=((1/gama)*(rho_c(i)*T_c(i))*(a(i)-a(i-1)))/dx;
        
        du1dt_c(i)=-(f1(i)-f1(i-1))/dx;
        du2dt_c(i)=(-(f2(i)-f2(i-1))/dx)+J2_c(i);
        du3dt_c(i)=-(f3(i)-f3(i-1))/dx;
    end
    
    % average values
    du1dt_avg=0.5*(du1dt_p+du1dt_c);
    du2dt_avg=0.5*(du2dt_p+du2dt_c);
    du3dt_avg=0.5*(du3dt_p+du3dt_c);
    
    for z=2:n-1
        u1(z)=u1_old(z) + du1dt_avg(z)*dt ;
        u2(z)=u2_old(z) + du2dt_avg(z)*dt ; 
        u3(z)=u3_old(z) + du3dt_avg(z)*dt ;
    end
    
    % inlet boundary conditions
    u1(1)=rho_c(1)*a(1);
    u2(1)=(2*u2(2))-u2(3);
    u3(1)=u1(1)*((T_c(1)/(gama-1))+(gama/2)*(V_c(1)^2));
    
    % outlet boundary conditions
    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);
    
    rho_c=u1./a;
    V_c=u2./u1;
    T_c=(gama-1)*((u3./u1)-(gama/2)*(V_c.^2));
    
    M_c=V_c./(T_c.^0.5);
    m_c=u2;
    P_c=rho_c.*T_c;
    
    rho_c_t(k)=rho_c(throat);
    M_c_t(k)=M_c(throat);
    P_c_t(k)=P_c(throat);
    T_c_t(k)=T_c(throat);
    V_c_t(k)=V_c(throat);
    m_c_t(k)=m_c(throat);
    
    figure(2)
    hold on
    if k==0
        plot(x,m_c,'--','linewidth',1.5)
    elseif k==100
        plot(x,m_c,'r','linewidth',1.5)
    elseif k==200
        plot(x,m_c,'k','linewidth',1.5)
    elseif k==300
        plot(x,m_c,'c','linewidth',1.5)
    elseif k==700
        plot(x,m_c,'b','linewidth',1.5)
        
    end
    title('Variation of mass flow distribution in conservative form');
    xlabel('non-dimensional length of the nozzle');
    ylabel('mass flow rate');
    grid on;
end
end

Plot:

In the above two plots, Variation of mass flow distribution through nozzle at different times duting the time marching process for Non-conservative and conservative form of governing equations.

Let us compare the steady-state vatiations of mass flow obtained with the nonconservative and conservative forms of the governing equations (both after 1400 time steps-well beyond the time required to converge to the steady state). This comparision shows that the scale of the ordinate for mass flow is greatly magnified. Hence we see that the steady state mass flow distribution predicted by the conservation form of the equations is much more satisfactory than that obtained from the nonconservation form, which is because

• The conservation form gives a distribution that is much closer to being a constant. In contrast, the nonconservative results have 9on the magnified scale) a sizable variation, with some spurious oscillations at both inflow and outflow boundaries. Of course, on the practical basis, these variations are not apparent and mass flow essentially appears to be constant.

• The steady state mass flow results obtained with the conservative form are, on the whole, much closer to the exact analytical solution of p'A'V' = 0.579

Figure shows a detailed comparison of the steady state mass flow variation(on a magnified scale) obtained with the nonconservative and conservative forms to the governing flow equation.

Solution for non conservative of steady state

solution for consetrvative form at steady state

Grid Dependence test:

Note that the noncoservative form results are distinctly closer to the exact values. However, by doubling the number of grid points, the steady state numericals results in conservative form of governing equations are slightly closer to the exact analytical values (but still not as close as the nonconservative form with half as many grid points). For this projects, we have grid indepence with 31 grid points.

Results from the project

For the given flow problem, we cannot establish a clear superiority of the conservation form of the governing equations over the non-conservation from. However, we can make following observations:

1. The conservation form yeilds a better mass flow distribution. The conservation from simply does a better job of conserving mass.

2. The non-consevartive form leads to smallar residuals. The amount by which the computational time is slighly less, however it merely depends on the numerical algorithms in the first place.

3. There is no clear indication that which form yeilds better accuracy, though nonconservative form seems to produce slightly more accurate results for the primitive variables, and the conservative form seems to produce slightly more accurate results for flux variables. This results in either case are certainly satisfacotry.

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.