Challenge

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

Analysis of quasi-one-dimensional flow through C-D nozzle using MacCormack method

Here we are going to simulate the isentropic flow through a quasi 1D subsonic-supersonic nozzle. We will be deriving both the conservation and non-conservation forms of the governing equations and solving them using the MacCormack's technique. Then we will define the steady-state flow-field. Also, we will compare the results from both the methods and study the difference between them. Computational Fluid Mechanics by Anderson is used for the reference.

The above-given diagram shows a typical C-D Nozzle through which a supersonic flow can occur. The inlet of the nozzle is having a very large area and is connected to a reservoir having a very large size. In the tank, the fluid velocity is very very small since the mass flow rate is fixed. This is referred to as stagnation condition. When fluid starts moving through the nozzle since the flow is subsonic and is flowing through a converging section its velocity will increase. The throat is the section where there it has a minimum cross-sectional area. If the backpressure allows the speed of flow will become equal to the speed of sound at this section. Since the further part is a diverging section e may get a supersonic outflow depending upon the value of exit pressure. Here we are assuming that the values are constant radially and keep varying axially only. such a flow can be termed as quasi 1D flow.

Non-dimensionalization

For the convenience of study and analysis, there is a general practice of non-dimensionalization. For that, we will be dividing all the variable with reservoir values and area by throat area. So we can define non-dimensionalized parameters as follows.

`x' = x/L`

`rho' = rho/rho^o`

`T' = T/T^o`

`V' = V/a_o`

`t'= t/(L/a_o)`

`P=P/P^0`

`A'= A/A^"*"`

where,

L - Length of the Nozzle

`T^o , rho^o , P^o` - temperature, density and Pressure at the reservoir respectively.

`a_o = sqrt(gamma R T_o)` and

`A^"*"` - throat area.

now let's go to the governing equations.

MacCormack method

MacCormack method is a widely used discretization scheme for the numerical solution of hyperbolic partial differential equations. The MacCormack method is a variation of the two-step Lax–Wendroff scheme but is much simpler in the application. It's second-order accurate in both space and time. to employ second-order accuracy in time a predictor-corrector strategy is employed and their average is used to calculate the actual derivative. To illustrate the algorithm, consider the following first-order hyperbolic equation.

`frac(delu)(delt) + alpha*frac(delu)(delx) = 0`

First, we will be using a predictor formula to find out the value at the next time step. i.e.

`u_i^bar(n+1) = u_i^(n) - alpha* (Deltat)/(Deltax) *(u_(i+1)^(n) - u_i^(n))`

In the corrector step, the predicted value at the new time step is corrected according to the equation

`u_i^bar(n+1) = u_i^(n+(1)/2) - alpha* (Deltat)/(Deltax) *(u_(i)^bar(n+1) - u_(i-1)^bar(n+1))`

Replacing the `u_i^(n+(1)/2)` term by the temporal average will give

`u_i^(n+(1)/2) = (u_i^(n) + u_i^bar(n+1))/2`

to obtain the corrector step as

`u_i^(n+1) = (u_i^(n) + u_i^bar(n+1))/2 - alpha*(Deltat)/(2Deltax)*(u_i^bar(n+1) - u_(i-1)^bar(n+1))`

now let's go to the governing equations.

Governing Equations.

Conservation of mass momentum energy principle will give 3 Governing equations. Generally, a GE may be of two types, Conservative or non - conservative. here we will be solving the problem by using both the methods.

a) Non - Conservative form

Continuity equation

`A (del rho)/(del t) + V (del(rho A))/(del x) = -rho A (del V)/(del x)`


Momentum equation

`rho (del V)/(del t) + rho V(del V)/(del x) = -(del p)/(del x)`

Energy equation

`rho (del e)/(del t) + rho V(del e)/(del x) = - p(del V)/(del x) - pV(del(ln A))/(del x)`

up on non dimensiolization it will become as follows.

Continuity equation (non dimensional)

`(del rho')/(del t') = -rho' (del V')/(del x') - rho' V' (del (ln A'))/(del x') - V'(del rho')/(del x')`


