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: object

Coordinates of an airfoil section on a unit chord.

All coordinates are fractions of the chord c; multiply by c [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

plot(ax=None)[source]#

Draw the section outline and camber line; return (fig, ax).

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: object

Thermodynamic 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

plot(ax=None)[source]#

Plot temperature, pressure and density against altitude; return (fig, axes).

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: object

Fanno 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

plot(ax=None)[source]#

Plot the property ratios against Mach number; return (fig, ax).

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

summary()[source]#

The ratios at the first Mach number in the state.

Return type:

dict

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: object

Glauert’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: object

State 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#

True for the strong-shock branch, False for the weak one.

Type:

bool

summary()[source]#

Wave angle in degrees and the downstream state.

Return type:

dict

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: object

Hess-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 x extent 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 x extent 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

plot(ax=None)[source]#

Plot \(-C_p\) along the chord; return (fig, ax).

source_strengths: ndarray#

Source strength per unit length on each panel, divided by \(V_\infty\) [-].

Type:

ndarray

summary()[source]#

Lift and moment coefficients and the suction peak.

Return type:

dict

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), x coordinates.

Type:

ndarray

y: ndarray#

Panel control points (midpoints), y coordinates.

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-5 for 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:

DuctFlowState

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 a0 as AR grows.

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

  1. 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:

AtmosphereState

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

    1. Kutta, Illustrierte Aeronautische Mitteilungen 6 (1902);

  1. 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:

LiftingLineResult

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.1036 instead of -0.1015 for the quartic coefficient so the trailing edge has zero thickness.

Return type:

Airfoil

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 m at chordwise position p.

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

m and p are 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:

ObliqueShockResult

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 theta exceeds 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 Airfoil from naca4_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:

PanelResult

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

    1. 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_parameter is zero.

Return type:

DuctFlowState

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

    1. 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

    1. 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:
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:
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:
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:
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:
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