Challenge

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




















Matlab code for Non-conservative form

% Clear previous data

clear

close all

clc

% Inputs

n = 31; % Number of grid points

x = linspace(0, 3, n); % Discretized spatial domain

dx = x(2) - x(1); % Spatial step size

gamma = 1.4; % Specific heat ratio

% Initial profiles

rho = 1 - 0.3146 * x; % Initial density profile

t = 1 - 0.2314 * x; % Initial temperature profile

v = (0.1 + 1.09 * x) .* t .^ 0.5; % Initial velocity profile

% Nozzle area profile

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

throat = find(a == 1); % Locate throat position

% Time steps

nt = 1400; % Number of time steps

CFL = 0.5; % CFL number

dt = min((CFL .* dx) ./ (v + sqrt(t))); % Time step size

% Outer time loop

for k = 1:nt

% Store old values for the corrector step

rho_old = rho;

v_old = v;

t_old = t;

% Predictor step

for j = 2:n-1

% Calculate derivatives

dvdx = (v(j+1) - v(j)) / dx;

drhodx = (rho(j+1) - rho(j)) / dx;

dtdx = (t(j+1) - t(j)) / dx;

dlogadx = (log(a(j+1)) - log(a(j))) / dx;

% Continuity equation

drhodt_p(j) = -rho(j) * dvdx - rho(j) * v(j) * dlogadx - v(j) * drhodx;

% Momentum equation

dvdt_p(j) = -v(j) * dvdx - (1 / gamma) * (dtdx + (t(j) / rho(j)) * drhodx);

% Energy equation

dtdt_p(j) = -v(j) * dtdx - (gamma - 1) * t(j) * (dvdx + v(j) * dlogadx);

% Solution update

rho(j) = rho(j) + drhodt_p(j) * dt;

v(j) = v(j) + dvdt_p(j) * dt;

t(j) = t(j) + dtdt_p(j) * dt;

end

% Corrector step

for j = 2:n-1

% Calculate derivatives

dvdx = (v(j) - v(j-1)) / dx;

drhodx = (rho(j) - rho(j-1)) / dx;

dtdx = (t(j) - t(j-1)) / dx;

dlogadx = (log(a(j)) - log(a(j-1))) / dx;

% Continuity equation

drhodt_c(j) = -rho(j) * dvdx - rho(j) * v(j) * dlogadx - v(j) * drhodx;

% Momentum equation

dvdt_c(j) = -v(j) * dvdx - (1 / gamma) * (dtdx + (t(j) / rho(j)) * drhodx);

% Energy equation

dtdt_c(j) = -v(j) * dtdx - (gamma - 1) * t(j) * (dvdx + v(j) * dlogadx);

% Compute the average time derivative

drhodt(j) = 0.5 * (drhodt_p(j) + drhodt_c(j));

dvdt(j) = 0.5 * (dvdt_p(j) + dvdt_c(j));

dtdt(j) = 0.5 * (dtdt_p(j) + dtdt_c(j));

end

% Final solution update

for i = 2:n-1

rho(i) = rho_old(i) + drhodt(i) * dt;

v(i) = v_old(i) + dvdt(i) * dt;

t(i) = t_old(i) + dtdt(i) * dt;

end

% Applying the boundary conditions

% Inlet

v(1) = 2 * v(2) - v(3);

rho(1) = 1;

t(1) = 1;

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

% Calculating derived quantities

p = rho .* t; % Pressure

mass_flow_rate = rho .* a .* v; % Mass flow rate

mach_no = v ./ sqrt(t); % Mach number

% Storing values at the throat for time-wise plots

p_throat(k) = p(throat);

rho_throat(k) = rho(throat);

v_throat(k) = v(throat);

t_throat(k) = t(throat);

mass_flow_rate_throat(k) = mass_flow_rate(throat);

mach_no_throat(k) = mach_no(throat);

% Storing mass flow rates at specific time steps for comparison

if k == 50

m_50 = mass_flow_rate;

end

if k == 100

m_100 = mass_flow_rate;

end

if k == 150

m_150 = mass_flow_rate;

end

if k == 200

m_200 = mass_flow_rate;

end

if k == 700

m_700 = mass_flow_rate;

end

end

% Plotting the results

% Steady state distribution of primitive variables

figure(1)

subplot(4,1,1)

plot(x, mach_no)

xlabel('Length of the nozzle')

ylabel('Mach No')

title('Steady state distribution of primitive variables (Non-Conservative form)')

subplot(4,1,2)

plot(x, p)

xlabel('Length of the nozzle')

ylabel('Pressure')

subplot(4,1,3)

plot(x, rho)

xlabel('Length of the nozzle')

ylabel('Density')

subplot(4,1,4)

plot(x, t)

xlabel('Length of the nozzle')

ylabel('Temperature')

% Time-wise variation of primitive variables at the throat

figure(2)

subplot(4,1,1)

plot(1:nt, p_throat)

ylabel('Pressure')

title('Time-wise variation of primitive variables (Non-Conservative form)')

subplot(4,1,2)

plot(1:nt, rho_throat)

ylabel('Density')

subplot(4,1,3)

plot(1:nt, t_throat)

ylabel('Temperature')

subplot(4,1,4)

plot(1:nt, mach_no_throat)

ylabel('Mach No')

% Mass flow rate distribution

figure(3)

plot(x, mass_flow_rate)

xlabel('Length of the nozzle')

ylabel('Mass flow rate')

title('Mass flow rate distribution (Non-Conservative form)')

% Mass flow rate at the throat over time

figure(4)

plot(1:nt, mass_flow_rate_throat)

xlabel('Different Time steps')

ylabel('Mass flow rate at throat')

title('Mass flow rate distribution at throat (Non-Conservative form)')

% Comparison of mass flow rates at different time steps

figure(5)

plot(x, m_50, 'r')

hold on

plot(x, m_100, 'b')

hold on

plot(x, m_150, 'y')

hold on

plot(x, m_200, 'm')

hold on

plot(x, m_700, 'g')

title('Mass flow rates at different Timesteps - Conservative form')

xlabel('Length of the nozzle')

ylabel('Mass flow rate')

legend({'50th Timestep', '100th Timestep', '150th Timestep', '200th Timestep', '700th Timestep'})

grid on




This script follows these steps:

  1. Initializes the spatial grid and flow variables.
  2. Sets up the nozzle area profile.
  3. Determines the time step size based on the CFL condition.
  4. Performs the time-marching process using the MacCormack method with predictor and corrector steps.
  5. Applies boundary conditions at each time step.
  6. Plots the results, including the steady-state distribution of primitive variables, time-wise variation of variables at the throat, mass flow rate distribution, and comparison of mass flow rates at different time steps.

The code includes detailed comments to help understand each section and the purpose of each calculation.










Initial Conditions

The initial conditions for U1, U2 and U3 were calculated by assuming the following variations of ρ’ and T’


Matlab code for Conservative form of Quasi-one-dimensional flow

% Clear all previous data and close all figures

clear all

close all

clc

% Define constants and initial setup

n = 31; % Number of grid points

x = linspace(0, 3, n); % Create grid from 0 to 3

dx = x(2) - x(1); % Calculate grid spacing

gamma = 1.4; % Specific heat ratio

% Calculate initial density (rho) and temperature (t) profiles

for i = 1:length(x)

if x(i) < 0.5

rho(i) = 1;

t(i) = 1;

elseif x(i) < 1.5

rho(i) = 1 - 0.366 * (x(i) - 0.5);

t(i) = 1 - 0.167 * (x(i) - 0.5);

else

rho(i) = 0.634 - 0.3879 * (x(i) - 1.5);

t(i) = 0.833 - 0.3507 * (x(i) - 1.5);

end

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

end

throat = find(A == 1); % Locate the throat (minimum area)

p = rho .* t; % Initial pressure

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

U1 = rho .* A;

U2 = rho .* A .* v;

U3 = rho .* ((t / (gamma - 1)) + ((gamma / 2) * v.^2)) .* A;

% Set the Courant–Friedrichs–Lewy (CFL) condition

CFL = 0.5;

dt = min((CFL * dx) ./ (v + sqrt(t))); % Time step size

% Time-stepping loop

for k = 1:1400

% Store old values

U1_old = U1;

U2_old = U2;

U3_old = U3;

% Calculate fluxes

F1 = U2;

F2 = (U2.^2 ./ U1) + ((gamma - 1) / gamma) * (U3 - (gamma / 2) * (U2.^2 ./ U1));

F3 = (gamma * U2 .* U3 ./ U1) - (gamma * (gamma - 1) * U2.^3 ./ (2 * U1.^2));

% Predictor step

for i = 2:n-1