Momentum equation (non dimensional)

`(del V')/(del t') = -V'(del V')/(del x') - 1/gamma((del T')/(del x') + (T')/(rho') (del rho')/(del x'))`

Energy equation (non dimensional)

`(del T')/(del t') = -V'(del T')/(del x') - (gamma-1)T'[(del V')/(del x') + V' (del(ln A'))/(del x')]`

Now we have to form the MacCromck Strategy.

Predictor Step

Find out time derivative at all the pints.

`((del rho)/(del t))_i^t = -rho_i^t[(V_(i+1)^t - V_i^t)/(Delta x)] - rho_i^t V_i^t[(ln(A_(i+1)) - ln(A_i))/(Delta x)] - V_i^t[(rho_(i+1)^t - rho_i^t)/(Delta x)]`

`((del V)/(del t))_i^t = -V_i^t[(V_(i+1)^t - V_i^t)/(Delta x)] - 1/gamma[(T_(i+1)^t - T_i^t)/(Delta x) + T_i^t/rho_i^t( (rho_(i+1)^t - rho_i^t)/(Delta x))]`

`((del T)/(del x))_i^t = -V_i^t[(T_(i+1)^t - T_i^t)/(Delta x)] - (gamma-1)T_i^t [(V_(i+1)^t-V_i^t)/(Delta x)+ V_i^t((ln(A_(i+1)) - ln(A_i))/(Delta x))]`

Compute Predicted values

`(bar rho)_i^(t+Delta t) = rho_i^t + ((del rho)/(del t))_i^t Delta t`

`(bar V)_i^(t+Delta t) = V_i^t + ((del V)/(del t))_i^t Delta t`

`(bar T)_i^(t+Delta t) = T_i^t + ((del T)/(del t))_i^t Delta t`

Corrector Step

Find time derivative values at time (t+dt) with the predicted values.

`(bar((del rho)/(del t)))_i^(t+Delta t) = -(bar rho)_i^(t+Delta t)[((bar V)_i^(t+ Delta t) - (bar V)_(i-1)^(t+Delta t))/(Delta x)] - (bar rho)_i^(t+Delta t)(bar V)_i^(t+Delta t)[(ln(A_i) - ln(A_(i-1)))/(Delta x)] - (bar V)_i^(t+Delta t)[((bar rho)_i^(t+Delta t) - (bar rho)_(i-1)^(t+Delta t))/(Delta x)]`

`(bar((del V)/(del t)))_i^(t+ Delta t) = -(bar V)_i^(t+Delta t)[((bar V)_i^(t+Delta t) - (bar V)_(i-1)^(t+Delta t))/(Delta x)] - 1/gamma[((bar T)_i^(t+Delta t) - (bar T)_(i-1)^(t+Delta t))/(Delta x) + (bar T)_i^(t+Delta t)/(bar rho)_i^(t+Delta t)( ((bar rho)_i^(t+Delta t) - (bar rho)_(i-1)^(t+Delta t))/(Delta x))]`

`(bar((del T)/(del x)))_i^(t+Delta t) = -(bar V)_i^(t+Delta t)[((bar T)_i^(t+Delta t) - (bar T)_(i-1)^(t+Delta t))/(Delta x)] - (gamma-1)T_i^(t+Delta t) [((bar V)_i^(t+Delta t)- (bar V)_(i-1)^(t+Delta t))/(Delta x)+ (bar V)_i^(t+Delta t)((ln(A_i) - ln(A_(i-1)))/(Delta x))]`

Find the average of time derivative values obtained from forward and backward difference methods.

`((del rho)/(del t))_(av) = 1/2[((del rho)/(del t))_i^t + (bar((del rho)/(del t)))_i^(t+Delta t)]`

`((del V)/(del t))_(av) = 1/2[((del V)/(del t))_i^t + (bar((del V)/(del t)))_i^(t+Delta t)]`

`((del T)/(del t))_(av) = 1/2[((del T)/(del t))_i^t + (bar((del T)/(del t)))_i^(t+Delta t)]`

Calculate the corrected values using the average value of time derivatives.

`rho_i^(t+Delta t) = rho_i^t + ((del rho)/(del t))_(av) Delta t`

`V_i^(t+Delta t) = V_i^t + ((del V)/(del t))_(av) Delta t`

`T_i^(t+Delta t) = T_i^t + ((del T)/(del t))_(av) Delta t`

`p_i^(t+Delta t) = rho_i^(t+Delta t) .T_i^(t+Delta t)`

Setting up

In Andersion Textbook shape of the nozzle is given by the following equation,

`A = 1 + 2.22*(x - 1.5)^2 0<= x <=3`

Initial Conditions are specified as

`rho = 1 - 0.3146 x`

`T = 1 - 0.2314 x`

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

Given Boundary conditions are

Inlet

`V(1) = 2*V(2) - V(3)`

Outlet

`rho(n) = 2*rho(n-1) - rho(n-1)`
`V(n) = 2*V(n-1) - V(n-2)`
`T(n) = 2*T(n-1) - T(n-2)`

These things are used to code the Program.

b) Conservative form

For the quasi 1D subsonic-supersonic isentropic flow nozzle, the conservation form of the governing equations can be expressed as given below.

Continuity equation

`(del(rho A))/(del t) + (del(rho A V))/(del x) = 0`

Momentum equation

`(del(rho A V))/(del t) + (del(rho A V^2))/(del x) = -A (del p)/(del x)`

Energy equation

`(del[rho (e + V^2/2) A])/(del t) + (del[rho (e + V^2/2) VA])/(del x) = - (del(p A V))/(del x)`

Expressing the above equations in the dimensionless form

Continuity equation

`(del(rho' A'))/(del t') + (del(rho' A' V'))/(del x') = 0`

Momentum equation

`(del(rho' A' V'))/(del t') + (del[rho' A' V'^2 + (1/gamma)p'A'])/(del x') = 1/gamma p' (del A')/(del x')`

Energy equation

`(del T')/(del t') = -V'(del T')/(del x') - (gamma-1)T'[(del V')/(del x') + V' (del(ln A'))/(del x')]`

For the sake of simplicity in solving we can take U as solution vector, F as flux Vector and J as Source vector. then these equations can be represented as

`(del U_1)/(del t') = -(del F_1)/(del x')`
`(del U_2)/(del t') = J2 - (del F_2)/(del x')`
`(del U_3)/(del t') = -(del F_3)/(del x')`

where

`U_1 = rho' A'`
`U_2 = rho' A' V'`
`U_3 = rho'((e')/(gamma-1)+gamma/2 V'^2)A'`
`F_1 = rho' A' V'`
`F_2 = rho' A' V'^2 + 1/gamma p'A'`
`F_3 = rho'((e')/(gamma-1) + gamma/2 V'^2)V' A' + p' A' V'`
`J_2 = 1/gamma p' (del A')`

While writing the code, we'll solve for the solution vectors and then consecutively calculate the primitive variables using the following relations.

`rho' = (U')/(A')`

`V' = U_2/U_1`

`T' = e' = (gamma-1)(U_3/U_1-gamma/2 V'^2)`

`p' = rho' T'`

W have to solve the solution vectors.flux terms and source terms must also be expressed in terms of U1, U2 and U3 to obtain the pure form of the flux terms.

`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_2 U_3)/U_1 - (gamma(gamma-1))/2 U_2^3/U_1^2`

`J_2 = (gamma-1)/gamma(U_3 - gamma/2 U_2^2/U_1)(del(ln A'))/(del x')`

now we have to apply the MacCromack Method here.

Predictor step

Calculate timederivative of quantities.

`((del U_1)/(del t'))_i^t = -(F_(1(i+1))^t - F_(1(i))^t)/(Delta x')`

`((del U_2)/(del t'))_i^t = (J_(2(i+1))^t-J_(2(i))^t)/(Delta x') - (F_(2(i+1))^t - F_(2(i))^t)/(Delta x')`

`((del U_3)/(del t'))_i^t = -(F_(3(i+1))^t - F_(3(i))^t)/(Delta x')`

Compute Predicted values

