Skip to content

matuscvengros/engunits

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Engineering Units

Tests Docs Python 3.10+ PyPI MIT License

Typed engineering quantities with unit-preserving storage, built on pint.

engunits wraps pint in a typed layer that gives every physical quantity its own Python class. You get IDE autocompletion, type-checked arithmetic, automatic cross-type resolution, and clean SI/Imperial conversions — without losing access to pint's full unit ecosystem.

Install

pip install engunits

Quick Start

Creating quantities

Quantities preserve the units you give them. When no unit is specified, SI is assumed.

from engunits import Mass, Force, Length, Velocity

m = Mass(1000, "lb")       # stored as 1000 lb
f = Force(100, "N")        # stored as 100 N
v = Velocity(60, "mph")    # stored as 60 mph
l = Length(5)               # stored as 5 m (SI default)

Converting units

Convert on demand with callable syntax, .to(), or the .si() / .imperial() shortcuts.

m = Mass(1000, "lb")

m("kg")              # Mass(453.592, 'kg')
m.to("kg")           # Mass(453.592, 'kg')  — same as above
m.si()               # Mass(453.592, 'kg')
m.imperial()         # Mass(1000, 'lb')

# Chain conversions
Force(100, "N")("lbf")("kN")  # Force(0.1, 'kN')

Arithmetic

Same-type arithmetic preserves the left operand's units. Cross-type arithmetic automatically resolves to the correct quantity type.

from engunits import Mass, Force, Acceleration, Velocity, Time, Power

# Same-type: preserves units
Mass(10, "lb") + Mass(5, "lb")     # Mass(15, 'lb')
Mass(30, "kg") / Mass(10, "kg")    # 3.0 (dimensionless float)

# Scalar multiplication/division
Mass(10, "kg") * 3                  # Mass(30, 'kg')
Force(30, "N") / 3                  # Force(10, 'N')

# Cross-type: automatic type resolution
Force(100, "N") / Mass(10, "kg")    # Acceleration(10, 'N / kg')
Mass(5, "kg") * Acceleration(10)    # Force(50, 'kg * m / s ** 2')
Velocity(10) * Time(5)              # Length(50, 'm / s * s')
Power(1000, "W") / Velocity(10)     # Force(100, 'W * s / m')

# Exponentiation
Length(3, "m") ** 2                  # Area(9, 'm ** 2')
Length(2, "m") ** 3                  # Volume(8, 'm ** 3')

Cross-type results preserve computed units

The units from the computation are preserved — call .si() to normalize.

result = Force(100, "lbf") / Mass(10, "lb")
print(result)           # 10 lbf / lb
print(result.si())      # 9.80665 m / s ** 2

Aggregation with sum()

from engunits import Mass
masses = [Mass(1, "kg"), Mass(2, "kg"), Mass(3, "kg")]
total = sum(masses)     # Mass(6, 'kg')

Comparisons

Mass(1, "kg") == Mass(1000, "g")   # True
Mass(1, "lb") < Mass(1, "kg")     # True
Force(10, "N") >= Force(5, "N")    # True

NumPy array support

All quantities accept NumPy arrays as values.

import numpy as np
from engunits import Force

f = Force(np.array([3.0, 4.0]), "N")
f.value       # array([3., 4.])
f.norm        # 5.0 (L2 norm)
f("lbf")      # Force(array([0.6744, 0.8992]), 'lbf')

Properties

m = Mass(10, "kg")
m.value       # 10.0 — raw numeric magnitude
m.magnitude   # 10.0 — alias for value (pint compatibility)
m.units       # 'kg'
m.norm        # 10.0 — float for scalars, L2 norm for arrays
m.quantity    # pint.Quantity(10, 'kg') — underlying pint object
float(m)      # 10.0
bool(m)       # True (False only for zero)

Ambiguous Dimensionality Conversions

Some quantity types share the same physical dimensions in pint. Cross-type arithmetic producing these dimensionalities returns a raw pint Quantity since the intended type is ambiguous. Explicit conversion methods are provided for intentional casts.

Frequency / Angular Velocity

Pint treats radians as dimensionless, so rad/s and Hz both reduce to 1/[time]. The physical relationship ω = 2πf requires an explicit conversion.

from engunits import Frequency, AngularVelocity

omega = AngularVelocity(60, "rpm")
f = omega.to_frequency()        # Frequency(1, 'Hz')

f = Frequency(50, "Hz")
omega = f.to_angular_velocity() # AngularVelocity(314.159, 'rad/s')

# Roundtrip
Frequency(10, "Hz").to_angular_velocity().to_frequency()  # Frequency(10, 'Hz')

Energy / Moment

Energy (J) and torque (N*m) share dimensionality [mass]*[length]²/[time]² but are physically distinct.

from engunits import Energy, Moment

e = Energy(100, "J")
m = e.to_moment()       # Moment(100, 'N * m')

m = Moment(50, "lbf*ft")
e = m.to_energy()       # Energy(67.791, 'J')

Charge / Capacity

Charge (C) and battery capacity (A*h) share dimensionality [current]*[time].

from engunits import Charge, Capacity

q = Charge(3600, "C")
cap = q.to_capacity()   # Capacity(1, 'A * h')

cap = Capacity(2, "A*h")
q = cap.to_charge()     # Charge(7200, 'C')

Supported Quantities (41)

SI Base

Class SI Unit
Mass kg
Length m
Time s
Temperature K
Current A
AmountOfSubstance mol
LuminousIntensity cd

Mechanics

Class SI Unit
Velocity m/s
Acceleration m/s^2
Force N
Moment N*m
Energy J
Power W
Area m^2
Volume m^3
Density kg/m^3
Pressure Pa
Frequency Hz
Momentum kg*m/s
AngularVelocity rad/s
AngularAcceleration rad/s^2
MomentOfInertia kg*m^2
SurfaceTension N/m

Electromagnetism

Class SI Unit
Voltage V
Charge C
Capacity A*h
Resistance ohm
Capacitance F
Inductance H
MagneticFlux Wb
MagneticFluxDensity T
Conductance S
ElectricField V/m

Fluid and Thermal

Class SI Unit
DynamicViscosity Pa*s
KinematicViscosity m^2/s
MassFlowRate kg/s
VolumetricFlowRate m^3/s
ThermalConductivity W/(m*K)
SpecificHeatCapacity J/(kg*K)
HeatFlux W/m^2

Optics

Class SI Unit
Illuminance lx

Accessing pint directly

Every quantity exposes its underlying pint object via .quantity for advanced use cases.

from engunits import Mass

m = Mass(10, "kg")
pq = m.quantity          # pint.Quantity(10, 'kg')
pq.dimensionality       # {'[mass]': 1}

You can also use the shared registry directly:

from engunits import Q_, ureg

q = Q_(9.81, "m/s**2")  # raw pint Quantity

License

MIT

About

Typed engineering quantities based on pint.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors