Compressible Flow Basics | Fluid Mechanics with Python | Skill-Lync Resources

50% OFF - Ends Soon!

Lesson 10 of 13 25 min

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

See His Journey

$$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

See All Tools

$$M = \frac{V}{a}$$

Mach rangeRegime
$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

See His Journey

$$\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.

🎯 3,000+ Engineers Placed
Sponsored
Harshal Sukenkar

Harshal

Fiat Chrysler

Abhishek

Abhishek

TATA ELXSI

Srinithin

Srinithin

Xitadel

Ranjith

Ranjith

Core Automotive

Gaurav Jadhav

Gaurav

Automotive Company

Bino K Biju

Bino

Design Firm

Aseem Shrivastava

Aseem

EV Company

Puneet

Puneet

Automotive Company

Vishal Kumar

Vishal

EV Startup

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.

3,000+ Engineers Placed in Top Companies
Career Growth

3,000+ Engineers Placed in Top Companies

Join the ranks of successful engineers at Bosch, Tata, L&T, and 500+ hiring partners.