`bar(U)_(1(i))^(t+Delta t) = ((del U_1)/(del t'))_i^t .Delta t'`

`bar(U)_(2(i))^(t+Delta t) = ((del U_2)/(del t'))_i^t .Delta t'`

`bar(U)_(3(i))^(t+Delta t) = ((del U_3)/(del t'))_i^t .Delta t'`

Corrector Step

Find time derivative values at time (t+dt) with the predicted values.

`(bar(del U_1)/(del t'))_i^(t+Delta t) = -(bar(F)_(1(i))^(t+Delta t) - bar(F)_(1(i-1))^(t+Delta t))/(Delta x')`

`(bar(del U_2)/(del t'))_i^(t+Delta t) = (bar(J)_(2(i))^(t+Delta t)-bar(J)_(2(i-1))^(t+Delta t))/(Delta x') - (bar(F)_(2(i))^(t+Delta t) - bar(F)_(2(i-1))^(t+Delta t))/(Delta x')`

`(bar(del U_3)/(del t'))_i^(t+Delta t) = -(bar(F)_(3(i))^(t+Delta t) - bar(F)_(3(i-1))^(t+Delta t))/(Delta x')`

Find the average of time derivative values obtained from forward and backward difference methods.

`((del U_1)/(del t'))_(av)=1/2[((del U_1)/(del t'))_i^t+(bar(del U_1)/(del t'))_i^(t+Delta t)]`

`((del U_2)/(del t'))_(av)=1/2[((del U_2)/(del t'))_i^t+(bar(del U_2)/(del t'))_i^(t+Delta t)]`

`((del U_3)/(del t'))_(av)=1/2[((del U_3)/(del t'))_i^t+(bar(del U_3)/(del t'))_i^(t+Delta t)]`

Calculate the corrected values using the average value of time derivatives.

`U_(1(i))^(t+Delta t) = ((del U_1)/(del t'))_(av) .Delta t'`

`U_(2(i))^(t+Delta t) = ((del U_2)/(del t'))_(av).Delta t'`

`U_(3(i))^(t+Delta t) = ((del U_3)/(del t'))_(av).Delta t'`

Setting up

In Andersion Textbook shape of the nozzle is given by the following equation,

`A = 1 + 2.22*(x - 1.5)^2 0<= x <=3`

The conservation form is much sensitive to initial conditions so, we will be applying the following initial condition.

`0<=x'<=0.5 {(rho',=,1),(T',=,1):}`

`0.5<=x'<=1.5 {(rho',=,1-0.366(x'-0.5)),(T',=,1-0.167(x'-0.5)):}`

`1.5<=x'<=3 {(rho',=,0.634-0.3879(x'-1.5)),(T',=,0.833-0.3507(x'-1.5)):}`

The variation of Velocity for initial conditions can be introduced by mass flow (U2) condition. If we are choosing U2 = 0.59 for initial condition, then


`V' = U_2/(rho' A')`


The same initial conditions should be be applied to U1, U2 and U3. for that following relations can be used.

`U_1 = rho' A'`

`U_2 = rho' A' V' = 0.59`

`U_3 = rho'((e')/(gamma-1)+gamma/2 V'^2)A'`

Given Boundary conditions are

Inlet

`U_1(1) = rho'(1) *A'(1)`

`U_2(1) = 2 U_2(2) - U_2(3)`

`V'(1) = (U_2(1))/(rho'(1)*A'(1))`

`U_3(1) = U_1(1)((T'(1))/(gamma-1) + gamma/2 V'(1)^2)`

Outlet

`U1(1) = 2*U1(n-1) - U1(n-2)`

`U2(1) = 2*U2(n-1) - U2(n-2)`

`U3(1) = 2*U3(n-1) - U3(n-2)`

These things are used to code the Program.

MATLAB Code

clear all
close all
clc

% Inputs
n = 31;
L = 3;
x = linspace(0, L, n);
dx = x(2) - x(1);
nt =1400;
% Specific Heat
gamma = 1.4;

% Courant Number
C = 0.5;

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

% Throat Index
n_throat = find(A == min(A));

