Compressible Flow Basics
When air moves slowly we happily treat it as incompressible. But push a flow past roughly 30% of the speed of sound and density changes can no longer be ignored. Rockets, jet engines, supersonic wind tunnels, and even a leaking high-pressure tank all live in the world of compressible flow, where temperature, pressure, and density are tightly coupled.
This lesson introduces the speed of sound, the Mach number, stagnation (total) properties, isentropic nozzle flow, and a brief look at normal shocks — all illustrated with Python.
Speed of Sound and Mach Number
Sound is a small pressure disturbance that travels through a gas. For an ideal gas the speed of sound is:
Sponsored
Harshal got placed at Fiat Chrysler as Design Engineer
Watch his video testimonial on how the program helped him
$$a = \sqrt{\gamma R T}$$
where $\gamma$ is the ratio of specific heats ($\approx 1.4$ for air), $R$ is the specific gas constant ($287\ \text{J/kg·K}$ for air), and $T$ is the absolute temperature.
The Mach number is the ratio of flow speed to local sound speed:
Sponsored
Master CATIA, NX, LS-DYNA, HyperMesh, ANSYS
The exact tools used by Mahindra, Bosch & TATA ELXSI
$$M = \frac{V}{a}$$
| Mach range | Regime |
|---|
| $M < 0.3$ | Incompressible (density ~ constant) |
| $0.3 \le M < 0.8$ | Subsonic compressible |
| $0.8 \le M < 1.2$ | Transonic |
| $1.2 \le M < 5$ | Supersonic |
| $M \ge 5$ | Hypersonic |
import numpy as np
gamma = 1.4
R = 287.0 # J/kg.K for air
def speed_of_sound(T):
return np.sqrt(gamma * R * T)
for T in [216.65, 288.15, 1000.0]: # stratosphere, sea level, hot gas
a = speed_of_sound(T)
print(f"T = {T:7.2f} K -> a = {a:6.1f} m/s")
# A jet cruising at 250 m/s at 11 km altitude (T = 216.65 K)
V = 250.0
M = V / speed_of_sound(216.65)
print(f"\nCruise Mach number = {M:.3f}")
Output:
T = 216.65 K -> a = 295.0 m/s
T = 288.15 K -> a = 340.3 m/s
T = 1000.00 K -> a = 633.9 m/s
Cruise Mach number = 0.847
Stagnation (Total) Properties
If you bring a flowing gas to rest isentropically (no losses), its kinetic energy converts to enthalpy, raising the temperature and pressure. These rest-state values are the stagnation or total properties, denoted with a subscript 0:
$$\frac{T_0}{T} = 1 + \frac{\gamma - 1}{2} M^2$$
Sponsored
Abhishek landed his dream job at TATA ELXSI
From learning simulations to working at an industry leader
$$\frac{p_0}{p} = \left(1 + \frac{\gamma - 1}{2} M^2\right)^{\frac{\gamma}{\gamma - 1}}, \qquad \frac{\rho_0}{\rho} = \left(1 + \frac{\gamma - 1}{2} M^2\right)^{\frac{1}{\gamma - 1}}$$
import numpy as np
gamma = 1.4
def stagnation_ratios(M):
f = 1 + 0.5 * (gamma - 1) * M**2
T0_T = f
p0_p = f**(gamma / (gamma - 1))
rho0_rho = f**(1 / (gamma - 1))
return T0_T, p0_p, rho0_rho
# Air flowing at M = 0.85, static T = 216.65 K, static p = 22.6 kPa
M = 0.85
T, p = 216.65, 22.6e3
T0_T, p0_p, rho0_rho = stagnation_ratios(M)
print(f"T0/T = {T0_T:.4f} -> T0 = {T0_T*T:7.2f} K")
print(f"p0/p = {p0_p:.4f} -> p0 = {p0_p*p/1e3:7.2f} kPa")
print(f"rho0/rho = {rho0_rho:.4f}")
Output:
T0/T = 1.1445 -> T0 = 247.95 K
p0/p = 1.6038 -> p0 = 36.25 kPa
rho0/rho = 1.4013
The stagnation temperature is what a probe at the nose of an aircraft actually measures — it is significantly hotter than the surrounding air.
Isentropic Property Ratios vs Mach
Let's plot how the static-to-stagnation ratios fall off as Mach number rises.
import numpy as np
import matplotlib.pyplot as plt
gamma = 1.4
M = np.linspace(0, 3, 300)
f = 1 + 0.5 * (gamma - 1) * M**2
T_T0 = 1 / f
p_p0 = f**(-gamma / (gamma - 1))
rho_rho0 = f**(-1 / (gamma - 1))
plt.figure(figsize=(9, 6))
plt.plot(M, T_T0, label=r'$T/T_0
Output:
At M=1: T*/T0 = 0.8333, p*/p0 = 0.5283
The pressure must drop to about 52.8% of the stagnation value to reach sonic speed — a key threshold for choked flow.
Choked Flow in a Converging-Diverging Nozzle
The area-Mach relation ties the local cross-section area to the Mach number, normalized by the area where $M=1$ (the throat, denoted $A^$):
$$\frac{A}{A^} = \frac{1}{M}\left[\frac{2}{\gamma+1}\left(1 + \frac{\gamma-1}{2}M^2\right)\right]^{\frac{\gamma+1}{2(\gamma-1)}}$$
This relation has two roots for a given $A/A^$: one subsonic and one supersonic. A converging-diverging (de Laval) nozzle uses the converging section to accelerate flow to $M=1$ at the throat, then the diverging section to go supersonic. Once the throat reaches $M=1$ the flow is choked — the mass flow rate cannot increase even if you lower the back pressure further.
import numpy as np
from scipy.optimize import brentq
gamma = 1.4
def area_ratio(M):
"""A/A* as a function of Mach number."""
f = 1 + 0.5 * (gamma - 1) * M**2
exp = (gamma + 1) / (2 * (gamma - 1))
return (1 / M) * (2 / (gamma + 1) * f)**exp
def mach_from_area(AR, supersonic=False):
"""Invert the area-Mach relation for a given A/A*."""
if supersonic:
return brentq(lambda M: area_ratio(M) - AR, 1.0 + 1e-6, 50)
else:
return brentq(lambda M: area_ratio(M) - AR, 1e-6, 1.0)
# A nozzle with exit area = 4 x throat area
AR = 4.0
M_sub = mach_from_area(AR, supersonic=False)
M_sup = mach_from_area(AR, supersonic=True)
print(f"A/A* = {AR}: subsonic M = {M_sub:.4f}, supersonic M = {M_sup:.4f}")
# Choked mass flow through the throat
p0, T0 = 5e5, 500.0 # stagnation conditions (Pa, K)
R = 287.0
A_throat = 0.01 # m^2
mdot = (A_throat * p0 / np.sqrt(T0)) * np.sqrt(gamma / R) * \
(1 + 0.5*(gamma-1))**(-(gamma+1)/(2*(gamma-1)))
print(f"Choked mass flow rate = {mdot:.4f} kg/s")
Output:
A/A* = 4.0: subsonic M = 0.1465, supersonic M = 2.9402
Choked mass flow rate = 9.0378 kg/s
Normal Shock Relations (Brief)
When a supersonic flow is forced to decelerate abruptly, it passes through a normal shock — a near-discontinuity across which the flow goes from supersonic ($M_1 > 1$) to subsonic ($M_2 < 1$). The process is adiabatic but not isentropic: entropy rises and stagnation pressure drops. The downstream Mach number and the static jumps are:
$$M_2^2 = \frac{1 + \frac{\gamma-1}{2}M_1^2}{\gamma M_1^2 - \frac{\gamma-1}{2}}, \qquad
\frac{p_2}{p_1} = 1 + \frac{2\gamma}{\gamma+1}\left(M_1^2 - 1\right)$$
$$\frac{T_2}{T_1} = \frac{\left[1 + \frac{\gamma-1}{2}M_1^2\right]\left[\frac{2\gamma}{\gamma-1}M_1^2 - 1\right]}{M_1^2 \left(\frac{2\gamma}{\gamma-1} + \frac{\gamma-1}{2}\cdot\frac{2}{1}\right)}$$
import numpy as np
gamma = 1.4
def normal_shock(M1):
M2 = np.sqrt((1 + 0.5*(gamma-1)*M1**2) / (gamma*M1**2 - 0.5*(gamma-1)))
p2_p1 = 1 + (2*gamma/(gamma+1)) * (M1**2 - 1)
rho2_rho1 = ((gamma+1)*M1**2) / (2 + (gamma-1)*M1**2)
T2_T1 = p2_p1 / rho2_rho1
# Stagnation pressure ratio across the shock (always < 1)
term1 = ((gamma+1)*M1**2 / (2 + (gamma-1)*M1**2))**(gamma/(gamma-1))
term2 = ((gamma+1) / (2*gamma*M1**2 - (gamma-1)))**(1/(gamma-1))
p02_p01 = term1 * term2
return M2, p2_p1, T2_T1, rho2_rho1, p02_p01
M1 = 2.0
M2, p2_p1, T2_T1, rho2_rho1, p02_p01 = normal_shock(M1)
print(f"Upstream M1 = {M1}")
print(f" M2 = {M2:.4f}")
print(f" p2/p1 = {p2_p1:.4f}")
print(f" T2/T1 = {T2_T1:.4f}")
print(f" rho2/rho1 = {rho2_rho1:.4f}")
print(f" p02/p01 = {p02_p01:.4f} (stagnation pressure loss)")
Output:
Upstream M1 = 2.0
M2 = 0.5774
p2/p1 = 4.5000
T2/T1 = 1.6875
rho2/rho1 = 2.6667
p02/p01 = 0.7209
The flow becomes subsonic, static pressure jumps 4.5x, and about 28% of the stagnation pressure is lost to entropy generation — a real cost in supersonic inlet design.
Common Pitfalls
- Using incompressible Bernoulli above $M \approx 0.3$. Density changes matter; use the isentropic relations instead.
- Forgetting temperature in the sound speed. $a = \sqrt{\gamma R T}$ depends on the local temperature, which itself changes through a nozzle.
- Treating a shock as isentropic. Shocks are adiabatic but raise entropy — stagnation temperature is conserved, but stagnation pressure drops.
- Picking the wrong root of $A/A^$. A given area ratio gives both a subsonic and supersonic Mach number; the nozzle geometry and back pressure decide which one occurs.
- Thinking lower back pressure always increases mass flow. Once the throat chokes ($M=1$), the mass flow is fixed.
Key Takeaways
- The speed of sound $a=\sqrt{\gamma R T}$ and Mach number $M=V/a$ classify the flow regime; compressibility matters above $M\approx0.3$.
- Stagnation properties ($T_0, p_0, \rho_0$) are reached by bringing the flow isentropically to rest and rise with $M^2$.
- The isentropic relations give $T/T_0$, $p/p_0$, $\rho/\rho_0$ as functions of Mach number; sonic conditions need $p/p_0 = 0.528$.
- A converging-diverging nozzle accelerates flow to $M=1$ at the throat (choked), then supersonic in the diverging section; the area-Mach relation has subsonic and supersonic roots.
- A normal shock** turns supersonic flow subsonic, jumping pressure and temperature while losing stagnation pressure.
Next, we open up the full Navier-Stokes equations and take our first step into computational fluid dynamics.
, lw=2)
plt.plot(M, p_p0, label=r'$p/p_0
Output:
___CODEBLOCK_5___
The pressure must drop to about 52.8% of the stagnation value to reach sonic speed — a key threshold for choked flow.
Choked Flow in a Converging-Diverging Nozzle
The area-Mach relation ties the local cross-section area to the Mach number, normalized by the area where $M=1$ (the throat, denoted $A^$):
$$\frac{A}{A^} = \frac{1}{M}\left[\frac{2}{\gamma+1}\left(1 + \frac{\gamma-1}{2}M^2\right)\right]^{\frac{\gamma+1}{2(\gamma-1)}}$$
This relation has two roots for a given $A/A^$: one subsonic and one supersonic. A converging-diverging (de Laval) nozzle uses the converging section to accelerate flow to $M=1$ at the throat, then the diverging section to go supersonic. Once the throat reaches $M=1$ the flow is choked — the mass flow rate cannot increase even if you lower the back pressure further.
___CODEBLOCK_6___
Output:
___CODEBLOCK_7___
Normal Shock Relations (Brief)
When a supersonic flow is forced to decelerate abruptly, it passes through a normal shock — a near-discontinuity across which the flow goes from supersonic ($M_1 > 1$) to subsonic ($M_2 < 1$). The process is adiabatic but not isentropic: entropy rises and stagnation pressure drops. The downstream Mach number and the static jumps are:
$$M_2^2 = \frac{1 + \frac{\gamma-1}{2}M_1^2}{\gamma M_1^2 - \frac{\gamma-1}{2}}, \qquad
\frac{p_2}{p_1} = 1 + \frac{2\gamma}{\gamma+1}\left(M_1^2 - 1\right)$$
$$\frac{T_2}{T_1} = \frac{\left[1 + \frac{\gamma-1}{2}M_1^2\right]\left[\frac{2\gamma}{\gamma-1}M_1^2 - 1\right]}{M_1^2 \left(\frac{2\gamma}{\gamma-1} + \frac{\gamma-1}{2}\cdot\frac{2}{1}\right)}$$
___CODEBLOCK_8___
Output:
___CODEBLOCK_9___
The flow becomes subsonic, static pressure jumps 4.5x, and about 28% of the stagnation pressure is lost to entropy generation — a real cost in supersonic inlet design.
Common Pitfalls
- Using incompressible Bernoulli above $M \approx 0.3$. Density changes matter; use the isentropic relations instead.
- Forgetting temperature in the sound speed. $a = \sqrt{\gamma R T}$ depends on the local temperature, which itself changes through a nozzle.
- Treating a shock as isentropic. Shocks are adiabatic but raise entropy — stagnation temperature is conserved, but stagnation pressure drops.
- Picking the wrong root of $A/A^$. A given area ratio gives both a subsonic and supersonic Mach number; the nozzle geometry and back pressure decide which one occurs.
- Thinking lower back pressure always increases mass flow. Once the throat chokes ($M=1$), the mass flow is fixed.
Key Takeaways
- The speed of sound $a=\sqrt{\gamma R T}$ and Mach number $M=V/a$ classify the flow regime; compressibility matters above $M\approx0.3$.
- Stagnation properties ($T_0, p_0, \rho_0$) are reached by bringing the flow isentropically to rest and rise with $M^2$.
- The isentropic relations give $T/T_0$, $p/p_0$, $\rho/\rho_0$ as functions of Mach number; sonic conditions need $p/p_0 = 0.528$.
- A converging-diverging nozzle accelerates flow to $M=1$ at the throat (choked), then supersonic in the diverging section; the area-Mach relation has subsonic and supersonic roots.
- A normal shock** turns supersonic flow subsonic, jumping pressure and temperature while losing stagnation pressure.
Next, we open up the full Navier-Stokes equations and take our first step into computational fluid dynamics.
, lw=2)
plt.plot(M, rho_rho0, label=r'$\rho/\rho_0
Output:
___CODEBLOCK_5___
The pressure must drop to about 52.8% of the stagnation value to reach sonic speed — a key threshold for choked flow.
Choked Flow in a Converging-Diverging Nozzle
The area-Mach relation ties the local cross-section area to the Mach number, normalized by the area where $M=1$ (the throat, denoted $A^$):
$$\frac{A}{A^} = \frac{1}{M}\left[\frac{2}{\gamma+1}\left(1 + \frac{\gamma-1}{2}M^2\right)\right]^{\frac{\gamma+1}{2(\gamma-1)}}$$
This relation has two roots for a given $A/A^$: one subsonic and one supersonic. A converging-diverging (de Laval) nozzle uses the converging section to accelerate flow to $M=1$ at the throat, then the diverging section to go supersonic. Once the throat reaches $M=1$ the flow is choked — the mass flow rate cannot increase even if you lower the back pressure further.
___CODEBLOCK_6___
Output:
___CODEBLOCK_7___
Normal Shock Relations (Brief)
When a supersonic flow is forced to decelerate abruptly, it passes through a normal shock — a near-discontinuity across which the flow goes from supersonic ($M_1 > 1$) to subsonic ($M_2 < 1$). The process is adiabatic but not isentropic: entropy rises and stagnation pressure drops. The downstream Mach number and the static jumps are:
$$M_2^2 = \frac{1 + \frac{\gamma-1}{2}M_1^2}{\gamma M_1^2 - \frac{\gamma-1}{2}}, \qquad
\frac{p_2}{p_1} = 1 + \frac{2\gamma}{\gamma+1}\left(M_1^2 - 1\right)$$
$$\frac{T_2}{T_1} = \frac{\left[1 + \frac{\gamma-1}{2}M_1^2\right]\left[\frac{2\gamma}{\gamma-1}M_1^2 - 1\right]}{M_1^2 \left(\frac{2\gamma}{\gamma-1} + \frac{\gamma-1}{2}\cdot\frac{2}{1}\right)}$$
___CODEBLOCK_8___
Output:
___CODEBLOCK_9___
The flow becomes subsonic, static pressure jumps 4.5x, and about 28% of the stagnation pressure is lost to entropy generation — a real cost in supersonic inlet design.
Common Pitfalls
- Using incompressible Bernoulli above $M \approx 0.3$. Density changes matter; use the isentropic relations instead.
- Forgetting temperature in the sound speed. $a = \sqrt{\gamma R T}$ depends on the local temperature, which itself changes through a nozzle.
- Treating a shock as isentropic. Shocks are adiabatic but raise entropy — stagnation temperature is conserved, but stagnation pressure drops.
- Picking the wrong root of $A/A^$. A given area ratio gives both a subsonic and supersonic Mach number; the nozzle geometry and back pressure decide which one occurs.
- Thinking lower back pressure always increases mass flow. Once the throat chokes ($M=1$), the mass flow is fixed.
Key Takeaways
- The speed of sound $a=\sqrt{\gamma R T}$ and Mach number $M=V/a$ classify the flow regime; compressibility matters above $M\approx0.3$.
- Stagnation properties ($T_0, p_0, \rho_0$) are reached by bringing the flow isentropically to rest and rise with $M^2$.
- The isentropic relations give $T/T_0$, $p/p_0$, $\rho/\rho_0$ as functions of Mach number; sonic conditions need $p/p_0 = 0.528$.
- A converging-diverging nozzle accelerates flow to $M=1$ at the throat (choked), then supersonic in the diverging section; the area-Mach relation has subsonic and supersonic roots.
- A normal shock** turns supersonic flow subsonic, jumping pressure and temperature while losing stagnation pressure.
Next, we open up the full Navier-Stokes equations and take our first step into computational fluid dynamics.
, lw=2)
plt.axvline(1.0, color='gray', ls='--', alpha=0.7, label='M = 1 (sonic)')
plt.xlabel('Mach number M'); plt.ylabel('Static / Stagnation ratio')
plt.title('Isentropic Flow Property Ratios')
plt.legend(); plt.grid(alpha=0.3)
plt.show()
# Sonic (M=1) reference values
fc = 1 + 0.5 * (gamma - 1)
print(f"At M=1: T*/T0 = {1/fc:.4f}, p*/p0 = {fc**(-gamma/(gamma-1)):.4f}")
Output:
___CODEBLOCK_5___
The pressure must drop to about 52.8% of the stagnation value to reach sonic speed — a key threshold for choked flow.
Choked Flow in a Converging-Diverging Nozzle
The area-Mach relation ties the local cross-section area to the Mach number, normalized by the area where $M=1$ (the throat, denoted $A^$):
$$\frac{A}{A^} = \frac{1}{M}\left[\frac{2}{\gamma+1}\left(1 + \frac{\gamma-1}{2}M^2\right)\right]^{\frac{\gamma+1}{2(\gamma-1)}}$$
This relation has two roots for a given $A/A^$: one subsonic and one supersonic. A converging-diverging (de Laval) nozzle uses the converging section to accelerate flow to $M=1$ at the throat, then the diverging section to go supersonic. Once the throat reaches $M=1$ the flow is choked — the mass flow rate cannot increase even if you lower the back pressure further.
___CODEBLOCK_6___
Output:
___CODEBLOCK_7___
Normal Shock Relations (Brief)
When a supersonic flow is forced to decelerate abruptly, it passes through a normal shock — a near-discontinuity across which the flow goes from supersonic ($M_1 > 1$) to subsonic ($M_2 < 1$). The process is adiabatic but not isentropic: entropy rises and stagnation pressure drops. The downstream Mach number and the static jumps are:
$$M_2^2 = \frac{1 + \frac{\gamma-1}{2}M_1^2}{\gamma M_1^2 - \frac{\gamma-1}{2}}, \qquad
\frac{p_2}{p_1} = 1 + \frac{2\gamma}{\gamma+1}\left(M_1^2 - 1\right)$$
$$\frac{T_2}{T_1} = \frac{\left[1 + \frac{\gamma-1}{2}M_1^2\right]\left[\frac{2\gamma}{\gamma-1}M_1^2 - 1\right]}{M_1^2 \left(\frac{2\gamma}{\gamma-1} + \frac{\gamma-1}{2}\cdot\frac{2}{1}\right)}$$
___CODEBLOCK_8___
Output:
___CODEBLOCK_9___
The flow becomes subsonic, static pressure jumps 4.5x, and about 28% of the stagnation pressure is lost to entropy generation — a real cost in supersonic inlet design.
Common Pitfalls
- Using incompressible Bernoulli above $M \approx 0.3$. Density changes matter; use the isentropic relations instead.
- Forgetting temperature in the sound speed. $a = \sqrt{\gamma R T}$ depends on the local temperature, which itself changes through a nozzle.
- Treating a shock as isentropic. Shocks are adiabatic but raise entropy — stagnation temperature is conserved, but stagnation pressure drops.
- Picking the wrong root of $A/A^$. A given area ratio gives both a subsonic and supersonic Mach number; the nozzle geometry and back pressure decide which one occurs.
- Thinking lower back pressure always increases mass flow. Once the throat chokes ($M=1$), the mass flow is fixed.
Key Takeaways
- The speed of sound $a=\sqrt{\gamma R T}$ and Mach number $M=V/a$ classify the flow regime; compressibility matters above $M\approx0.3$.
- Stagnation properties ($T_0, p_0, \rho_0$) are reached by bringing the flow isentropically to rest and rise with $M^2$.
- The isentropic relations give $T/T_0$, $p/p_0$, $\rho/\rho_0$ as functions of Mach number; sonic conditions need $p/p_0 = 0.528$.
- A converging-diverging nozzle accelerates flow to $M=1$ at the throat (choked), then supersonic in the diverging section; the area-Mach relation has subsonic and supersonic roots.
- A normal shock** turns supersonic flow subsonic, jumping pressure and temperature while losing stagnation pressure.
Next, we open up the full Navier-Stokes equations and take our first step into computational fluid dynamics.