| name | dimensional-analysis |
| description | Automated dimensional analysis — Buckingham Pi theorem, non-dimensionalization, unit validation with pint, and characteristic scale estimation. Use before any physics computation to verify consistency and reduce parameter space. |
| category | physics |
| version | 1.0.0 |
| author | Synthetic Sciences |
| license | MIT |
| tags | ["Dimensional Analysis","Buckingham Pi","Units","Non-dimensionalization","Physics"] |
| dependencies | ["scipy>=1.11.0","numpy>=1.24.0","sympy>=1.12.0"] |
Dimensional Analysis
Overview
Systematic dimensional analysis for physics problems. Implements Buckingham Pi theorem to find dimensionless groups, validates unit consistency, non-dimensionalizes equations, and estimates characteristic scales.
When to Use
- Before any physics computation: verify unit consistency
- Reducing parameter space via dimensionless groups
- Identifying which physical effects dominate (comparing dimensionless numbers)
- Non-dimensionalizing PDEs before numerical solution
- Checking if a derived formula has correct dimensions
Core Workflows
1. Buckingham Pi Theorem
import numpy as np
from sympy import symbols, Matrix, zeros, Rational
def buckingham_pi(variables, dimensions):
"""
Buckingham Pi theorem: find dimensionless groups.
Args:
variables: dict of {name: {dim: power}} e.g. {'v': {'L': 1, 'T': -1}}
dimensions: list of fundamental dimensions e.g. ['M', 'L', 'T']
Returns:
List of dimensionless Pi groups
"""
var_names = list(variables.keys())
n_vars = len(var_names)
n_dims = len(dimensions)
D = np.zeros((n_dims, n_vars))
for j, var in enumerate(var_names):
for i, dim in enumerate(dimensions):
D[i, j] = variables[var].get(dim, 0)
rank = np.linalg.matrix_rank(D)
n_pi = n_vars - rank
print(f"Variables: {n_vars}, Dimensions: {n_dims}, Rank: {rank}")
print(f"Number of Pi groups: {n_pi}")
print(f"\nDimension matrix:")
print(f" {' '.join(f'{v:>8}' for v in var_names)}")
for i, dim in enumerate(dimensions):
print(f" {dim} {' '.join( j (n_vars))}")
D_sym = Matrix(D).T
null = D_sym.nullspace()
()
k, vec (null):
terms = []
j, exp (vec):
exp != :
terms.append()
()
null
variables = {
: {: , : , : -},
: {: , : -},
: {: },
: {: , : -},
: {: , : -, : -},
}
pi_groups = buckingham_pi(variables, [, , ])
2. Unit Validation with pint
import pint
ureg = pint.UnitRegistry()
Q_ = ureg.Quantity
mass = Q_(2.0, 'kg')
velocity = Q_(3.0, 'm/s')
height = Q_(10.0, 'm')
g = Q_(9.80665, 'm/s^2')
KE = 0.5 * mass * velocity**2
PE = mass * g * height
print(f"KE = {KE.to('J')}")
print(f"PE = {PE.to('J')}")
print(f"Total E = {(KE + PE).to('J')}")
try:
bad = mass + velocity
except pint.DimensionalityError as e:
print(f"\nUnit error caught: {e}")
force = Q_(100, 'N')
print(f"\n{force} = {force.to('dyn')} = {force.to('lbf')}")
L = Q_(1.0, 'm')
T = 2 * 3.14159 * (L / g)**
()
3. Non-dimensionalization
import sympy as sp
def nondimensionalize(equation, scales):
"""
Non-dimensionalize an equation given characteristic scales.
Args:
equation: sympy equation (lhs - rhs = 0)
scales: dict of {variable: scale_value}
"""
for var, scale in scales.items():
dim_less = sp.Symbol(f'{var.name}*')
equation = equation.subs(var, scale * dim_less)
return sp.simplify(equation)
print("Navier-Stokes non-dimensionalization:")
print(" Scales: U (velocity), L (length), ρ₀ (density)")
print(" Dimensionless variables:")
print(" t* = tU/L")
print(" x* = x/L")
print(" u* = u/U")
print(" p* = p/(ρU²)")
print(" Result:")
print(" ∂u*/∂t* + u*·∇*u* = -∇*p* + (1/Re)∇*²u*")
print(" where Re = ρUL/μ")
4. Common Dimensionless Numbers
def dimensionless_numbers(params):
"""Compute common dimensionless numbers from physical parameters."""
rho = params.get('density')
v = params.get('velocity')
L = params.get('length')
mu = params.get('viscosity')
alpha = params.get('thermal_diff')
g = params.get('gravity', 9.81)
beta = params.get('thermal_exp')
dT = params.get('delta_T')
D = params.get('mass_diff')
c = params.get('sound_speed')
nu = mu / rho if (mu and rho) else None
numbers = {}
if rho and v and L and mu:
numbers['Re'] = rho * v * L / mu
if v and c:
numbers['Ma'] = v / c
if nu and alpha:
numbers['Pr'] = nu / alpha
if g and beta and dT and L and nu and alpha:
numbers['Ra'] = g * beta * dT * L** / (nu * alpha)
v L D:
numbers[] = v * L / D
nu D:
numbers[] = nu / D
name, val numbers.items():
()
numbers
()
nums = dimensionless_numbers({
: ,
: ,
: ,
: ,
: ,
})
nums:
Re = nums[]
Re < :
()
Re < :
()
:
()
5. Dimension Checking for Formulas
def check_dimensions(formula_str, var_dims):
"""
Check if a formula is dimensionally consistent.
Args:
formula_str: string like "0.5 * m * v**2"
var_dims: dict of {var_name: {dim: power}}
"""
import re
print(f"Formula: {formula_str}")
print(f"Variable dimensions:")
for var, dims in var_dims.items():
dim_str = " · ".join(f"{d}^{p}" for d, p in dims.items() if p != 0)
print(f" {var}: [{dim_str}]")
ureg = pint.UnitRegistry()
dim_to_unit = {'M': 'kg', 'L': 'm', 'T': 's', 'Θ': 'K', 'I': 'A'}
context = {}
for var, dims in var_dims.items():
unit_str = " * ".join(f"{dim_to_unit[d]}**{p}" for d, p in dims.items() if p != 0)
context[var] = ureg.Quantity(, unit_str)
:
result = (formula_str, {: {}}, context)
()
pint.DimensionalityError e:
()
check_dimensions(, {
: {: },
: {: , : -}
})
Quick Reference: Fundamental Dimensions
| Dimension | Symbol | SI Unit |
|---|
| Mass | M | kg |
| Length | L | m |
| Time | T | s |
| Temperature | Θ | K |
| Electric current | I | A |
| Amount | N | mol |
| Luminous intensity | J | cd |
Common Dimensionless Numbers
| Number | Formula | Physical Meaning |
|---|
| Reynolds (Re) | ρvL/μ | Inertia / viscosity |
| Mach (Ma) | v/c | Flow speed / sound speed |
| Prandtl (Pr) | ν/α | Momentum diffusion / thermal diffusion |
| Rayleigh (Ra) | gβΔTL³/(να) | Buoyancy / diffusion |
| Peclet (Pe) | vL/D | Advection / diffusion |
| Knudsen (Kn) | λ/L | Mean free path / system size |
| Froude (Fr) | v/√(gL) | Inertia / gravity |
| Weber (We) | ρv²L/σ | Inertia / surface tension |
| Strouhal (St) | fL/v | Oscillation / flow |
| Nusselt (Nu) | hL/k | Convective / conductive heat transfer |