for solver = 1:2
    % Non - Conservative Solver

if solver == 1

    % Calculate Initial Profile

    rho = 1 - 0.3146*x;
    T = 1 - 0.2314*x;
    v = (0.1 + 1.09*x) .* T.^0.5;

    % Non - Conservative Solver Function
    [rho_nc, v_nc, T_nc, P_nc, M_nc, mass_flow_nc,dtnc,rho_tnc,p_tnc, v_tnc, T_throatnc,M_tnc] = non_conservative_function_MacCormack(n,x,dx, gamma, A, rho, v, T, C,nt,n_throat);
end


% Conservative Solver

if solver == 2

    % Initial Profiles
    % Density & Temperature

        for k = 1: n

                if x(k) >= 0 && 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

                        rho(k) = 0.634 - 0.3879 * (x(k) - 1.5);
                        T(k) = 0.833 - 0.3507 * (x(k) - 1.5);
                end
        end

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

    % Conservative Solver Function
    [rho_c, v_c, T_c, P_c, M_c, mass_flow_c,dtc,rho_tcf,p_tcf, v_tcf, T_throatcf,M_tcf] = conservative_function_MacCormack(n,x, dx,gamma, A, rho, v, T, C,nt,n_throat);
   
end
end

%%
%Plotting Non dimensionalized primitive variables Non conservative
figure(3)
opengl software
plot(x,rho_nc,'m', 'linewidth', 1.5)
grid minor
hold on
plot(x,v_nc,'r', 'linewidth', 1.5)
hold on
plot(x,T_nc,'k', 'linewidth', 1.5)
hold on
plot(x,P_nc,'c', 'linewidth', 1.5)
title('Steady state distribution of primitive variables - non conservative form')
legend("(rho/rho_0)","(v/v_0)","(T/T0)","(P/P_0)",'Location','Best')
xlabel ('X')
ylabel('Non - dimensional primitive variable')
%%
figure(4)
subplot(2,2,1)
nozGrid(x,A,v_nc);
title(sprintf("Variation of non dimensional velocity along the axis at steady state \n non - conservative form"))

subplot(2,2,2)
nozGrid(x,A,rho_nc);
title(sprintf("Variation of non dimensional density along the axis at steady state \n non - conservative form"))

subplot(2,2,3)
nozGrid(x,A,P_nc);
title(sprintf("Variation of non dimensional Pressure along the axis at steady state \n non - conservative form"))

subplot(2,2,4)
nozGrid(x,A,T_nc);
title(sprintf("Variation of non dimensional Temparature along the axis at steady state \n non - conservative form"))


%%
%Plotting Non dimensionalized primitive variables conservative
figure(5)
opengl software
plot(x,rho_c,'m', 'linewidth', 1.5)
grid minor
hold on
plot(x,v_c,'r', 'linewidth', 1.5)
hold on
plot(x,T_c,'k', 'linewidth', 1.5)
hold on
plot(x,P_c,'c', 'linewidth', 1.5)
title('Steady state distribution of primitive variables - Conservative form')
legend("(rho/rho_0)","(v/v_0)","(T/T0)","(P/P_0)",'Location','Best')
xlabel ('X')
ylabel('Non - dimensional primitive variable')
%%
figure(6)
subplot(2,2,1)
nozGrid(x,A,v_c);
title(sprintf("Variation of non dimensional velocity along the axis at steady state \n conservative form"))

subplot(2,2,2)
nozGrid(x,A,rho_c);
title(sprintf("Variation of non dimensional density along the axis at steady state \n conservative form"))

subplot(2,2,3)
nozGrid(x,A,P_c);
title(sprintf("Variation of non dimensional Pressure along the axis at steady state \n conservative form"))

subplot(2,2,4)
nozGrid(x,A,T_c);
title(sprintf("Variation of non dimensional Temparature along the axis at steady state \n conservative form"))

%%

timenc = dtnc*nt;
t_NC = [dtnc:dtnc:timenc];

