Source code for physicskit.fluids.utils.dimensionless

"""Dimensionless numbers: Reynolds, Froude, Mach, Strouhal, and Weber.

Fluid mechanics is governed by ratios, not absolute scales: two flows with
the same dimensionless numbers behave identically regardless of their size,
speed, or fluid, which is what makes wind-tunnel testing of a model
airplane meaningful for a full-size one. Each function here computes one
such ratio, and each result's magnitude is what determines which regime
(and which module of this package) actually applies -- a low Reynolds
number licenses :func:`physicskit.fluids.systems.viscous_flow.stokes_drag`,
a high one calls for
:class:`physicskit.fluids.systems.navier_stokes.NavierStokes2D` or the
turbulence tools in :mod:`physicskit.fluids.utils.spectral_analysis`.
"""

from __future__ import annotations

from physicskit.fluids.exceptions import InvalidParameterError

__all__ = [
    "reynolds_number",
    "froude_number",
    "mach_number",
    "strouhal_number",
    "weber_number",
]


[docs] def reynolds_number(velocity: float, length: float, nu: float) -> float: """The Reynolds number: inertial forces over viscous forces. .. math:: Re = \\frac{U L}{\\nu} Osborne Reynolds' 1883 pipe-flow experiments identified this ratio as the single parameter controlling the transition from smooth (laminar) to chaotic (turbulent) flow, regardless of the pipe's size or the fluid's identity -- the founding result of dimensional-similarity reasoning in fluid mechanics. Parameters ---------- velocity : float Characteristic flow speed `U`. length : float Characteristic length scale `L`. nu : float Kinematic viscosity. Returns ------- float Reynolds number `Re`. Raises ------ InvalidParameterError If `length` or `nu` is not positive. Examples -------- >>> reynolds_number(velocity=2.0, length=0.5, nu=1e-6) 1000000.0 """ if length <= 0: raise InvalidParameterError(f"length must be positive, got {length}") if nu <= 0: raise InvalidParameterError(f"nu must be positive, got {nu}") return velocity * length / nu
[docs] def froude_number(velocity: float, length: float, g: float = 9.81) -> float: """The Froude number: inertial forces over gravitational forces. .. math:: Fr = \\frac{U}{\\sqrt{gL}} Governs free-surface (gravity wave) flows the way the Reynolds number governs viscous ones: a ship model and its full-size counterpart make the same waves, relative to their length, only if `Fr` matches. William Froude's 1868 ship-hull towing-tank experiments established exactly this scaling law. Parameters ---------- velocity : float Characteristic flow speed `U`. length : float Characteristic length scale `L`. g : float, default 9.81 Gravitational acceleration. Returns ------- float Froude number `Fr`. Raises ------ InvalidParameterError If `length` or `g` is not positive. Examples -------- >>> round(froude_number(velocity=3.0, length=9.81, g=9.81), 4) 0.3058 """ if length <= 0: raise InvalidParameterError(f"length must be positive, got {length}") if g <= 0: raise InvalidParameterError(f"g must be positive, got {g}") return velocity / (g * length) ** 0.5
[docs] def mach_number(velocity: float, speed_of_sound: float) -> float: """The Mach number: flow speed over the local speed of sound. .. math:: M = \\frac{U}{c} The single number that decides whether compressibility can be ignored (:math:`M \\ll 1`, the regime of every other module in this package except :mod:`physicskit.fluids.systems.compressible_flow`) or dominates the flow (:math:`M \\gtrsim 1`, where :func:`~physicskit.fluids.systems.compressible_flow.normal_shock_relations` applies). Parameters ---------- velocity : float Flow speed `U`. speed_of_sound : float Local speed of sound `c`. Returns ------- float Mach number `M`. Raises ------ InvalidParameterError If `speed_of_sound` is not positive. Examples -------- >>> mach_number(velocity=340.0, speed_of_sound=340.0) 1.0 """ if speed_of_sound <= 0: raise InvalidParameterError(f"speed_of_sound must be positive, got {speed_of_sound}") return velocity / speed_of_sound
[docs] def strouhal_number(frequency: float, length: float, velocity: float) -> float: """The Strouhal number: a dimensionless vortex-shedding frequency. .. math:: St = \\frac{f L}{U} For flow past a bluff body shedding a :func:`~physicskit.fluids.systems.vortex_dynamics.von_karman_vortex_street` at frequency `f`, `St` stays remarkably constant (near 0.2 for a circular cylinder) over a wide range of Reynolds number, letting a single scaled model predict the shedding frequency at full scale. Parameters ---------- frequency : float Vortex-shedding frequency `f`. length : float Characteristic length scale `L` (e.g. the body's cross-stream width). velocity : float Characteristic flow speed `U`. Returns ------- float Strouhal number `St`. Raises ------ InvalidParameterError If `velocity` is not positive. Examples -------- >>> round(strouhal_number(frequency=2.0, length=0.1, velocity=1.0), 4) 0.2 """ if velocity <= 0: raise InvalidParameterError(f"velocity must be positive, got {velocity}") return frequency * length / velocity
[docs] def weber_number(rho: float, velocity: float, length: float, surface_tension: float) -> float: """The Weber number: inertial forces over surface-tension forces. .. math:: We = \\frac{\\rho U^2 L}{\\sigma} Governs whether a free liquid surface (a droplet, a jet, a bubble) deforms and breaks up under its own inertia (:math:`We \\gg 1`) or is held together by surface tension (:math:`We \\lesssim 1`) -- the parameter that decides, for instance, whether a jet of liquid breaks into droplets. Parameters ---------- rho : float Fluid density. velocity : float Characteristic flow speed `U`. length : float Characteristic length scale `L` (e.g. a droplet diameter). surface_tension : float Surface tension coefficient :math:`\\sigma`. Returns ------- float Weber number `We`. Raises ------ InvalidParameterError If `surface_tension` is not positive. Examples -------- >>> round(weber_number(rho=1000.0, velocity=1.0, length=0.001, surface_tension=0.072), 4) 13.8889 """ if surface_tension <= 0: raise InvalidParameterError(f"surface_tension must be positive, got {surface_tension}") return rho * velocity**2 * length / surface_tension