Compressible flow (gas dynamics)
Virginia Tech AOE 3114 compressible-flow relation set — isentropic flow, normal shock, oblique shock (θ-β-M), Fanno friction flow, and Rayleigh heat-addition flow, in one reference.
Each relation set below includes a Voici11Voici compiles a notebook to a static, serverless dashboard — mocked here as a static page, since this pipeline has no Jupyter kernel to run against. dashboard: a matplotlib-styled chart with the live calculator input marked as a red point on the curve.
2.1 · Isentropic flow relations
$$\frac{T_0}{T}=1+\frac{\gamma-1}{2}M^2,\quad \frac{p_0}{p}=\left(\frac{T_0}{T}\right)^{\frac{\gamma}{\gamma-1}},\quad \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)}}$$
Mach angle $\mu=\arcsin(1/M)$ and Prandtl-Meyer angle $\nu(M)$ defined for $M>1$. Source: Devenport, VT AOE 3114.
| T₀/T | — | |
| p₀/p | — | |
| ρ₀/ρ | — | |
| A/A* | — | |
| Mach angle μ | — | |
| Prandtl-Meyer ν | — |
import numpy as np, matplotlib.pyplot as plt M = np.linspace(0.01, 3, 300) T0_T = 1 + (gamma-1)/2*M**2 plt.plot(M, T0_T); plt.scatter([M_input],[T0_T_input], color='red', zorder=3)
2.2 · Normal shock wave relations
$$M_2^2=\frac{2+(\gamma-1)M_1^2}{2\gamma M_1^2-(\gamma-1)},\quad \frac{p_2}{p_1}=1+\frac{2\gamma}{\gamma+1}(M_1^2-1)$$
$$\frac{p_{02}}{p_{01}}=\left(\frac{(\gamma+1)M_1^2}{(\gamma-1)M_1^2+2}\right)^{\frac{\gamma}{\gamma-1}}\left(\frac{\gamma+1}{2\gamma M_1^2-(\gamma-1)}\right)^{\frac{1}{\gamma-1}}$$
Source: Devenport, VT AOE 3114 Compressible Aerodynamics.
| M₂ | — | |
| p₂/p₁ | — | |
| ρ₂/ρ₁ | — | |
| T₂/T₁ | — | |
| p₀₂/p₀₁ | — |
2.3 · Oblique shock wave relations (θ-β-M)
$$\tan\theta=2\cot\beta\left[\frac{M_1^2\sin^2\beta-1}{M_1^2(\gamma+\cos2\beta)+2}\right]$$
Solved numerically for weak/strong shock angle β given M₁, γ, deflection θ. Source: Devenport, VT AOE 3114.
| β weak | — | |
| β strong | — | |
| M₂ (weak) | — | |
| p₂/p₁ (weak) | — |
import numpy as np, matplotlib.pyplot as plt theta = np.linspace(0.1, theta_max, 200) beta_weak = solve_theta_beta_M(M1, theta, gamma) plt.plot(theta, beta_weak); plt.scatter([theta_input],[beta_input], color='red', zorder=3)
2.4 · Conical shock wave relations (Taylor-Maccoll)
$$\frac{\gamma-1}{2}\left(1-V_r'^2-V_\theta'^2\right)\left(2V_r'+V_\theta'\cot\theta+\frac{dV_\theta'}{d\theta}\right)+V_\theta'\left(V_r'V_\theta'+\frac{dV_\theta'}{d\theta}\right)=0,\quad V_\theta'=\frac{dV_r'}{d\theta}$$
Axisymmetric supersonic flow past a rigid cone: unlike a 2D wedge, streamlines behind the (conical, attached) shock keep turning as they approach the cone surface — the shock angle β, cone half-angle θc, and surface Mach Mc are related through the Taylor-Maccoll ODE, not a closed-form expression. Solved here by shooting: guess β, integrate the ODE pair (V′r, V′θ) from the post-shock state at θ=β inward, and bisect on β until V′θ=0 lands exactly at θ=θc (flow tangent to the cone surface). Source: Virginia Tech AOE 3114 (Devenport); NACA Report 1135 tables for cross-check.
| Shock angle β | — | |
| Surface Mach Mc | — | |
| Surface pressure ratio pc/p₁ | — | |
| Max attached θc at this M₁ | — |
from scipy.integrate import solve_ivp from scipy.optimize import brentq sol = solve_ivp(taylor_maccoll_rhs, [beta, theta_c], [Vr0, Vth0]) beta_solution = brentq(lambda b: theta_at_Vtheta_zero(b) - theta_c_target, mu, beta_max)
2.5 · Fanno flow with friction
$$\frac{4fL^*}{D}=\frac{1-M^2}{\gamma M^2}+\frac{\gamma+1}{2\gamma}\ln\left(\frac{(\gamma+1)M^2}{2+(\gamma-1)M^2}\right)$$
Constant-area adiabatic duct with wall friction; * denotes the sonic (choked) reference state. Source: Devenport, VT AOE 3114.
| 4fL*/D | — | |
| L* max length | — | |
| p/p* | — | |
| T/T* | — | |
| p₀/p₀* | — |
import numpy as np, matplotlib.pyplot as plt M = np.linspace(0.05, 1, 300) fLD = (1-M**2)/(gamma*M**2) + (gamma+1)/(2*gamma)*np.log((gamma+1)*M**2/(2+(gamma-1)*M**2)) plt.plot(M, fLD); plt.scatter([M_input],[fLD_input], color='red', zorder=3)
2.6 · Rayleigh flow with heat transfer
$$\frac{T_0}{T_0^*}=\frac{2(\gamma+1)M^2\left(1+\frac{\gamma-1}{2}M^2\right)}{(1+\gamma M^2)^2},\quad \frac{p}{p^*}=\frac{\gamma+1}{1+\gamma M^2}$$
Constant-area frictionless duct with heat addition/rejection; * denotes the thermally choked (M=1) state. Source: Devenport, VT AOE 3114.
| T₀/T₀* | — | |
| T/T* | — | |
| p/p* | — | |
| p₀/p₀* | — |
import numpy as np, matplotlib.pyplot as plt M = np.linspace(0.05, 3, 300) T_Tstar = M**2 * ((gamma+1)/(1+gamma*M**2))**2 plt.plot(M, T_Tstar); plt.scatter([M_input],[T_Tstar_input], color='red', zorder=3)
2.7 · Air-breathing propulsion cycle
$$F_{\text{spec}}=\sqrt{2c_pT_a\left(\tau_\lambda-\tau_r(\tau_c-1)-\frac{\tau_\lambda}{\tau_r\tau_c}\right)}-V_0,\quad \tau_r=1+\frac{\gamma-1}{2}M_0^2,\quad \tau_c=\pi_c^{\frac{\gamma-1}{\gamma}},\quad \tau_\lambda=\frac{T_{04}}{T_a}$$
Ideal (no losses) turbojet/ramjet Brayton cycle: diffuser and compressor bring station 0 (freestream) to station 3 isentropically, the burner adds heat at constant stagnation pressure to T₀₄, and the turbine/nozzle expand back to ambient. Setting πc=1 reduces this to the ramjet case (no compressor, no turbine). Ta is the ambient static temperature at the flight altitude (ISA troposphere/lower-stratosphere approximation below). Source: Virginia Tech AOE 3114 air-breathing propulsion sub-calculator (Devenport); ideal-cycle formulation per Hill & Peterson, Mechanics and Thermodynamics of Propulsion.
| Ambient Ta (ISA) | — | |
| Specific thrust Fspec | — | |
| TSFC | — | |
| Thermal efficiency ηth | — | |
| Propulsive efficiency ηp | — | |
| Overall efficiency ηo | — |
import numpy as np, matplotlib.pyplot as plt pi_c = np.linspace(1, 40, 200) Fspec, TSFC = ideal_turbojet_cycle(M0, altitude, pi_c, T04, gamma) fig, (ax1, ax2) = plt.subplots(1, 2) ax1.plot(pi_c, Fspec); ax2.plot(pi_c, TSFC*1e6)