figure(7)
plot(t_NC,rho_tnc)
grid minor
hold on
plot(t_NC,p_tnc)
hold on
plot(t_NC,v_tnc)
hold on
plot(t_NC,T_throatnc)
hold on
plot(t_NC,M_tnc)
xlabel('Time')
ylabel('Non-dimensional Variables')
title(sprintf("Variation of Variables with time \n non-conservative form"))
legend("rho/rho_0","P/P_0","V/V_0","T/T0","Mach Number")

%%
timecf = dtc*nt;
t_CF = [dtc:dtc:timecf];

figure(8)
plot(t_CF,rho_tcf)
grid minor
hold on
plot(t_CF,p_tcf)
hold on
plot(t_CF,v_tcf)
hold on
plot(t_CF,T_throatcf)
hold on
plot(t_CF,M_tcf)
xlabel('Time')
ylabel('Non-dimensional Variables')
title(sprintf("Variation of Variables with time \n conservative form"))
legend("rho/rho_0","P/P_0","V/V_0","T/T0","Mach Number")
%%
figure(9)
plot(x,mass_flow_c,'m', 'linewidth', 1.5)
grid minor
hold on
plot(x,mass_flow_nc,'b', 'linewidth', 1.5)
legend('Conservative form','Non Conservative form')
title('Mass flow rate in Conservative form & Non Conservative form')
xlabel('X')
ylabel('Normalized mass flow rate')

MATLAB function for conservative form