J2_p(i) = (1 / gamma) * rho(i) * t(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;

% Update solution

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

% Update primitive variables

rho = U1 ./ A;

v = U2 ./ U1;

t = (gamma - 1) * ((U3 ./ U1) - (gamma / 2) * (v.^2));

% Recalculate fluxes

F1 = U2;

F2 = (U2.^2 ./ U1) + ((gamma - 1) / gamma) * (U3 - (gamma / 2) * (U2.^2 ./ U1));

F3 = (gamma * U2 .* U3 ./ U1) - (gamma * (gamma - 1) * U2.^3 ./ (2 * U1.^2));

% Corrector step

for i = 2:n-1

J2_c(i) = (1 / gamma) * rho(i) * t(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 the rates of change

dU1_dt = 0.5 * (dU1dt_p + dU1dt_c);

dU2_dt = 0.5 * (dU2dt_p + dU2dt_c);

dU3_dt = 0.5 * (dU3dt_p + dU3dt_c);

% Final 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

% Update boundary conditions

U1(1) = A(1) * rho(1);

U2(1) = 2 * U2(2) - U2(3);

U3(1) = U1(1) * ((t(1) / (gamma - 1)) + (gamma / 2) * v(1)^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);

% Update primitive variables again

rho = U1 ./ A;

v = U2 ./ U1;

t = (gamma - 1) * ((U3 ./ U1) - (gamma / 2) * (v.^2));

p = rho .* t;

mass_flow_rate = rho .* A .* v;

mach_no = v ./ sqrt(t);

% Store throat values at each time step

rho_throat(k) = rho(throat);

v_throat(k) = v(throat);

t_throat(k) = t(throat);

mass_flow_rate_throat(k) = mass_flow_rate(throat);

mach_no_throat(k) = mach_no(throat);

% Save mass flow rate at specific time steps

if k == 50, m_50 = mass_flow_rate; end

if k == 100, m_100 = mass_flow_rate; end

if k == 200, m_200 = mass_flow_rate; end

if k == 700, m_700 = mass_flow_rate; end

if k == 800, m_800 = mass_flow_rate; end

if k == 1000, m_1000 = mass_flow_rate; end

if k == 1400, m_1400 = mass_flow_rate; end

end

% Plot the results

figure(1)

subplot(4, 1, 1)

plot(x, mach_no)

xlabel('Length of the nozzle')

ylabel('Mach No')

title('Steady state distribution of primitive variables (Conservative form)')

subplot(4, 1, 2)

plot(x, p)

xlabel('Length of the nozzle')

ylabel('Pressure')

subplot(4, 1, 3)

plot(x, rho)

xlabel('Length of the nozzle')

ylabel('Density')

subplot(4, 1, 4)

plot(x, t)

xlabel('Length of the nozzle')

ylabel('Temperature')

% Plot time-wise variation of primitive variables at the throat

figure(2)

subplot(3, 1, 1)

plot(1:1400, v_throat)

ylabel('Velocity')

title('Time-wise variation of primitive variables (Conservative form)')

subplot(3, 1, 2)

plot(1:1400, rho_throat)

ylabel('Density')

subplot(3, 1, 3)

plot(1:1400, t_throat)

ylabel('Temperature')

% Plot mass flow rate distribution along the nozzle at the last time step

figure(3)

plot(x, m_1400)

xlabel('Length of the nozzle')

ylabel('Mass flow rate')

title('Mass flow rate distribution through length of the nozzle (Conservative form)')

% Plot mass flow rate at the throat over time

figure(4)

plot(1:1400, mass_flow_rate_throat)

xlabel('Different Time step')

ylabel('Mass flow rate at throat')

title('Mass flow rate distribution (Conservative form)')

% Plot mass flow rates at different time steps

figure(5)

plot(x, m_50)

hold on

plot(x, m_100)

plot(x, m_200)

plot(x, m_700)

plot(x, m_800)

plot(x, m_1000)

plot(x, m_1400)

xlabel('Length of the nozzle')

ylabel('Mass flow rate')

title('Mass flow rate at different time steps')

legend('50', '100', '200', '700', '800', '1000', '1400')

hold off

Output Interpretation:

Mach Number Distribution (Figure 1, subplot 1)This plot shows the Mach number along the length of the nozzle.

    • The Mach number is subsonic (less than 1) at the inlet.
    • The Mach number is supersonic (greater than 1) at the outlet.
    • Mach number equals 1 at the throat (length 1.5), indicating that the flow is sonic at this point.
    1. Pressure, Density, and Temperature Distributions (Figure 1, subplots 2-4):

      • These plots show how pressure, density, and temperature vary along the length of the nozzle.
      • The pressure, density, and temperature profiles adjust as the flow accelerates from subsonic to supersonic speeds.
    2. Time-wise Variation at Throat (Figure 2):

      • This set of plots shows how velocity, density, and temperature at the throat change over time steps.
      • This indicates how the throat conditions stabilize as the simulation progresses.
    3. Mass Flow Rate Distribution (Figure 3):

      • This plot shows the mass flow rate along the length of the nozzle at the final time step.
      • It helps verify the conservation of mass flow rate through the nozzle.
    4. Mass Flow Rate at Throat Over Time (Figure 4):

      • This plot shows how the mass flow rate at the throat evolves over time.
      • It should stabilize, indicating steady-state conditions.
    5. Mass Flow Rates at Different Time Steps (Figure 5):

      • This plot shows the mass flow rates at various significant time steps (50, 100, 200, 700, 800, 1000, 1400).
      • This demonstrates the progression toward a steady-state mass flow rate distribution through the nozzle.






    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.