engineeringkit.aerodynamics#
Dynamic pressure and force coefficients; Kutta-Joukowski circulation lift;
thin-airfoil theory (with Glauert’s zero-lift and moment integrals by
scipy.integrate.quad), the aerodynamic centre, NACA four-digit sections
and the Hess-Smith panel method; Prandtl’s lifting line, Glauert’s Fourier
solution for any planform, induced drag and the Oswald drag polar; static
longitudinal stability; climb, turn, take-off and the jet and propeller
Breguet range equations; Reynolds similarity and Blasius/Prandtl flat-plate
friction; sound speed, the Mach cone, isentropic stagnation states,
Prandtl-Glauert, normal and oblique shocks, Prandtl-Meyer expansions, the
area-Mach relation, and Fanno and Rayleigh duct flow; and the International
Standard Atmosphere. Models are hand-written closed forms or small linear
solves, because the formula is the subject.
engineeringkit.aerodynamics: from dynamic pressure to finite wings and compressible flow.
Force coefficients and dynamic pressure; Kutta-Joukowski circulation lift; thin-airfoil theory (lift, pitching moment, aerodynamic centre), NACA four-digit sections and the Hess-Smith panel method; Prandtl’s lifting line, with Glauert’s Fourier solution for any planform, induced drag and the parabolic drag polar; static longitudinal stability; climb, turn, take-off and jet and propeller Breguet range; Reynolds-number similarity and Blasius/Prandtl flat-plate boundary layers; perfect-gas sound speed, isentropic stagnation states, the Mach cone, Prandtl-Glauert, Rankine-Hugoniot normal shocks, oblique shocks, Prandtl-Meyer expansions, the de Laval area-Mach relation, and Fanno and Rayleigh duct flow; and the International Standard Atmosphere. Models are hand-written closed forms or small linear solves (the formula is the pedagogical subject); SciPy is used only for quadrature and the inverse Prandtl-Meyer root.
- class engineeringkit.aerodynamics.Airfoil(name, x, camber, thickness, upper, lower)[source]#
Bases:
objectCoordinates of an airfoil section on a unit chord.
All coordinates are fractions of the chord
c; multiply byc[m] for physical dimensions.- Parameters:
name (str)
x (ndarray)
camber (ndarray)
thickness (ndarray)
upper (ndarray)
lower (ndarray)
- camber: ndarray#
Mean-camber-line ordinate at each station.
- Type:
ndarray
- lower: ndarray#
Lower-surface points, shape
(n, 2).- Type:
ndarray
- name: str#
Section designation, e.g.
"NACA 2412".- Type:
str
- summary()[source]#
Maximum thickness and camber (fractions of chord) and their locations.
- Return type:
dict
- thickness: ndarray#
Half-thickness at each station.
- Type:
ndarray
- upper: ndarray#
Upper-surface points, shape
(n, 2).- Type:
ndarray
- x: ndarray#
Chordwise stations of the mean camber line, from 0 to 1.
- Type:
ndarray
- class engineeringkit.aerodynamics.AtmosphereState(altitude, temperature, pressure, density, speed_of_sound)[source]#
Bases:
objectThermodynamic state of the standard atmosphere at a geometric altitude.
- Parameters:
altitude (ndarray)
temperature (ndarray)
pressure (ndarray)
density (ndarray)
speed_of_sound (ndarray)
- altitude: ndarray#
Altitude above mean sea level [m].
- Type:
ndarray
- density: ndarray#
Density [kg/m^3].
- Type:
ndarray
- pressure: ndarray#
Static pressure [Pa].
- Type:
ndarray
- speed_of_sound: ndarray#
Speed of sound [m/s].
- Type:
ndarray
- summary()[source]#
Sea-level-relative density and pressure at the highest altitude.
- Return type:
dict
- temperature: ndarray#
Static temperature [K].
- Type:
ndarray
- class engineeringkit.aerodynamics.DuctFlowState(kind, mach, temperature_ratio, pressure_ratio, density_ratio, stagnation_pressure_ratio, stagnation_temperature_ratio, friction_parameter)[source]#
Bases:
objectFanno or Rayleigh flow state relative to the sonic (starred) reference state.
Every ratio is the local value divided by the value at \(M = 1\) on the same Fanno or Rayleigh line.
- Parameters:
kind (str)
mach (ndarray)
temperature_ratio (ndarray)
pressure_ratio (ndarray)
density_ratio (ndarray)
stagnation_pressure_ratio (ndarray)
stagnation_temperature_ratio (ndarray)
friction_parameter (ndarray)
- density_ratio: ndarray#
\(\rho/\rho^*\) [-]; also \(V^*/V\) by continuity.
- Type:
ndarray
- friction_parameter: ndarray#
\(f L^*/D\) [-] (Darcy friction factor) to reach \(M = 1\); zero for Rayleigh flow.
- Type:
ndarray
- kind: str#
"fanno"(adiabatic flow with friction) or"rayleigh"(frictionless flow with heat addition).- Type:
str
- mach: ndarray#
Mach number [-].
- Type:
ndarray
- pressure_ratio: ndarray#
\(p/p^*\) [-].
- Type:
ndarray
- stagnation_pressure_ratio: ndarray#
\(p_0/p_0^*\) [-].
- Type:
ndarray
- stagnation_temperature_ratio: ndarray#
\(T_0/T_0^*\) [-]; identically one for Fanno flow.
- Type:
ndarray
- temperature_ratio: ndarray#
\(T/T^*\) [-].
- Type:
ndarray
- class engineeringkit.aerodynamics.LiftingLineResult(span, area, aspect_ratio, coefficients, y, chord, cl, induced_angle, circulation_per_speed, CL, CDi, span_efficiency)[source]#
Bases:
objectGlauert’s Fourier solution of Prandtl’s lifting-line equation for one wing.
- Parameters:
span (float)
area (float)
aspect_ratio (float)
coefficients (ndarray)
y (ndarray)
chord (ndarray)
cl (ndarray)
induced_angle (ndarray)
circulation_per_speed (ndarray)
CL (float)
CDi (float)
span_efficiency (float)
- CDi: float#
Induced drag coefficient \(\pi AR \sum n A_n^2\) [-].
- Type:
float
- CL: float#
Wing lift coefficient \(\pi AR A_1\) [-].
- Type:
float
- area: float#
Planform area [m^2].
- Type:
float
- aspect_ratio: float#
Aspect ratio \(b^2/S\) [-].
- Type:
float
- chord: ndarray#
Chord at each station [m].
- Type:
ndarray
- circulation_per_speed: ndarray#
\(\Gamma/V_\infty = \tfrac12 c\,c_l\) at each station [m].
- Type:
ndarray
- cl: ndarray#
Section lift coefficient at each station [-].
- Type:
ndarray
- coefficients: ndarray#
Fourier coefficients \(A_1 \ldots A_N\) of the circulation [-].
- Type:
ndarray
- induced_angle: ndarray#
Downwash angle \(\alpha_i\) at each station [rad].
- Type:
ndarray
- plot(ax=None)[source]#
Plot the spanwise lift distribution against the elliptic one; return
(fig, ax).
- span: float#
Wing span [m].
- Type:
float
- span_efficiency: float#
Span efficiency \(e = C_L^2/(\pi AR C_{D,i})\) [-]; NaN at zero lift and drag.
- Type:
float
- summary()[source]#
Wing coefficients, span efficiency and the largest section lift coefficient.
- Return type:
dict
- y: ndarray#
Spanwise collocation stations, from the left tip to the right [m].
- Type:
ndarray
- class engineeringkit.aerodynamics.ObliqueShockResult(mach1, theta, beta, mach2, pressure_ratio, density_ratio, temperature_ratio, stagnation_pressure_ratio, gamma, strong)[source]#
Bases:
objectState change across an attached oblique shock in a perfect gas.
- Parameters:
mach1 (float)
theta (float)
beta (float)
mach2 (float)
pressure_ratio (float)
density_ratio (float)
temperature_ratio (float)
stagnation_pressure_ratio (float)
gamma (float)
strong (bool)
- beta: float#
Shock-wave angle measured from the upstream flow [rad].
- Type:
float
- density_ratio: float#
Density ratio \(\rho_2/\rho_1\) [-].
- Type:
float
- gamma: float#
Ratio of specific heats [-].
- Type:
float
- mach1: float#
Upstream Mach number [-].
- Type:
float
- mach2: float#
Downstream Mach number [-].
- Type:
float
- plot(ax=None)[source]#
Mark this shock on the theta-beta-M chart for its Mach number; return
(fig, ax).
- pressure_ratio: float#
Static pressure ratio \(p_2/p_1\) [-].
- Type:
float
- stagnation_pressure_ratio: float#
Total pressure ratio \(p_{02}/p_{01}\) [-], at most one.
- Type:
float
- strong: bool#
Truefor the strong-shock branch,Falsefor the weak one.- Type:
bool
- temperature_ratio: float#
Static temperature ratio \(T_2/T_1\) [-].
- Type:
float
- theta: float#
Flow deflection (wedge half-angle) [rad].
- Type:
float
- class engineeringkit.aerodynamics.PanelResult(nodes, x, y, tangential_velocity, cp, source_strengths, vortex_strength, alpha, chord, cl, cl_pressure, cm_quarter_chord)[source]#
Bases:
objectHess-Smith panel solution for a two-dimensional body in a uniform stream.
Lengths are in units of the input coordinates; the coefficients are referred to the chord, the
xextent of the body.- Parameters:
nodes (ndarray)
x (ndarray)
y (ndarray)
tangential_velocity (ndarray)
cp (ndarray)
source_strengths (ndarray)
vortex_strength (float)
alpha (float)
chord (float)
cl (float)
cl_pressure (float)
cm_quarter_chord (float)
- alpha: float#
Angle of attack [rad].
- Type:
float
- chord: float#
Chord, the
xextent of the nodes.- Type:
float
- cl: float#
Lift coefficient from the circulation, \(2\Gamma/(V_\infty c)\) [-].
- Type:
float
- cl_pressure: float#
Lift coefficient from integrating the surface pressure [-].
- Type:
float
- cm_quarter_chord: float#
Pitching moment about the quarter chord from the surface pressure, nose up positive [-].
- Type:
float
- cp: ndarray#
Pressure coefficient \(1 - (V_t/V_\infty)^2\) at each control point [-].
- Type:
ndarray
- nodes: ndarray#
Panel end points, shape
(N + 1, 2), clockwise from the trailing edge.- Type:
ndarray
- source_strengths: ndarray#
Source strength per unit length on each panel, divided by \(V_\infty\) [-].
- Type:
ndarray
- tangential_velocity: ndarray#
Surface speed \(V_t/V_\infty\) along each panel’s clockwise tangent [-].
- Type:
ndarray
- vortex_strength: float#
Uniform vortex-sheet strength (clockwise positive), divided by \(V_\infty\) [-].
- Type:
float
- x: ndarray#
Panel control points (midpoints),
xcoordinates.- Type:
ndarray
- y: ndarray#
Panel control points (midpoints),
ycoordinates.- Type:
ndarray
- engineeringkit.aerodynamics.aerodynamic_center(a0, m0)[source]#
Chordwise position of the aerodynamic centre, \(x_{ac}/c = \tfrac14 - m_0/a_0\).
The aerodynamic centre is the point about which the pitching moment does not change with angle of attack.
- Parameters:
a0 (float or array_like) – Section lift-curve slope \(dc_l/d\alpha\) [1/rad], positive.
m0 (float or array_like) – Slope of the quarter-chord moment coefficient, \(dc_{m,c/4}/d\alpha\) [1/rad]; zero in thin-airfoil theory.
- Returns:
Aerodynamic-centre position as a fraction of chord from the leading edge [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
J. D. Anderson, Fundamentals of Aerodynamics, 6th ed. (McGraw-Hill, 2017), sec. 4.9.
Examples
>>> round(float(aerodynamic_center(6.0, -0.06)), 4) 0.26
- engineeringkit.aerodynamics.area_mach_ratio(M, gamma=1.4)[source]#
Isentropic area ratio \(A/A^*\) of a quasi-one-dimensional nozzle.
\[\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)}}\]- Parameters:
M (float or array_like) – Mach number [-], positive.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Area relative to the sonic throat [-]; one at \(M = 1\). Each ratio above one corresponds to one subsonic and one supersonic Mach number; this function does not invert.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(area_mach_ratio(2.0)), 4) 1.6875
- engineeringkit.aerodynamics.aspect_ratio(span, area)[source]#
Wing aspect ratio \(AR = b^2 / S\).
- Parameters:
span (float or array_like) – Wing span [m], positive.
area (float or array_like) – Planform area [m^2], positive.
- Returns:
Aspect ratio [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(aspect_ratio(10.0, 20.0)) 5.0
- engineeringkit.aerodynamics.best_glide_cl(Cd0, AR, e=1.0)[source]#
Lift coefficient of maximum \(L/D\) for a parabolic polar, \(\sqrt{\pi e AR C_{D0}}\).
At this point induced drag equals parasite drag, so \((L/D)_{\max} = \tfrac12\sqrt{\pi e AR / C_{D0}}\).
- Parameters:
Cd0 (float or array_like) – Zero-lift drag coefficient [-], positive.
AR (float or array_like) – Aspect ratio [-], positive.
e (float or array_like, optional) – Oswald efficiency factor [-] in
(0, 1].
- Returns:
Lift coefficient for best glide [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(best_glide_cl(0.02, 8.0, 0.8)), 4) 0.6341
- engineeringkit.aerodynamics.boundary_layer_laminar(x, Re_x)[source]#
Laminar boundary-layer thickness \(\delta \approx 5x/\sqrt{Re_x}\).
- Parameters:
x (float or array_like) – Distance from the leading edge [m], nonnegative.
Re_x (float or array_like) – Local Reynolds number \(\rho V x/\mu\) [-], positive.
- Returns:
99%-velocity thickness [m] (Blasius gives 4.91; 5 is the textbook rounding).
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(boundary_layer_laminar(1.0, 1e6)), 6) 0.005
- engineeringkit.aerodynamics.breguet_range(V, tsfc, lift_to_drag, W_initial, W_final, g=9.80665)[source]#
Jet-aircraft cruise range \(R = \dfrac{V}{g\,c_T}\dfrac{L}{D}\ln\dfrac{W_i}{W_f}\) (Breguet).
Integrates \(dR = V\,dt\) while fuel burns at \(\dot m = c_T T\) and thrust equals drag, \(T = W/(L/D)\), at constant speed and lift-to-drag ratio.
- Parameters:
V (float or array_like) – Cruise true airspeed [m/s], positive.
tsfc (float or array_like) – Thrust-specific fuel consumption [kg/(N s)], positive (e.g.
1.6e-5for a modern turbofan).lift_to_drag (float or array_like) – Cruise lift-to-drag ratio [-], positive.
W_initial (float or array_like) – Weight at the start and end of cruise [N], with
W_initial >= W_final > 0.W_final (float or array_like) – Weight at the start and end of cruise [N], with
W_initial >= W_final > 0.g (float, optional) – Gravitational acceleration [m/s^2].
- Returns:
Still-air range [m].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
J. D. Anderson, Aircraft Performance and Design (McGraw-Hill, 1999), sec. 5.13, for the derivation of the range equation attributed to Louis Breguet.
Examples
>>> round(float(breguet_range(230.0, 1.6e-5, 18.0, 7.0e5, 5.0e5)) / 1e3) 8878
- engineeringkit.aerodynamics.breguet_range_propeller(eta_prop, psfc, lift_to_drag, W_initial, W_final, g=9.80665)[source]#
Propeller-aircraft cruise range \(R = \dfrac{\eta_{pr}}{g\,c_P}\dfrac{L}{D}\ln\dfrac{W_i}{W_f}\) (Breguet).
Shaft power \(P = DV/\eta_{pr}\) burns fuel at \(\dot m = c_P P\) and drag is \(W/(L/D)\), so the speed cancels: a propeller aircraft’s range depends on speed only through \(L/D\).
- Parameters:
eta_prop (float or array_like) – Propeller efficiency [-], in
(0, 1].psfc (float or array_like) – Power-specific fuel consumption [kg/(W s)], positive (
7.6e-8, about 0.45 lb/(hp h), for a piston engine).lift_to_drag (float or array_like) – Cruise lift-to-drag ratio [-], positive.
W_initial (float or array_like) – Weight at the start and end of cruise [N], with
W_initial >= W_final > 0.W_final (float or array_like) – Weight at the start and end of cruise [N], with
W_initial >= W_final > 0.g (float, optional) – Gravitational acceleration [m/s^2].
- Returns:
Still-air range [m]; largest at the maximum-\(L/D\) speed.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
J. D. Anderson, Introduction to Flight, 8th ed. (McGraw-Hill, 2016), sec. 6.12.
Examples
>>> round(float(breguet_range_propeller(0.8, 7.6e-8, 13.6, 13.1e3, 11.7e3)) / 1e3) 1650
- engineeringkit.aerodynamics.climb_angle(thrust, drag, weight)[source]#
Steady climb angle \(\gamma = \arcsin\left[(T - D)/W\right]\).
- Parameters:
thrust (float or array_like) – Thrust available [N], nonnegative.
drag (float or array_like) – Drag [N], nonnegative.
weight (float or array_like) – Aircraft weight [N], positive, with \(|T - D| \le W\).
- Returns:
Flight-path angle [rad].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(np.degrees(climb_angle(3000.0, 1500.0, 15000.0))), 3) 5.739
- engineeringkit.aerodynamics.downwash_gradient(a_w, AR)[source]#
Downwash gradient at the tail, \(d\varepsilon/d\alpha = 2a_w/(\pi AR)\).
Far behind an elliptically loaded wing the downwash angle is \(\varepsilon = 2C_L/(\pi AR)\), twice its value at the wing.
- Parameters:
a_w (float or array_like) – Wing lift-curve slope [1/rad], positive.
AR (float or array_like) – Wing aspect ratio [-], positive.
- Returns:
\(d\varepsilon/d\alpha\) [-].
- Return type:
float or ndarray
Notes
A far-wake estimate; a tail close behind the wing sees less. Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(downwash_gradient(4.8, 8.0)), 4) 0.382
- engineeringkit.aerodynamics.drag(q, S, Cd)[source]#
Drag force \(D = q S C_D\).
- Parameters:
q (float or array_like) – Dynamic pressure [Pa], nonnegative.
S (float or array_like) – Reference area [m^2], positive.
Cd (float or array_like) – Drag coefficient [-], nonnegative.
- Returns:
Drag [N], parallel to the free stream.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; assumptions and validity limits are in Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(drag(1500.0, 2.0, 0.02)) 60.0
- engineeringkit.aerodynamics.drag_coefficient(D, rho, V, S)[source]#
Drag coefficient \(C_D = D / (q S)\) from a measured drag force.
- Parameters:
D (float or array_like) – Drag [N], nonnegative.
rho (float or array_like) – Density [kg/m^3], positive.
V (float or array_like) – Speed [m/s], positive.
S (float or array_like) – Reference area [m^2], positive.
- Returns:
Drag coefficient [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; assumptions and validity limits are in Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(drag_coefficient(60.0, 1.2, 50.0, 2.0)) 0.02
- engineeringkit.aerodynamics.drag_polar(Cl, Cd0, AR, e=1.0)[source]#
Parabolic drag polar \(C_D = C_{D0} + C_L^2/(\pi e AR)\).
- Parameters:
Cl (float or array_like) – Lift coefficient [-].
Cd0 (float or array_like) – Zero-lift (parasite) drag coefficient [-], nonnegative.
AR (float or array_like) – Aspect ratio [-], positive.
e (float or array_like, optional) – Oswald efficiency factor [-] in
(0, 1].
- Returns:
Total drag coefficient [-].
- Return type:
float or ndarray
Notes
Compressibility and Reynolds-number variation of \(C_{D0}\) are not modelled. Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(drag_polar(0.5, 0.02, 8.0, 0.8)), 6) 0.032434
- engineeringkit.aerodynamics.dynamic_pressure(rho, V)[source]#
Dynamic pressure \(q = \tfrac12 \rho V^2\).
Bernoulli’s kinetic-energy term per unit volume: the pressure rise available when a stream is brought to rest without losses.
- Parameters:
rho (float or array_like) – Fluid density [kg/m^3], positive.
V (float or array_like) – Flow speed [m/s], nonnegative.
- Returns:
Dynamic pressure [Pa].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; assumptions and validity limits are in Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(dynamic_pressure(1.2, 50.0)) 1500.0
- engineeringkit.aerodynamics.fanno_choking_length(M, D, f, gamma=1.4)[source]#
Duct length \(L^*\) over which friction brings the flow to \(M = 1\).
- Parameters:
M (float or array_like) – Inlet Mach number [-], positive.
D (float or array_like) – Hydraulic diameter [m], positive.
f (float or array_like) – Darcy friction factor [-], positive (for example from
engineeringkit.fluid_engineering.colebrook_friction_factor()).gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Choking length [m]. A longer duct cannot pass the same mass flow: subsonic inlet flow is throttled and supersonic flow shocks.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(fanno_choking_length(0.5, 0.05, 0.02)), 4) 2.6727
- engineeringkit.aerodynamics.fanno_flow(M, gamma=1.4)[source]#
Fanno-line ratios of adiabatic flow with wall friction in a constant-area duct.
\[\frac{T}{T^*} = \frac{\gamma+1}{2 + (\gamma-1)M^2},\qquad \frac{p}{p^*} = \frac1M\sqrt{\frac{T}{T^*}},\qquad \frac{f L^*}{D} = \frac{1 - M^2}{\gamma M^2} + \frac{\gamma+1}{2\gamma}\ln\frac{(\gamma+1)M^2}{2 + (\gamma-1)M^2}\]- Parameters:
M (float or array_like) – Mach number [-], positive.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Ratios to the sonic state, including the friction parameter \(f L^*/D\) with the Darcy friction factor \(f\) (four times the Fanning factor, so this is the \(4 f_F L^*/D\) of Fanning-factor tables).
- Return type:
Notes
Friction drives subsonic flow up and supersonic flow down towards \(M = 1\), while \(T_0\) stays constant and \(p_0\) falls. Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
J. D. Anderson, Modern Compressible Flow, 3rd ed. (McGraw-Hill, 2003), sec. 3.9, after G. Fanno’s 1904 diploma thesis at the ETH Zürich.
Examples
>>> state = fanno_flow(2.0) >>> round(float(state.friction_parameter), 5), round(float(state.pressure_ratio), 5) (0.305, 0.40825)
- engineeringkit.aerodynamics.finite_wing_cl(alpha_rad, AR, e=1.0, alpha_l0=0.0)[source]#
Wing lift coefficient \(C_L = a(\alpha - \alpha_{L=0})\) with the lifting-line slope.
- Parameters:
alpha_rad (float or array_like) – Angle of attack [rad].
AR (float or array_like) – Aspect ratio [-], positive.
e (float, optional) – Span efficiency factor [-] in
(0, 1].alpha_l0 (float, optional) – Zero-lift angle [rad].
- Returns:
Wing lift coefficient [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(finite_wing_cl(0.1, 8.0)), 5) 0.50265
- engineeringkit.aerodynamics.finite_wing_lift_slope(AR, e=1.0, a0=6.283185307179586)[source]#
Lifting-line lift-curve slope \(a = a_0 / (1 + a_0/(\pi e AR))\).
- Parameters:
AR (float or array_like) – Aspect ratio [-], positive.
e (float or array_like, optional) – Span efficiency factor [-] in
(0, 1].a0 (float, optional) – Two-dimensional section lift slope [1/rad]; \(2\pi\) from thin-airfoil theory.
- Returns:
Wing lift-curve slope [1/rad]; tends to
a0asARgrows.- Return type:
float or ndarray
Notes
Valid for unswept, moderate-to-high aspect-ratio wings in attached incompressible flow. Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(finite_wing_lift_slope(8.0)), 4) 5.0265
- engineeringkit.aerodynamics.glide_ratio(Cl, Cd)[source]#
Lift-to-drag ratio \(L/D = C_L/C_D\), the still-air glide distance per unit height lost.
- Parameters:
Cl (float or array_like) – Lift coefficient [-].
Cd (float or array_like) – Drag coefficient [-], positive.
- Returns:
Glide ratio [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(glide_ratio(0.8, 0.05)) 16.0
- engineeringkit.aerodynamics.induced_drag_coefficient(Cl, AR, e=1.0)[source]#
Induced (vortex) drag coefficient \(C_{D,i} = C_L^2/(\pi e AR)\).
- Parameters:
Cl (float or array_like) – Wing lift coefficient [-].
AR (float or array_like) – Aspect ratio [-], positive.
e (float or array_like, optional) – Span efficiency factor [-] in
(0, 1]; one for an elliptic load.
- Returns:
Induced drag coefficient [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
Prandtl, “Tragflügeltheorie,” Nachr. Ges. Wiss. Göttingen (1918).
Examples
>>> round(float(induced_drag_coefficient(0.5, 8.0)), 6) 0.009947
- engineeringkit.aerodynamics.inverse_prandtl_meyer(nu, gamma=1.4)[source]#
Mach number whose Prandtl-Meyer angle is \(\nu\), found by a bracketing root search.
- Parameters:
nu (float or array_like) – Prandtl-Meyer angle [rad], nonnegative and below the limit \(\tfrac{\pi}{2}(\sqrt{(\gamma+1)/(\gamma-1)} - 1)\) (130.45° for \(\gamma = 1.4\)).
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Mach number [-], at least one.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(inverse_prandtl_meyer(np.radians(26.38))), 4) 2.0
- engineeringkit.aerodynamics.isa_atmosphere(altitude)[source]#
Standard-atmosphere temperature, pressure, density and sound speed.
\[T = T_0 - L h,\quad p = p_0 (T/T_0)^{g_0/(R L)} \quad (h \le 11\,\mathrm{km}), \qquad p = p_{11}\, e^{-g_0 (h - 11\,\mathrm{km})/(R T_{11})} \quad (11 < h \le 20\,\mathrm{km})\]- Parameters:
altitude (float or array_like) – Geopotential altitude [m] in
[0, 20000].- Return type:
Notes
Sea-level values are 288.15 K, 101325 Pa and 1.225 kg/m^3 with a lapse rate of 6.5 K/km. Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
ISO 2533:1975, Standard Atmosphere; ICAO Doc 7488 (1952).
Examples
>>> state = isa_atmosphere(11000.0) >>> round(float(state.temperature), 2), round(float(state.pressure)) (216.65, 22632)
- engineeringkit.aerodynamics.isentropic_factor(M, gamma=1.4)[source]#
Stagnation-to-static temperature ratio \(1 + \tfrac{\gamma-1}{2}M^2\).
Every isentropic relation (stagnation temperature and pressure, the area-Mach relation) is a power of this one factor.
- Parameters:
M (float or array_like) – Mach number [-], nonnegative.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
\(T_0/T\) [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(isentropic_factor(1.0)) 1.2
- engineeringkit.aerodynamics.kutta_joukowski_lift(rho, V, circulation)[source]#
Lift per unit span \(L' = \rho V \Gamma\) (Kutta-Joukowski theorem).
Any two-dimensional body in a steady inviscid stream carries a lift per unit span proportional to the circulation \(\Gamma\) around it, and no drag (d’Alembert).
- Parameters:
rho (float or array_like) – Density [kg/m^3], positive.
V (float or array_like) – Free-stream speed [m/s], nonnegative.
circulation (float or array_like) – Circulation \(\Gamma\) [m^2/s]; positive for clockwise flow about a body in a stream moving in the +x direction.
- Returns:
Lift per unit span [N/m].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; assumptions and validity limits are in Aerodynamics: incompressible limits and compressible conservation.
References
Kutta, Illustrierte Aeronautische Mitteilungen 6 (1902);
Joukowski, Bull. Inst. Aérodyn. Koutchino 1 (1906).
Examples
>>> float(kutta_joukowski_lift(1.2, 50.0, 10.0)) 600.0
- engineeringkit.aerodynamics.lift(q, S, Cl)[source]#
Lift force \(L = q S C_L\).
- Parameters:
q (float or array_like) – Dynamic pressure [Pa], nonnegative.
S (float or array_like) – Reference (wing planform) area [m^2], positive.
Cl (float or array_like) – Lift coefficient [-]; signed.
- Returns:
Lift [N], perpendicular to the free stream.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; assumptions and validity limits are in Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(lift(1500.0, 2.0, 0.5)) 1500.0
- engineeringkit.aerodynamics.lift_coefficient(L, rho, V, S)[source]#
Lift coefficient \(C_L = L / (q S)\) from a measured lift force.
- Parameters:
L (float or array_like) – Lift [N]; signed.
rho (float or array_like) – Density [kg/m^3], positive.
V (float or array_like) – Speed [m/s], positive.
S (float or array_like) – Reference area [m^2], positive.
- Returns:
Lift coefficient [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; assumptions and validity limits are in Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(lift_coefficient(1500.0, 1.2, 50.0, 2.0)) 0.5
- engineeringkit.aerodynamics.lifting_line(span, chord, alpha, alpha_l0=0.0, a0=6.283185307179586, n_terms=40)[source]#
Spanwise lift distribution, lift and induced drag of an unswept wing.
- Parameters:
span (float) – Wing span \(b\) [m], positive.
chord (float or callable) – Chord [m], positive: a constant, or a function of the spanwise station
y[m] in \([-b/2, b/2]\) that accepts arrays.alpha (float or callable) – Geometric angle of attack [rad], a constant or a function of
y(washout makes it fall towards the tips).alpha_l0 (float or callable, optional) – Section zero-lift angle [rad], a constant or a function of
y.a0 (float, optional) – Section lift-curve slope [1/rad], positive; \(2\pi\) from thin-airfoil theory.
n_terms (int, optional) – Number of Fourier terms and collocation stations, at least one.
- Returns:
Fourier coefficients, the section lift and downwash at each collocation station, and the wing \(C_L\), \(C_{D,i}\) and span efficiency.
- Return type:
Notes
Attached, incompressible flow over a straight wing of moderate to large aspect ratio; sweep, stall and the root and tip corrections of lifting-surface theory are not modelled. All harmonics are kept, so asymmetric twist (aileron deflection) is allowed. Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
H. Glauert, The Elements of Aerofoil and Airscrew Theory (Cambridge University Press, 1926), ch. 11; J. D. Anderson, Fundamentals of Aerodynamics, 6th ed. (McGraw-Hill, 2017), sec. 5.3.
Examples
>>> wing = lifting_line(10.0, lambda y: 1.25 * np.sqrt(1 - (2 * y / 10.0) ** 2), 0.1) >>> round(wing.span_efficiency, 6), round(wing.CL, 5) (1.0, 0.5252)
- engineeringkit.aerodynamics.load_factor(bank_angle)[source]#
Load factor of a level, coordinated turn, \(n = L/W = 1/\cos\phi\).
- Parameters:
bank_angle (float or array_like) – Bank angle \(\phi\) [rad], in
[0, pi/2).- Returns:
Load factor [-]; 2 at a 60° bank.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(load_factor(np.radians(60.0))), 6) 2.0
- engineeringkit.aerodynamics.mach_angle(M)[source]#
Half-angle of the Mach cone, \(\mu = \arcsin(1/M)\).
- Parameters:
M (float or array_like) – Mach number [-], at least one.
- Returns:
Mach angle [rad]; \(\pi/2\) at \(M = 1\).
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
E. Mach and P. Salcher, “Photographische Fixirung der durch Projectile in der Luft eingeleiteten Vorgänge,” Sitzungsber. Akad. Wiss. Wien 95 (1887).
Examples
>>> round(float(np.degrees(mach_angle(2.0))), 6) 30.0
- engineeringkit.aerodynamics.mach_number(V, a)[source]#
Mach number \(M = V/a\).
- Parameters:
V (float or array_like) – Flow speed [m/s], nonnegative.
a (float or array_like) – Speed of sound [m/s], positive.
- Returns:
Mach number [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> float(mach_number(170.0, 340.0)) 0.5
- engineeringkit.aerodynamics.naca4_airfoil(designation, n=101, closed_trailing_edge=False)[source]#
Coordinates of a NACA four-digit section on a unit chord.
The half-thickness is
\[y_t = 5t\,(0.2969\sqrt{x} - 0.1260x - 0.3516x^2 + 0.2843x^3 - 0.1015x^4),\]and the surfaces are offset from the camber line along its normal. Stations are cosine-spaced to resolve the leading edge.
- Parameters:
designation (
str) – Four digits, e.g."0012"or"2412".n (
int) – Number of chordwise stations, at least 3.closed_trailing_edge (
bool) – Use-0.1036instead of-0.1015for the quartic coefficient so the trailing edge has zero thickness.
- Return type:
Notes
Coordinates are fractions of chord; see Aerodynamics: incompressible limits and compressible conservation.
References
E. N. Jacobs, K. E. Ward and R. M. Pinkerton, “The characteristics of 78 related airfoil sections from tests in the variable-density wind tunnel,” NACA Report 460 (1933).
Examples
>>> foil = naca4_airfoil("2412") >>> round(foil.summary()["max_thickness"], 3) 0.12
- engineeringkit.aerodynamics.naca4_moment_coefficient(m, p)[source]#
Thin-airfoil quarter-chord pitching moment of a NACA four-digit camber line.
Glauert’s Fourier coefficients of the camber-line slope,
\[A_n = \frac{2}{\pi}\int_0^\pi \frac{dz}{dx}(\theta)\cos n\theta\,d\theta,\]give \(c_{m,c/4} = \tfrac{\pi}{4}(A_2 - A_1)\), which does not depend on the angle of attack: the quarter chord is the thin-airfoil aerodynamic centre.
- Parameters:
m (float) – Maximum camber as a fraction of chord, in
[0, 0.095](first digit / 100).p (float) – Position of maximum camber as a fraction of chord, in
(0, 1)(second digit / 10).
- Returns:
Moment coefficient about the quarter chord [-], nose up positive; negative for positive camber and zero for a symmetric section.
- Return type:
float
Notes
The moment about the leading edge follows as \(c_{m,le} = c_{m,c/4} - c_l/4\). Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
J. D. Anderson, Fundamentals of Aerodynamics, 6th ed. (McGraw-Hill, 2017), sec. 4.8 and example 4.6.
Examples
>>> round(float(naca4_moment_coefficient(0.02, 0.4)), 4) -0.0531
- engineeringkit.aerodynamics.naca4_zero_lift_angle(m, p)[source]#
Thin-airfoil zero-lift angle of a NACA four-digit camber line.
Glauert’s integral
\[\alpha_{L=0} = -\frac{1}{\pi}\int_0^\pi \frac{dz}{dx}(\theta)\,(\cos\theta - 1)\,d\theta, \qquad x = \tfrac12(1-\cos\theta),\]is evaluated numerically for the two-parabola camber line with maximum camber
mat chordwise positionp.- Parameters:
m (float) – Maximum camber as a fraction of chord, in
[0, 0.095](first digit / 100).p (float) – Position of maximum camber as a fraction of chord, in
(0, 1)(second digit / 10).
- Returns:
Zero-lift angle of attack [rad]; zero for
m = 0.- Return type:
float
Notes
mandpare scalar-only: each camber line needs its own quadrature.Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(np.degrees(naca4_zero_lift_angle(0.02, 0.4))), 2) -2.08
- engineeringkit.aerodynamics.neutral_point(h_ac_wb, a_wb, a_t, V_H, deps_dalpha=0.0, eta=1.0)[source]#
Stick-fixed neutral point \(h_n = h_{ac,wb} + \eta V_H \frac{a_t}{a_{wb}}\left(1 - \frac{d\varepsilon}{d\alpha}\right)\).
- Parameters:
h_ac_wb (float or array_like) – Wing-body aerodynamic centre as a fraction of the mean chord from its leading edge [-].
a_wb (float or array_like) – Wing-body lift-curve slope [1/rad], positive.
a_t (float or array_like) – Tail lift-curve slope [1/rad], positive.
V_H (float or array_like) – Tail volume ratio [-], positive (
tail_volume_ratio()).deps_dalpha (float or array_like, optional) – Downwash gradient at the tail [-] in
[0, 1)(downwash_gradient()).eta (float or array_like, optional) – Tail efficiency, the tail-to-free-stream dynamic-pressure ratio [-], in
(0, 1].
- Returns:
Neutral point as a fraction of the mean chord [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
J. D. Anderson, Introduction to Flight, 8th ed. (McGraw-Hill, 2016), secs. 7.5-7.10.
Examples
>>> round(float(neutral_point(0.24, 4.8, 4.0, 0.6, 0.38)), 4) 0.55
- engineeringkit.aerodynamics.normal_shock_mach2(M1, gamma=1.4)[source]#
Downstream Mach number of a normal shock.
\[M_2^2 = \frac{1 + \tfrac{\gamma-1}{2}M_1^2}{\gamma M_1^2 - \tfrac{\gamma-1}{2}}\]- Parameters:
M1 (float or array_like) – Upstream Mach number [-], at least one.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Downstream Mach number [-], at most one.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
W. J. M. Rankine, Phil. Trans. R. Soc. 160 (1870) 277-288; H. Hugoniot, J. École Polytech. 57 (1887) 3-97; 58 (1889) 1-125.
Examples
>>> round(float(normal_shock_mach2(2.0)), 6) 0.57735
- engineeringkit.aerodynamics.normal_shock_pressure_ratio(M1, gamma=1.4)[source]#
Static pressure ratio across a normal shock, \(p_2/p_1 = 1 + \tfrac{2\gamma}{\gamma+1}(M_1^2 - 1)\).
- Parameters:
M1 (float or array_like) – Upstream Mach number [-], at least one.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Pressure ratio [-], at least one.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(normal_shock_pressure_ratio(2.0)), 6) 4.5
- engineeringkit.aerodynamics.oblique_shock(M1, theta, gamma=1.4, strong=False)[source]#
Downstream state of an attached oblique shock.
The velocity component normal to the wave, \(M_{n1} = M_1\sin\beta\), passes through a normal shock; the tangential component is unchanged, so \(M_2 = M_{n2}/\sin(\beta - \theta)\).
- Parameters:
M1 (float) – Upstream Mach number [-], greater than one.
theta (float) – Deflection angle [rad], positive and at most the maximum deflection.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
strong (bool, optional) – Use the strong-shock branch instead of the weak one.
- Returns:
Wave angle, downstream Mach number and the static and stagnation ratios across the shock.
- Return type:
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> shock = oblique_shock(2.0, np.radians(20.0)) >>> round(shock.mach2, 3), round(shock.pressure_ratio, 3) (1.21, 2.843)
- engineeringkit.aerodynamics.oblique_shock_angle(M1, theta, gamma=1.4, strong=False)[source]#
Wave angle \(\beta\) of the attached oblique shock that turns a stream by \(\theta\).
Solves the \(\theta\)-\(\beta\)-\(M\) relation, a cubic in \(\tan\beta\), in closed form:
\[\tan\beta = \frac{M_1^2 - 1 + 2\lambda\cos\left[(4\pi\delta + \cos^{-1}\chi)/3\right]} {3\left(1 + \tfrac{\gamma-1}{2}M_1^2\right)\tan\theta},\]with \(\delta = 1\) for the weak and \(\delta = 0\) for the strong solution.
- Parameters:
M1 (float or array_like) – Upstream Mach number [-], greater than one.
theta (float or array_like) – Deflection angle [rad], positive and at most
oblique_shock_max_deflection().gamma (float, optional) – Ratio of specific heats [-], greater than one.
strong (bool, optional) – Return the strong-shock branch (subsonic downstream flow) instead of the weak one that occurs on wedges and ramps.
- Returns:
Wave angle [rad].
- Return type:
float or ndarray
- Raises:
ValueError – If
thetaexceeds the maximum deflection (the shock detaches).
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
M. J. Thompson, “A note on the calculation of oblique shock-wave characteristics,” J. Aeronaut. Sci. 17 (1950) 744; T. Meyer, “Über zweidimensionale Bewegungsvorgänge in einem Gas, das mit Überschallgeschwindigkeit strömt,” Forschungsheft VDI 62 (1908).
Examples
>>> round(float(np.degrees(oblique_shock_angle(2.0, np.radians(20.0)))), 2) 53.42
- engineeringkit.aerodynamics.oblique_shock_deflection(M1, beta, gamma=1.4)[source]#
Flow deflection behind an oblique shock, the \(\theta\)-\(\beta\)-\(M\) relation.
\[\tan\theta = 2\cot\beta\,\frac{M_1^2\sin^2\beta - 1}{M_1^2(\gamma + \cos 2\beta) + 2}\]- Parameters:
M1 (float or array_like) – Upstream Mach number [-], at least one.
beta (float or array_like) – Wave angle from the upstream flow [rad], in \([\mu, \pi/2]\) where \(\mu = \arcsin(1/M_1)\).
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Deflection angle [rad]; zero for a Mach wave (\(\beta = \mu\)) and for a normal shock (\(\beta = \pi/2\)).
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
J. D. Anderson, Modern Compressible Flow, 3rd ed. (McGraw-Hill, 2003), eq. 4.17.
Examples
>>> round(float(np.degrees(oblique_shock_deflection(2.0, np.radians(53.4229)))), 3) 20.0
- engineeringkit.aerodynamics.oblique_shock_max_deflection(M1, gamma=1.4)[source]#
Largest deflection an attached oblique shock can turn, and its wave angle.
The wave angle at maximum deflection satisfies
\[\sin^2\beta_{\max} = \frac{1}{\gamma M_1^2}\left[\frac{\gamma+1}{4}M_1^2 - 1 + \sqrt{(\gamma+1)\left(\frac{\gamma+1}{16}M_1^4 + \frac{\gamma-1}{2}M_1^2 + 1\right)}\right].\]- Parameters:
M1 (float or array_like) – Upstream Mach number [-], at least one.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
theta_max (float or ndarray) – Maximum deflection [rad]; a steeper wedge carries a detached bow shock.
beta_max (float or ndarray) – Wave angle at that deflection [rad], dividing the weak and strong branches.
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> theta_max, beta_max = oblique_shock_max_deflection(2.0) >>> round(float(np.degrees(theta_max)), 2), round(float(np.degrees(beta_max)), 2) (22.97, 64.67)
- engineeringkit.aerodynamics.oswald_efficiency_estimate(AR)[source]#
Empirical Oswald factor for straight wings, \(e = 1.78(1 - 0.045 AR^{0.68}) - 0.64\).
- Parameters:
AR (float or array_like) – Aspect ratio [-] in
[2, 10], the range of the underlying data.- Returns:
Oswald efficiency factor [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
D. P. Raymer, Aircraft Design: A Conceptual Approach, 6th ed. (AIAA, 2018), eq. 12.48.
Examples
>>> round(float(oswald_efficiency_estimate(8.0)), 4) 0.8106
- engineeringkit.aerodynamics.panel_method(geometry, alpha_rad)[source]#
Surface pressure, lift and moment of a 2-D body by the Hess-Smith source-vortex panel method.
- Parameters:
geometry (Airfoil or array_like) – An
Airfoilfromnaca4_airfoil(), or the panel end points as an(N + 1, 2)array ordered clockwise from the lower surface at the trailing edge, round the leading edge, to the upper surface at the trailing edge. Repeat the first point last to close a smooth body such as a circle. Units are arbitrary but consistent.alpha_rad (float) – Angle of attack [rad].
- Returns:
Surface speed and pressure coefficient at each panel midpoint, the singularity strengths, and the lift coefficient from the circulation and from the integrated pressure, with the quarter-chord moment.
- Return type:
- Raises:
ValueError – If the points run counterclockwise or are not a list of 2-D points.
Notes
Steady, inviscid, incompressible flow: no boundary layer, separation or stall, and so no drag. The pressure-integrated lift converges to the circulation lift as the panels are refined. Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
J. L. Hess and A. M. O. Smith, “Calculation of potential flow about arbitrary bodies,” Progress in Aerospace Sciences 8 (1967) 1-138; J. D. Anderson, Fundamentals of Aerodynamics, 6th ed. (McGraw-Hill, 2017), secs. 3.17 and 4.10.
Examples
>>> from engineeringkit.aerodynamics import naca4_airfoil >>> result = panel_method(naca4_airfoil("0012", 81), np.radians(5.0)) >>> round(result.cl, 3) 0.599
- engineeringkit.aerodynamics.pitching_moment_slope(h, h_ac_wb, a_wb, a_t, V_H, deps_dalpha=0.0, eta=1.0)[source]#
Moment-curve slope about the centre of gravity, \(C_{M,\alpha} = a_{wb}(h - h_n)\).
- Parameters:
h (float or array_like) – Centre of gravity as a fraction of the mean chord [-].
h_ac_wb – As in
neutral_point().a_wb – As in
neutral_point().a_t – As in
neutral_point().V_H – As in
neutral_point().deps_dalpha – As in
neutral_point().eta – As in
neutral_point().
- Returns:
\(dC_{M,cg}/d\alpha\) [1/rad]; negative for a statically stable aircraft.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(pitching_moment_slope(0.3, 0.24, 4.8, 4.0, 0.6, 0.38)), 4) -1.2
- engineeringkit.aerodynamics.prandtl_glauert_cp(cp0, M)[source]#
Prandtl-Glauert compressibility correction \(C_p = C_{p,0}/\sqrt{1 - M_\infty^2}\).
- Parameters:
cp0 (float or array_like) – Incompressible pressure coefficient [-].
M (float or array_like) – Free-stream Mach number [-] in
[0, 1).
- Returns:
Compressible pressure coefficient [-].
- Return type:
float or ndarray
Notes
Linearized subsonic theory; it diverges as \(M \to 1\) and is unreliable above roughly \(M = 0.7\). Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
H. Glauert, “The effect of compressibility on the lift of an aerofoil,” Proc. R. Soc. Lond. A 118 (1928) 113-119.
Examples
>>> round(float(prandtl_glauert_cp(-1.0, 0.6)), 6) -1.25
- engineeringkit.aerodynamics.prandtl_meyer_angle(M, gamma=1.4)[source]#
Prandtl-Meyer function \(\nu(M)\), the turning angle that expands a sonic stream to \(M\).
\[\nu(M) = \sqrt{\frac{\gamma+1}{\gamma-1}}\arctan\sqrt{\frac{\gamma-1}{\gamma+1}(M^2-1)} - \arctan\sqrt{M^2-1}\]- Parameters:
M (float or array_like) – Mach number [-], at least one.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Prandtl-Meyer angle [rad]; zero at \(M = 1\), tending to \(\tfrac{\pi}{2}(\sqrt{(\gamma+1)/(\gamma-1)} - 1)\) as \(M \to \infty\).
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
L. Prandtl, “Neue Untersuchungen über die strömende Bewegung der Gase und Dämpfe,” Physikalische Zeitschrift 8 (1907) 23-30; T. Meyer, Forschungsheft VDI 62 (1908).
Examples
>>> round(float(np.degrees(prandtl_meyer_angle(2.0))), 3) 26.38
- engineeringkit.aerodynamics.prandtl_meyer_expansion(M1, theta, gamma=1.4)[source]#
Mach number after a supersonic stream turns away from itself by \(\theta\).
The expansion is isentropic, so \(\nu(M_2) = \nu(M_1) + \theta\) and the stagnation state is unchanged.
- Parameters:
M1 (float or array_like) – Upstream Mach number [-], at least one.
theta (float or array_like) – Turning angle [rad], nonnegative.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Downstream Mach number [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(prandtl_meyer_expansion(1.5, np.radians(20.0))), 3) 2.207
- engineeringkit.aerodynamics.rate_of_climb(thrust, drag, V, weight)[source]#
Steady rate of climb from excess power, \(R/C = (T - D)V/W\).
- Parameters:
thrust (float or array_like) – Thrust available [N], nonnegative.
drag (float or array_like) – Drag at the flight condition [N], nonnegative.
V (float or array_like) – True airspeed [m/s], nonnegative.
weight (float or array_like) – Aircraft weight [N], positive.
- Returns:
Vertical speed [m/s]; negative when drag exceeds thrust.
- Return type:
float or ndarray
Notes
Uses the drag of level flight, a good approximation for climb angles below about 15°. Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
Anderson, Introduction to Flight, 8th ed. (McGraw-Hill, 2016), sec. 6.8.
Examples
>>> float(rate_of_climb(3000.0, 1500.0, 60.0, 15000.0)) 6.0
- engineeringkit.aerodynamics.rayleigh_choking_heat(M, T0, gamma=1.4, R=287.05287)[source]#
Heat per unit mass \(q^* = c_p (T_0^* - T_0)\) that brings Rayleigh flow to \(M = 1\).
- Parameters:
M (float or array_like) – Inlet Mach number [-], positive.
T0 (float or array_like) – Inlet stagnation temperature [K], positive.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
R (float, optional) – Specific gas constant [J/(kg K)], positive.
- Returns:
Heat addition to choke the duct [J/kg]; adding more forces the inlet state to change (thermal choking).
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(rayleigh_choking_heat(0.2, 300.0)) / 1e3, 1) 1435.3
- engineeringkit.aerodynamics.rayleigh_flow(M, gamma=1.4)[source]#
Rayleigh-line ratios of frictionless flow with heat transfer in a constant-area duct.
\[\frac{p}{p^*} = \frac{1+\gamma}{1+\gamma M^2},\qquad \frac{T}{T^*} = M^2\left(\frac{p}{p^*}\right)^2,\qquad \frac{T_0}{T_0^*} = \frac{(\gamma+1)M^2\,[2 + (\gamma-1)M^2]}{(1+\gamma M^2)^2}\]- Parameters:
M (float or array_like) – Mach number [-], positive.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Ratios to the sonic state;
friction_parameteris zero.- Return type:
Notes
Heating drives the Mach number towards one from either side and cooling drives it away. The stagnation temperature peaks at \(M = 1\), so a given inlet state can absorb only a finite heat. Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
Lord Rayleigh, “Aerial plane waves of finite amplitude,” Proc. R. Soc. Lond. A 84 (1910) 247-284.
Examples
>>> state = rayleigh_flow(2.0) >>> round(float(state.stagnation_temperature_ratio), 4), round(float(state.pressure_ratio), 4) (0.7934, 0.3636)
- engineeringkit.aerodynamics.reynolds_number(rho, V, L, mu)[source]#
Reynolds number \(Re = \rho V L / \mu\).
- Parameters:
rho (float or array_like) – Density [kg/m^3], positive.
V (float or array_like) – Speed [m/s], nonnegative.
L (float or array_like) – Reference length (chord, plate distance) [m], positive.
mu (float or array_like) – Dynamic viscosity [Pa s], positive.
- Returns:
Reynolds number [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(reynolds_number(1.0, 10.0, 1.0, 1e-5))) 1000000
- engineeringkit.aerodynamics.skin_friction_laminar(Re)[source]#
Blasius average skin-friction coefficient of a laminar flat plate, \(C_f = 1.328/\sqrt{Re_L}\).
- Parameters:
Re (float or array_like) – Plate-length Reynolds number [-], positive; laminar flow (typically \(Re_L < 5\times10^5\)) is assumed, not checked.
- Returns:
Average skin-friction coefficient (both sides not included) [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
H. Blasius, “Grenzschichten in Flüssigkeiten mit kleiner Reibung,” Z. Math. Phys. 56 (1908) 1-37.
Examples
>>> round(float(skin_friction_laminar(1e6)), 6) 0.001328
- engineeringkit.aerodynamics.skin_friction_turbulent(Re)[source]#
Prandtl’s one-fifth-power turbulent flat-plate skin friction, \(C_f = 0.074/Re_L^{1/5}\).
- Parameters:
Re (float or array_like) – Plate-length Reynolds number [-], positive; fully turbulent flow from the leading edge, roughly \(5\times10^5 < Re_L < 10^7\).
- Returns:
Average skin-friction coefficient [-].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
H. Schlichting and K. Gersten, Boundary-Layer Theory, 9th ed. (Springer, 2017), ch. 18.
Examples
>>> round(float(skin_friction_turbulent(1e5)), 6) 0.0074
- engineeringkit.aerodynamics.speed_of_sound(gamma, R, T)[source]#
Speed of sound in a perfect gas, \(a = \sqrt{\gamma R T}\) (Laplace).
- Parameters:
gamma (float or array_like) – Ratio of specific heats [-], greater than one.
R (float or array_like) – Specific gas constant [J/(kg K)], positive (287.05 for air).
T (float or array_like) – Absolute temperature [K], positive.
- Returns:
Speed of sound [m/s].
- Return type:
float or ndarray
Notes
Newton’s isothermal estimate is \(\sqrt{RT}\); Laplace’s adiabatic correction multiplies it by \(\sqrt{\gamma}\). Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(speed_of_sound(1.4, 287.05, 288.15)), 2) 340.29
- engineeringkit.aerodynamics.stagnation_pressure(p, M, gamma=1.4)[source]#
Isentropic stagnation pressure \(p_0 = p(1 + \tfrac{\gamma-1}{2}M^2)^{\gamma/(\gamma-1)}\).
- Parameters:
p (float or array_like) – Static pressure [Pa], positive.
M (float or array_like) – Mach number [-], nonnegative.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Stagnation (total) pressure [Pa].
- Return type:
float or ndarray
Notes
Not conserved across a shock wave. Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
References
A. J. C. B. de Saint-Venant and L. Wantzel, “Mémoire et expériences sur l’écoulement de l’air,” J. École Polytech. 16 (1839) 85-122.
Examples
>>> round(float(stagnation_pressure(100.0, 2.0)), 3) 782.445
- engineeringkit.aerodynamics.stagnation_temperature(T, M, gamma=1.4)[source]#
Isentropic stagnation temperature \(T_0 = T(1 + \tfrac{\gamma-1}{2}M^2)\).
- Parameters:
T (float or array_like) – Static temperature [K], positive.
M (float or array_like) – Mach number [-], nonnegative.
gamma (float, optional) – Ratio of specific heats [-], greater than one.
- Returns:
Stagnation (total) temperature [K].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(stagnation_temperature(300.0, 2.0)), 6) 540.0
- engineeringkit.aerodynamics.stall_speed(weight, rho, S, Clmax)[source]#
Minimum level-flight speed \(V_s = \sqrt{2W / (\rho S C_{L,\max})}\).
Setting lift equal to weight at the largest attainable lift coefficient gives the slowest speed at which the wing can still support the aircraft.
- Parameters:
weight (float or array_like) – Aircraft weight [N], positive.
rho (float or array_like) – Air density [kg/m^3], positive.
S (float or array_like) – Wing area [m^2], positive.
Clmax (float or array_like) – Maximum lift coefficient [-], positive.
- Returns:
Stall speed [m/s].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; assumptions and validity limits are in Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(stall_speed(12000.0, 1.2, 20.0, 1.5)), 4) 25.8199
- engineeringkit.aerodynamics.static_margin(h_n, h)[source]#
Static margin \(h_n - h\), the neutral point’s distance behind the centre of gravity.
- Parameters:
h_n (float or array_like) – Neutral point as a fraction of the mean chord [-].
h (float or array_like) – Centre of gravity as a fraction of the mean chord [-].
- Returns:
Static margin [-]; positive for a statically stable aircraft (5-15% of the chord for most transport aircraft).
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(static_margin(0.55, 0.3)), 4) 0.25
- engineeringkit.aerodynamics.tail_volume_ratio(S_t, l_t, S, c_bar)[source]#
Horizontal-tail volume ratio \(V_H = l_t S_t / (\bar c S)\).
- Parameters:
S_t (float or array_like) – Horizontal-tail area [m^2], positive.
l_t (float or array_like) – Distance from the centre of gravity to the tail aerodynamic centre [m], positive.
S (float or array_like) – Wing area [m^2], positive.
c_bar (float or array_like) – Mean aerodynamic chord [m], positive.
- Returns:
Tail volume ratio [-]; typically 0.3 to 1.
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(tail_volume_ratio(3.0, 5.0, 16.0, 1.5)), 4) 0.625
- engineeringkit.aerodynamics.takeoff_ground_roll(weight, rho, S, Clmax, thrust, resistance=0.0, g=9.80665)[source]#
Take-off ground roll to lift-off at \(1.2V_{stall}\).
\[s_{LO} = \frac{1.44\,W^2}{g\,\rho\,S\,C_{L,\max}\,(T - R)}\]with the net accelerating force \(T - R\) taken constant along the roll, where \(R = D + \mu_r(W - L)\) is the drag and rolling friction evaluated at \(0.7V_{LO}\).
- Parameters:
weight (float or array_like) – Take-off weight [N], positive.
rho (float or array_like) – Air density [kg/m^3], positive.
S (float or array_like) – Wing area [m^2], positive.
Clmax (float or array_like) – Maximum lift coefficient in take-off configuration [-], positive.
thrust (float or array_like) – Mean thrust over the roll [N], positive.
resistance (float or array_like, optional) – Mean drag plus rolling friction [N], nonnegative and less than
thrust.g (float, optional) – Gravitational acceleration [m/s^2].
- Returns:
Ground-roll distance [m].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
Anderson, Introduction to Flight, 8th ed. (McGraw-Hill, 2016), sec. 6.15.
Examples
>>> round(float(takeoff_ground_roll(10.7e3, 1.225, 16.2, 1.6, 2400.0, 400.0)), 1) 264.7
- engineeringkit.aerodynamics.thin_airfoil_cl(alpha_rad, alpha_l0=0.0)[source]#
Thin-airfoil section lift coefficient \(c_l = 2\pi(\alpha - \alpha_{L=0})\).
- Parameters:
alpha_rad (float or array_like) – Angle of attack [rad].
alpha_l0 (float, optional) – Zero-lift angle of attack [rad]; zero for a symmetric section and negative for positive camber (see
naca4_zero_lift_angle()).
- Returns:
Section lift coefficient [-].
- Return type:
float or ndarray
Notes
Small angles and attached, inviscid, incompressible flow are assumed; stall is not predicted. Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
H. Glauert, The Elements of Aerofoil and Airscrew Theory (Cambridge University Press, 1926), ch. 7.
Examples
>>> round(float(thin_airfoil_cl(0.1)), 6) 0.628319
- engineeringkit.aerodynamics.turn_radius(V, n, g=9.80665)[source]#
Radius of a level turn, \(R = V^2/(g\sqrt{n^2 - 1})\).
- Parameters:
V (float or array_like) – True airspeed [m/s], nonnegative.
n (float or array_like) – Load factor [-], greater than one.
g (float, optional) – Gravitational acceleration [m/s^2].
- Returns:
Turn radius [m].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
References
Anderson, Introduction to Flight, 8th ed. (McGraw-Hill, 2016), sec. 6.17.
Examples
>>> round(float(turn_radius(60.0, 2.0)), 2) 211.94
- engineeringkit.aerodynamics.turn_rate(V, n, g=9.80665)[source]#
Turn rate of a level turn, \(\omega = g\sqrt{n^2 - 1}/V\).
- Parameters:
V (float or array_like) – True airspeed [m/s], positive.
n (float or array_like) – Load factor [-], greater than one.
g (float, optional) – Gravitational acceleration [m/s^2].
- Returns:
Turn rate [rad/s].
- Return type:
float or ndarray
Notes
Inputs are raw SI numbers with no dimensional metadata; see Aerodynamics: incompressible limits and compressible conservation.
Examples
>>> round(float(np.degrees(turn_rate(60.0, 2.0))), 3) 16.22
Visualizers#
Matplotlib visualizers for engineeringkit.aerodynamics.
- engineeringkit.aerodynamics.visualizers.plot_airfoil(airfoil, ax=None)[source]#
Draw an airfoil outline and its mean camber line on equal axes.
- Parameters:
airfoil (
Airfoil) – Fromengineeringkit.aerodynamics.naca4_airfoil().ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure is created if omitted.
- Return type:
matplotlib.axes.Axes
- engineeringkit.aerodynamics.visualizers.plot_atmosphere(state, axes=None)[source]#
Plot temperature, pressure and density against altitude side by side.
- Parameters:
state (
AtmosphereState) – Fromengineeringkit.aerodynamics.isa_atmosphere()with an altitude array.axes (sequence of three matplotlib.axes.Axes, optional) – Axes to draw on; a new figure is created if omitted.
- Return type:
ndarray of matplotlib.axes.Axes
- engineeringkit.aerodynamics.visualizers.plot_drag_polar(cl, cd, ax=None, label=None)[source]#
Plot lift coefficient against drag coefficient and mark the best-glide tangent.
- Parameters:
cl (array_like) – Matching lift and drag coefficients [-].
cd (array_like) – Matching lift and drag coefficients [-].
ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure is created if omitted.
label (str, optional) – Legend label for the polar.
- Return type:
matplotlib.axes.Axes
- engineeringkit.aerodynamics.visualizers.plot_duct_flow(state, ax=None)[source]#
Plot the Fanno or Rayleigh property ratios against Mach number.
- Parameters:
state (
DuctFlowState) – Fromengineeringkit.aerodynamics.fanno_flow()orengineeringkit.aerodynamics.rayleigh_flow()with a Mach-number array.ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure is created if omitted.
- Return type:
matplotlib.axes.Axes
- engineeringkit.aerodynamics.visualizers.plot_pressure_coefficient(result, ax=None)[source]#
Plot \(-C_p\) along the chord, upper surface solid and lower surface dashed.
- Parameters:
result (
PanelResult) – Fromengineeringkit.aerodynamics.panel_method().ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure is created if omitted.
- Return type:
matplotlib.axes.Axes
- engineeringkit.aerodynamics.visualizers.plot_spanwise_loading(result, ax=None)[source]#
Plot a lifting-line circulation distribution next to the elliptic load of equal lift.
- Parameters:
result (
LiftingLineResult) – Fromengineeringkit.aerodynamics.lifting_line().ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure is created if omitted.
- Return type:
matplotlib.axes.Axes
- engineeringkit.aerodynamics.visualizers.plot_theta_beta_mach(mach_numbers, gamma=1.4, ax=None)[source]#
Draw the oblique-shock theta-beta-M chart: wave angle against deflection for each Mach number.
- Parameters:
mach_numbers (sequence of float) – Upstream Mach numbers [-], each greater than one.
gamma (float, optional) – Ratio of specific heats [-].
ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure is created if omitted.
- Returns:
Weak branches are solid and strong branches dashed; the dotted line joins the maximum-deflection points.
- Return type:
matplotlib.axes.Axes