function [rho, v, T, P, M, mass_flow,dtc,rho_t,p_t, v_t, T_throat,M_t] = conservative_function_MacCormack(n,x,dx, gamma, A, rho, v, T, C, nt,n_throat)
   
    % Solution Vectors
    U1 = rho .* A;
    U2 = rho .* A .* v;
    U3 = rho .* (T/(gamma-1) + (gamma/2) * (v.^2)) .* A;
    
    % Time step based on Stability
    a = sqrt(T);
    delt = (C * dx) ./ (a + v);
    dt = min(delt);
    dtc = dt;

    % Initializing Loop
    for z = 1:nt 
        U1_old = U1;
        U2_old = U2;
        U3_old = U3;
        
        % 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);


        % Predictor Step  (FDS)
        for i = 2: n-1
            dF1_dx = (F1(i+1) - F1(i)) / dx;
            dF2_dx = (F2(i+1) - F2(i)) / dx;
            dF3_dx = (F3(i+1) - F3(i)) / dx;
            dA_dx = (A(i+1) - A(i)) / dx;

            % Source Term
            J2(i) = (1/gamma) * rho(i) * T(i) * dA_dx;

            % Continuity Equation
            dU1_dt_p(i) = -dF1_dx;

            % Momentum Equation
            dU2_dt_p(i) = -dF2_dx + J2(i);

            % Energy Equation
            dU3_dt_p(i) = -dF3_dx;


            % Solution Update
            U1(i) = U1(i) + dU1_dt_p(i) * dt;
            U2(i) = U2(i) + dU2_dt_p(i) * dt;
            U3(i) = U3(i) + dU3_dt_p(i) * dt;

        end


       % Update 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);    


        % Update Flow Properties to apply in source term

        rho = U1 ./ A;
        v = U2 ./ U1;
        T = (gamma - 1) * (U3 ./ (rho .* A) - (gamma/2) * v.^2);

        % Corrector step  (BDS)

        for i = 2: n-1

            dF1_dx = (F1(i) - F1(i-1)) / dx;
            dF2_dx = (F2(i) - F2(i-1)) / dx;
            dF3_dx = (F3(i) - F3(i-1)) / dx;
            dA_dx = (A(i) - A(i-1)) / dx;

            % Source Term
            J2(i) = (1/gamma) * rho(i) * T(i) * dA_dx;

            % Continuity Equation
            dU1_dt_c(i) = -dF1_dx;

            % Momentum Equation
            dU2_dt_c(i) = -dF2_dx + J2(i);

            % Energy Equation
            dU3_dt_c(i) = -dF3_dx;

        end

        % Compute the Average Derivative

        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 j = 2: n-1

            U1(j) = U1_old(j) + dU1_dt(j) * dt;
            U2(j) = U2_old(j) + dU2_dt(j) * dt;
            U3(j) = U3_old(j) + dU3_dt(j) * dt;

        end

        % Apply Boundary Conditions

        % Inlet
        rho(1) = 1;
        T(1) = 1;

        U1(1) = rho(1) * A(1);
        U2(1) = 2 * U2(2) - U2(3);
        U3(1) = U1(1) * (T(1)/(gamma-1) + (gamma/2) * ((U2(1) / U1(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);

        % Update Flow Properties
        rho = U1 ./ A;
        v = U2 ./ U1;
        T = (gamma - 1) * (U3 ./ (rho .* A) - (gamma/2) * v.^2);
        P = rho .* T;
        M = v ./ sqrt(T);
        mass_flow = rho .* v .* A;
        
        %Storing values at the throat
        rho_t(z)=rho(n_throat);
        p_t(z)=P(n_throat);
        v_t(z)=v(n_throat);
        T_throat(z)=T(n_throat);
        M_t(z) = M(n_throat);  
        
        figure(2);        
        if z == 1
            plot(x, mass_flow, '--k', 'linewidth', 1.5)
            grid minor
            hold on
        elseif z == 50
            plot(x, mass_flow, 'r', 'linewidth', 1.5)
            hold on
        elseif z == 100
            plot(x, mass_flow, 'b', 'linewidth', 1.5)
            hold on
        elseif z == 150
            plot(x, mass_flow, 'g', 'linewidth', 1.5)
            hold on
        elseif z == 200
            plot(x, mass_flow, 'm', 'linewidth', 1.5)
            hold on
        elseif z == nt
            plot(x, mass_flow, '-.k', 'linewidth', 2)
            xlabel('x')
            ylabel('Mass Flow')
            legend('1Deltat', '50Deltat', '100Deltat', '150Deltat', '200Deltat', 'Steady State','Location','Best')
            title(sprintf('Transient State Mass Flow Profile for Conservative Solver'))
            hold off   
        end
        
        
        
    end
 

            
end

MATLAB function for non - conservative form

function [rho, v, T, P, M, mass_flow,dtnc,rho_t,p_t, v_t, T_throat,M_t] = non_conservative_function_MacCormack(n,x,dx, gamma, A,rho,v, T, C,nt,n_throat)
        
    for z = 1:nt
               
        rho_old = rho;
        v_old = v;
        T_old = T;
        
        % Time step based on Stability        
        a_old = sqrt(T_old);
        delt = (C * dx) ./ (a_old + v_old);
        dt = min(delt);
        dtnc=dt;

        % Predictor Step  (FDS)

        for i = 2: n-1

            drho_dx = (rho(i+1) - rho(i)) / dx;
            dv_dx = (v(i+1) - v(i)) / dx;
            dT_dx = (T(i+1) - T(i)) / dx;
            dlogA_dx = (log(A(i+1)) - log(A(i))) / dx;

            % Continuity Equation
            drho_dt_p(i) = -(rho(i) * dv_dx) - (rho(i) * v(i) * dlogA_dx) - (v(i) * drho_dx);

            % Momentum Equation
            dv_dt_p(i) = -(v(i) * dv_dx) - (1/gamma) * (dT_dx + (T(i)/rho(i)) * drho_dx);

            % Energy Equation
            dT_dt_p(i) = -(v(i) * dT_dx) - (gamma - 1) * T(i) * (dv_dx + v(i) * dlogA_dx);

            % Solution Update
            rho(i) = rho(i) + drho_dt_p(i) * dt;
            v(i) = v(i) + dv_dt_p(i) * dt;
            T(i) = T(i) + dT_dt_p(i) * dt;

        end

        % Corrector Step  (BDS)

        for i = 2: n-1

            drho_dx = (rho(i) - rho(i-1)) / dx;
            dv_dx = (v(i) - v(i-1)) / dx;
            dT_dx = (T(i) - T(i-1)) / dx;
            dlogA_dx = (log(A(i)) - log(A(i-1))) / dx;

            % Continuity Equation
            drho_dt_c(i) = -(rho(i) * dv_dx) - (rho(i) * v(i) * dlogA_dx) - (v(i) * drho_dx);

            % Momentum Equation
            dv_dt_c(i) = -(v(i) * dv_dx) - (1/gamma) * (dT_dx + (T(i)/rho(i)) * drho_dx);

            % Energy Equation
            dT_dt_c(i) = -(v(i) * dT_dx) - (gamma - 1) * T(i) * (dv_dx + v(i) * dlogA_dx);

        end

        % Compute the Average 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 Solution update

        for j = 2: n-1

            rho(j) = rho_old(j) + drho_dt(j) * dt;
            v(j) = v_old(j) + dv_dt(j) * dt;
            T(j) = T_old(j) + dT_dt(j) * dt;

        end

        % Apply Boundary Conditions

        % 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);
        
        P = rho .* T;
        M = v ./ sqrt(T);
        mass_flow = rho .* v .* A;
        
        rho_t(z)=rho(n_throat);
        p_t(z)=P(n_throat);
        v_t(z)=v(n_throat);
        T_throat(z)=T(n_throat);
        M_t(z) = M(n_throat);   
        
        
        
        % Plotting the Transient Mass Flow Rate
        figure(1);        
        if z == 1
            plot(x, mass_flow, '--k', 'linewidth', 1.5)
            grid minor
            hold on
        elseif z == 50
            plot(x, mass_flow, 'r', 'linewidth', 1.5)
            hold on
        elseif z == 100
            plot(x, mass_flow, 'b', 'linewidth', 1.5)
            hold on
        elseif z == 150
            plot(x, mass_flow, 'g', 'linewidth', 1.5)
            hold on
        elseif z == 200
            plot(x, mass_flow, 'm', 'linewidth', 1.5)
            hold on
        elseif z==nt
            plot(x, mass_flow, '-.k', 'linewidth', 2)
            xlabel('x')
            ylabel('Mass Flow')
            legend('1Deltat', '50 Deltat', '100 Deltat', '150 Deltat', '200 Deltat', 'Steady State','Location','Best')
            title(sprintf('Transient State Mass Flow Profile for Non - Conservative Solver'))
            hold off
        end

    end
 

    

end

MATLAB function for flow visualization

function [a,b] = nozGrid(x,AA,v)
y = linspace(-max(AA), max(AA), length(x));
vplot = ones(length(x),length(y));
for i = 1: length(x)
	for j = 1 : length (y)        
		if abs(y(j))<AA(i)
            vplot(i,j) = v(i);
        else
            vplot(i,j) = -0.1;
        end         
	end
end

[a,b] = contourf(x,y,vplot','showText','off');
% colorbar;
colormap(jet);clc
xlabel('X Axis');
title(sprintf('Variation of non-dimensional velocity along the axial direction \n non - Conservative Form. Number of node = 201'))
ylabel('Y Axis');
hold on
plot(x,AA,'w','linewidth', 2)
hold on
plot(x,-AA,'w','linewidth', 2)
end


Results

1. Steady-state distribution of primitive variables inside the nozzle

a)Conservative form

The Steady-state distribution of various primitive variables obtained via the conservative form of the equations is shown here. The Trend is verified by referring Anderson Textbook

b)Non - Conservative form

The Steady-state distribution of various primitive variables obtained via the non-conservative form of the equations is shown here. The Trend is verified by referring Anderson Textbook


2. Time-wise variation of the primitive variables

a) Conservative form

The below figure shows the time-wise variation of various primitive values at the throat using conservative method.

b)Non - Conservative form

The below figure shows the time-wise variation of various primitive values at the throat using the non-conservative method


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

a) Conservative form

Time-wise variation of mass flow along with the axis is plotted here. Here the conservative form is used

b)Non - Conservative form

Time-wise variation of mass flow along with the axis is plotted here. Here the non-conservative form is used


4. Comparison of Normalized mass flow rate distributions of both forms.

The steady-state mass-flow rate obtained via both forms of the equations is plotted here.

Grid Independence Test.

The above code is run for double the number of nodes and the final distribution is almost a constant. So the solution is grid-independent.

I am attaching my code 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.