Units and Conventions#
physicskit doesn’t force one unit system on every field. Each subpackage
computes in the units its own literature uses, so its formulas look like
the ones in the papers you are checking against: \(r_\text{ISCO} = 6M\)
rather than \(6GM/c^2\), and \(E_n = n + \tfrac12\) rather than
\((n + \tfrac12)\hbar\omega\). The cost is that a bare number such as
6.0 only has a physical meaning once you say what the unit is. This
page lists the convention of each subpackage, and shows how
physicskit.units makes the missing scale choice explicit, converts
results to SI and back, and keeps the units attached when results are
saved.
Conventions by subpackage#
Subpackage |
Convention |
What you still have to choose |
|---|---|---|
gravitational, \(G = 1\) |
a length and a mass scale (e.g. 1 pc and 1 \(M_\odot\));
|
|
geometrized, \(G = c = 1\) |
one scale, conventionally the mass \(M\);
|
|
\(\hbar = 1\) (usually with \(m = 1\)) |
a mass and a length (or energy) scale;
|
|
\(k_B = 1\), couplings \(J = 1\) |
an energy (equivalently temperature) scale; also a length and mass
for molecular dynamics; |
|
SI for single-particle, MHD and wave functions; normalized (\(\omega_{pe} = \lambda_D = 1\)) for the PIC code |
nothing for the SI functions; a density and temperature to give the PIC units physical meaning |
|
any consistent system you pass in; idealized problems are non-dimensional |
your own units |
|
dimensionless |
nothing |
|
|
constants are explicit parameters ( |
read the function’s docstring |
physicskit.constants is the single source of SI values (CODATA,
via scipy.constants) that all of this is built on.
Choosing the scale: physicskit.units#
Setting constants to 1 leaves some scales free: \(G = c = 1\) leaves
one and \(G = 1\) leaves two. Each preset in
physicskit.units takes the free scales as required keyword
arguments. None of them has a default, because a default would pick a
physical system for you without saying so:
import physicskit.constants as const
from physicskit.units import geometrized_units
sun = geometrized_units(mass_kg=const.SOLAR_MASS_KG) # M = 1 solar mass
print(f"{sun.scale('length'):.1f} m, {sun.scale('time') * 1e6:.3f} us")
# 1476.7 m, 4.926 us
print(f"ISCO: {sun.to_si(6.0, 'length') / 1e3:.2f} km") # r = 6M
# ISCO: 8.86 km
print(f"1 ms = {sun.from_si(1.0e-3, 'time'):.1f} M")
# 1 ms = 203.0 M
The same \(r = 6M\) is 8.86 km for a solar-mass black hole and about 58 billion km (385 au) for the \(6.5\times10^9\,M_\odot\) black hole at the centre of M87. The code is identical; only the scale changes.
A dimension the scales don’t determine raises an error instead of returning a number. With \(k_B = 1\) and only an energy scale, an Ising-model temperature converts but a length doesn’t:
from physicskit.units import statphys_units
ising = statphys_units(temperature_k=300.0) # coupling J = k_B * 300 K
print(f"T_c = {ising.to_si(2.269, 'temperature'):.1f} K")
# T_c = 680.7 K
ising.to_si(1.0, "length")
# ValueError: unit system 'statphys (k_B=1)' does not fix the scale of dimension L^1;
# supply another scale (e.g. length_m or mass_kg) when building it
Choosing the electron mass and the Bohr radius for \(\hbar = 1\) gives Hartree atomic units, so a ground-state energy of \(-1/2\) becomes the hydrogen binding energy:
from physicskit.units import quantum_units
au = quantum_units(mass_kg=const.ELECTRON_MASS, length_m=5.29177210903e-11)
print(f"{const.joules_to_ev(au.to_si(0.5, 'energy')):.3f} eV")
# 13.606 eV
Any other combination can be built with
natural_units(), for example particle-physics
units with \(\hbar = c = 1\) and energies in GeV:
from physicskit.units import natural_units
gev = natural_units("hbar", "c", energy_j=1e9 * const.ELECTRONVOLT)
print(f"1/GeV = {gev.to_si(1.0, 'length') * 1e15:.4f} fm = {gev.to_si(1.0, 'time'):.3e} s")
# 1/GeV = 0.1973 fm = 6.582e-25 s
How it works: a UnitSystem stores anchors,
pairs of a Dimension and the SI size of one
unit. Each constant set to 1 is one anchor and each chosen scale is
another. Solving the anchors in log space gives the SI size of one unit
of any dimension they determine. Anchors that contradict each other,
such as \(c = 1\) together with unrelated length and time scales,
are rejected when the system is built.
Keeping units with results#
physicskit.results.Result holds a time series (or any array
output) together with its metadata, the dimension of each array, and the
unit system they are expressed in. The from_* adapters in
physicskit.results wrap the result types the subpackages already
return (integrator tuples, the classical SimulationResult, quantum
EigenResult, rmt Spectrum, chaos map orbits). You can also
build one directly:
import numpy as np
import physicskit.relativity as rel
from physicskit.results import Result
bh = rel.SchwarzschildBlackHole(M=1.0)
orbit = bh.integrate_geodesic(bh.circular_orbit_initial_state(10.0), dtau=0.5, n_steps=2000)
result = Result(
times=orbit["t"],
states=np.column_stack([orbit["r"], orbit["phi"]]),
metadata={"r0": 10.0},
units={"times": "time"},
unit_system=sun,
)
print(f"{result.times[-1]:.1f} M = {result.to_si().times[-1] * 1e3:.3f} ms")
# 1195.2 M = 5.887 ms
physicskit.io.save() and load() write and
read the whole thing, unit system included, as .npz or (with
pip install "physicskit[hdf5]") HDF5:
from physicskit import io
io.save(result, "orbit.npz")
back = io.load("orbit.npz")
print(back, back.unit_system == sun)
# Result(times=(2001,), states=(2001, 2), unit_system='relativity (G=c=1)') True
Interoperating with pint#
If you already use pint, install physicskit[units] and convert
at the boundary with to_pint() and
from_pint(). The dimension of a pint quantity is
read from the quantity itself:
import pint
from physicskit.units import from_pint, to_pint
ureg = pint.UnitRegistry()
print(to_pint(6.0, "length", sun, registry=ureg).to("km"))
# 8.860018146200808 kilometer
print(f"{from_pint(1.0 * ureg.millisecond, sun):.1f}")
# 203.0
Relation to older helpers#
A few conversion helpers predate physicskit.units and remain
supported: physicskit.constants.gravitational_unit_system() (the
same numbers as astro_units()),
energy_to_temperature() and the eV
converters, and physicskit.relativity.utils.constants
(solar_masses_to_geometrized and friends, for the 1-metre geometrized
units used by BinaryMerger). For anything
else, physicskit.units is the general tool.
Reference#
Natural-unit systems and conversions to and from SI.
Each physicskit subpackage computes in the unit system natural to its own
field: physicskit.astro sets \(G = 1\),
physicskit.relativity sets \(G = c = 1\),
physicskit.quantum sets \(\hbar = 1\), and
physicskit.statphys sets \(k_B = 1\). Setting a constant to 1
alone does not fix a unit system: \(G = c = 1\) still leaves one scale
free (conventionally a mass \(M\)), and \(G = 1\) leaves two. This
module makes those remaining choices explicit. Every preset has keyword
arguments you must supply for the free scales; none of them has a hidden
default.
How it works. A UnitSystem is defined by a set of anchors: pairs of a
Dimension and the SI value of one unit of that dimension. A
constant set to 1 is an anchor (for \(c = 1\), one unit of velocity is
\(c_{SI}\) m/s), and so is each user-chosen scale (one unit of mass is
\(M_\odot\)). Writing the unknown SI sizes of the base units as
\([L], [M], [T], [\Theta]\), each anchor with dimension
\(L^a M^b T^c \Theta^d\) and SI value \(v\) gives one linear
equation in log space,
A dimension is convertible exactly when its exponent vector lies in the
span of the anchors’ exponent vectors. So statphys_units() with only
an energy scale can convert energies and temperatures but refuses to
convert a length, rather than returning a meaningless number.
SI values come from physicskit.constants. Converting to and from
pint quantities is supported when pint is installed
(pip install "physicskit[units]"); see to_pint() and
from_pint().
Examples
The geometrized (\(G = c = 1\)) length of one solar mass is
\(GM_\odot/c^2 \approx 1476.6\) m (to the precision of
physicskit.constants.SOLAR_MASS_KG):
>>> import physicskit.constants as const
>>> from physicskit.units import geometrized_units
>>> sun = geometrized_units(mass_kg=const.SOLAR_MASS_KG)
>>> abs(sun.scale("length") - 1476.6) < 0.1
True
>>> round(sun.to_si(10.0, "time") * 1e6, 2) # 10 M in microseconds
49.26
- physicskit.units.DIMENSIONS: dict[str, Dimension] = {'acceleration': Dimension(length=1.0, mass=0.0, time=-2.0, temperature=0.0), 'action': Dimension(length=2.0, mass=1.0, time=-1.0, temperature=0.0), 'angular_momentum': Dimension(length=2.0, mass=1.0, time=-1.0, temperature=0.0), 'area': Dimension(length=2.0, mass=0.0, time=0.0, temperature=0.0), 'density': Dimension(length=-3.0, mass=1.0, time=0.0, temperature=0.0), 'dimensionless': Dimension(length=0.0, mass=0.0, time=0.0, temperature=0.0), 'energy': Dimension(length=2.0, mass=1.0, time=-2.0, temperature=0.0), 'entropy': Dimension(length=2.0, mass=1.0, time=-2.0, temperature=-1.0), 'force': Dimension(length=1.0, mass=1.0, time=-2.0, temperature=0.0), 'frequency': Dimension(length=-0.0, mass=-0.0, time=-1.0, temperature=-0.0), 'length': Dimension(length=1, mass=0.0, time=0.0, temperature=0.0), 'mass': Dimension(length=0.0, mass=1, time=0.0, temperature=0.0), 'momentum': Dimension(length=1.0, mass=1.0, time=-1.0, temperature=0.0), 'number_density': Dimension(length=-3.0, mass=-0.0, time=-0.0, temperature=-0.0), 'power': Dimension(length=2.0, mass=1.0, time=-3.0, temperature=0.0), 'pressure': Dimension(length=-1.0, mass=1.0, time=-2.0, temperature=0.0), 'temperature': Dimension(length=0.0, mass=0.0, time=0.0, temperature=1), 'time': Dimension(length=0.0, mass=0.0, time=1, temperature=0.0), 'velocity': Dimension(length=1.0, mass=0.0, time=-1.0, temperature=0.0), 'volume': Dimension(length=3.0, mass=0.0, time=0.0, temperature=0.0)}#
Named dimensions accepted wherever a
dimensionargument is taken.
- class physicskit.units.Dimension(length=0.0, mass=0.0, time=0.0, temperature=0.0)[source]#
Bases:
objectPhysical dimension \(L^a M^b T^c \Theta^d\) as an exponent vector.
Dimensions multiply, divide and raise to powers like the quantities they describe, so derived dimensions can be built from base ones.
- Parameters:
Examples
>>> L, M, T = Dimension(length=1), Dimension(mass=1), Dimension(time=1) >>> M * L**2 / T**2 == DIMENSIONS["energy"] True
- physicskit.units.NATURAL_CONSTANTS: dict[str, tuple[Dimension, float]] = {'G': (Dimension(length=3.0, mass=-1.0, time=-2.0, temperature=0.0), 6.6743e-11), 'c': (Dimension(length=1.0, mass=0.0, time=-1.0, temperature=0.0), 299792458.0), 'hbar': (Dimension(length=2.0, mass=1.0, time=-1.0, temperature=0.0), 1.0545718176461565e-34), 'k_B': (Dimension(length=2.0, mass=1.0, time=-2.0, temperature=-1.0), 1.380649e-23)}#
Constants that a natural-unit system can set to 1, as
name -> (dimension, SI value). SI values are fromphysicskit.constants(CODATA values viascipy.constants).
- physicskit.units.SI = UnitSystem(name='SI', anchors=((Dimension(length=1, mass=0.0, time=0.0, temperature=0.0), 1.0), (Dimension(length=0.0, mass=1, time=0.0, temperature=0.0), 1.0), (Dimension(length=0.0, mass=0.0, time=1, temperature=0.0), 1.0), (Dimension(length=0.0, mass=0.0, time=0.0, temperature=1), 1.0)))#
one unit of every dimension is its SI unit. Converting to it is the identity.
- Type:
The SI system itself
- physicskit.units.SUBPACKAGE_CONVENTIONS: dict[str, dict[str, Any]] = {'astro': {'constants': ('G',), 'preset': 'astro_units'}, 'quantum': {'constants': ('hbar',), 'preset': 'quantum_units'}, 'relativity': {'constants': ('G', 'c'), 'preset': 'geometrized_units'}, 'statphys': {'constants': ('k_B',), 'preset': 'statphys_units'}}#
Which constants each subpackage sets to 1, and the preset that builds a matching
UnitSystemonce the remaining free scales are chosen.
- class physicskit.units.UnitSystem(name, anchors)[source]#
Bases:
objectA system of units fixed by a set of anchors.
Most users should build one with a preset (
astro_units(),geometrized_units(),quantum_units(),statphys_units()) or withnatural_units().- Parameters:
- Raises:
ValueError – If an anchor value is not a positive finite number, or redundant anchors disagree.
Examples
A plain “centimetre-gram-second” mechanical system:
>>> cgs = UnitSystem("cgs", ((Dimension(length=1), 1e-2), (Dimension(mass=1), 1e-3), (Dimension(time=1), 1.0))) >>> round(cgs.to_si(1.0, "energy"), 15) # 1 erg in J 1e-07
- classmethod from_dict(data)[source]#
Rebuild a
UnitSystemfromto_dict()output.- Parameters:
- Return type:
- Returns:
UnitSystem
Examples
>>> u = geometrized_units(mass_kg=const.SOLAR_MASS_KG) >>> UnitSystem.from_dict(u.to_dict()) == u True
- from_si(value, dimension)[source]#
Convert
valuefrom SI to this system.- Parameters:
- Return type:
- Returns:
float or ndarray – The same quantity in this system’s units.
Examples
>>> u = geometrized_units(mass_kg=const.SOLAR_MASS_KG) >>> round(u.from_si(const.C, "velocity"), 12) 1.0
- is_determined(dimension)[source]#
Whether the anchors fix the SI size of one unit of
dimension.- Parameters:
dimension (
str|Dimension) – A key ofDIMENSIONSor aDimension.- Return type:
- Returns:
bool
Examples
>>> u = statphys_units(energy_j=1.0e-21) >>> u.is_determined("temperature"), u.is_determined("length") (True, False)
- scale(dimension)[source]#
SI value of one unit of
dimensionin this system.- Parameters:
dimension (
str|Dimension) – A key ofDIMENSIONSor aDimension.- Return type:
- Returns:
float
- Raises:
ValueError – If the system’s anchors do not determine this dimension.
Examples
>>> u = quantum_units(mass_kg=const.ELECTRON_MASS, length_m=5.29177210903e-11) >>> print(f"{u.scale('time'):.4e}") # atomic unit of time, s 2.4189e-17
- scales()[source]#
SI value of one unit for every named dimension this system fixes.
- Return type:
- Returns:
dict of str to float – Keys are the entries of
DIMENSIONSthat are determined.
Examples
>>> sorted(statphys_units(temperature_k=300.0).scales()) ['dimensionless', 'energy', 'entropy', 'temperature']
- to_dict()[source]#
Serialize to a JSON-compatible dict (inverse of
from_dict()).
- to_si(value, dimension)[source]#
Convert
valuefrom this system to SI.- Parameters:
- Return type:
- Returns:
float or ndarray – The same quantity in SI units.
Examples
>>> u = astro_units(length_m=const.ASTRONOMICAL_UNIT_M, mass_kg=const.SOLAR_MASS_KG) >>> round(u.to_si(2 * np.pi, "time") / 86400 / 365.25, 4) # Earth's orbit in years 1.0
- physicskit.units.astro_units(*, length_m, mass_kg)[source]#
Gravitational units, \(G = 1\), as used by
physicskit.astro.The time unit follows from \(G_{SI} = L^3/(M T^2)\), i.e. \(T = \sqrt{L^3/(G_{SI} M)}\) (same as
physicskit.constants.gravitational_unit_system()).- Parameters:
- Return type:
- Returns:
UnitSystem
Examples
With 1 pc and 1 solar mass, one time unit is about 14.9 Myr:
>>> u = astro_units(length_m=const.PARSEC_M, mass_kg=const.SOLAR_MASS_KG) >>> round(u.scale("time") / (1e6 * 365.25 * 86400), 2) 14.91
- physicskit.units.from_pint(quantity, system)[source]#
Convert a
pintquantity intosystem’s units.The dimension is read from the quantity itself. Requires the optional
pintdependency (physicskit[units]).- Parameters:
quantity (
Any) – Any quantity whose dimensionality is built from length, mass, time and temperature.system (
UnitSystem) – The target unit system.
- Return type:
- Returns:
float or ndarray – The magnitude in
system’s units.- Raises:
ValueError – If
quantityinvolves another base dimension (e.g. current).
Examples
>>> import pint >>> ureg = pint.UnitRegistry() >>> from_pint(1476.6 * ureg.meter, geometrized_units(mass_kg=const.SOLAR_MASS_KG)) 0.99997...
- physicskit.units.from_si(value, dimension, system)[source]#
Convert an SI
valueintosystem’s units.Equivalent to
system.from_si(value, dimension).- Parameters:
value (
ArrayLike) – Quantity in SI units.system (
UnitSystem) – The target unit system.
- Return type:
- Returns:
float or ndarray
Examples
>>> round(from_si(300.0, "temperature", statphys_units(temperature_k=300.0)), 12) 1.0
- physicskit.units.geometrized_units(*, mass_kg=None, length_m=None)[source]#
Geometrized units, \(G = c = 1\), as used by
physicskit.relativity.With a mass scale \(M\), one unit of length is \(GM/c^2\) and one unit of time is \(GM/c^3\) (Misner, Thorne & Wheeler, Gravitation, 1973, Box 1.8).
- Parameters:
- Return type:
- Returns:
UnitSystem
Examples
>>> u = geometrized_units(mass_kg=const.SOLAR_MASS_KG) >>> print(f"{u.scale('length'):.5g} m, {u.scale('time') * 1e6:.4g} us") 1476.7 m, 4.926 us
- physicskit.units.natural_units(*constants, name=None, length_m=None, mass_kg=None, time_s=None, energy_j=None, temperature_k=None)[source]#
Build a unit system with the given constants set to 1 and explicit scales.
- Parameters:
*constants (
str) – Names fromNATURAL_CONSTANTS("G","c","hbar","k_B") to set equal to 1.name (
str|None) – Label for the system; defaults to e.g."G=c=1".length_m (
float|None) – SI size of one unit of length, mass, time, energy or temperature.mass_kg (
float|None) – SI size of one unit of length, mass, time, energy or temperature.time_s (
float|None) – SI size of one unit of length, mass, time, energy or temperature.energy_j (
float|None) – SI size of one unit of length, mass, time, energy or temperature.temperature_k (
float|None) – SI size of one unit of length, mass, time, energy or temperature.
- Return type:
- Returns:
UnitSystem
- Raises:
ValueError – For an unknown constant name, or scales that contradict the constants set to 1 (e.g. \(c = 1\) with both a length and a time scale that are not in ratio \(c\)).
Examples
Particle-physics units \(\hbar = c = 1\) with energies in GeV:
>>> gev = natural_units("hbar", "c", energy_j=1e9 * const.ELECTRONVOLT) >>> round(gev.scale("length") * 1e15, 4) # hbar*c / GeV, in fm 0.1973
- physicskit.units.quantum_units(*, mass_kg, length_m=None, energy_j=None)[source]#
Units with \(\hbar = 1\), as used by
physicskit.quantum.Choosing a mass \(m\) and a length \(a\) fixes the energy unit \(\hbar^2/(m a^2)\) and time unit \(m a^2/\hbar\). With the electron mass and the Bohr radius these are the Hartree atomic units (CODATA: \(E_h = 27.211\) eV, \(t_{au} = 2.4189\times10^{-17}\) s).
- Parameters:
- Return type:
- Returns:
UnitSystem
Examples
>>> au = quantum_units(mass_kg=const.ELECTRON_MASS, length_m=5.29177210903e-11) >>> round(const.joules_to_ev(au.scale("energy")), 3) # Hartree, eV 27.211
- physicskit.units.statphys_units(*, energy_j=None, temperature_k=None, length_m=None, mass_kg=None)[source]#
Units with \(k_B = 1\), as used by
physicskit.statphys.With \(k_B = 1\) an energy scale \(\epsilon\) and a temperature scale \(\epsilon/k_B\) are the same choice, which is enough for lattice models (e.g. Ising with coupling \(J = 1\)). Molecular dynamics additionally needs a length \(\sigma\) and mass \(m\), giving the Lennard-Jones reduced time unit \(\tau = \sigma\sqrt{m/\epsilon}\) (Allen & Tildesley, Computer Simulation of Liquids, 2nd ed., 2017, Appendix B).
- Parameters:
energy_j (
float|None) – SI energy of one energy unit (e.g. the coupling \(J\)).temperature_k (
float|None) – SI temperature of one temperature unit, as an alternative toenergy_j. Supply exactly one of the two.length_m (
float|None) – Length and mass scales, needed only to convert mechanical quantities such as time or pressure.mass_kg (
float|None) – Length and mass scales, needed only to convert mechanical quantities such as time or pressure.
- Return type:
- Returns:
UnitSystem
Examples
Lennard-Jones argon (\(\sigma = 3.405\) Å, \(\epsilon/k_B = 119.8\) K, \(m = 39.948\) u) has a time unit of about 2.16 ps:
>>> u = statphys_units(temperature_k=119.8, length_m=3.405e-10, mass_kg=39.948 * 1.66053906660e-27) >>> round(u.scale("time") * 1e12, 2) 2.16
- physicskit.units.to_pint(value, dimension, system, registry=None)[source]#
Convert a natural-unit value into a
pintquantity in SI base units.Requires the optional
pintdependency (physicskit[units]).- Parameters:
value (
ArrayLike) – Quantity insystem’s units.system (
UnitSystem) – The unit systemvalueis expressed in.registry (
Any) – Registry to create the quantity in; defaults topint.get_application_registry().
- Return type:
- Returns:
pint.Quantity
Examples
>>> q = to_pint(1.0, "length", geometrized_units(mass_kg=const.SOLAR_MASS_KG)) >>> q.to("km") <Quantity(1.47662..., 'kilometer')>
- physicskit.units.to_si(value, dimension, system)[source]#
Convert
valuefromsystem’s units to SI.Equivalent to
system.to_si(value, dimension).- Parameters:
value (
ArrayLike) – Quantity insystem’s units.system (
UnitSystem) – The unit systemvalueis expressed in.
- Return type:
- Returns:
float or ndarray
Examples
>>> to_si(1.0, "length", geometrized_units(mass_kg=const.SOLAR_MASS_KG)) > 1476 True
A shared, unit-aware container for simulation output.
Subpackages return results in several shapes: a (times, states) tuple
from the shared physicskit.integrators and the chaos flows, a
(times, positions, velocities) tuple from the symplectic integrators,
the classical SimulationResult,
an orbit array from a chaos map, a quantum
EigenResult, and an rmt
Spectrum. Result is a single
container they can all be converted to, which physicskit.io can
save and load and which knows its units.
The container is opt-in. Subpackages keep returning their own types, and
the from_* adapters below convert them. The adapters read attributes
by name and do not import the subpackages.
Examples
>>> import numpy as np
>>> from physicskit.results import Result
>>> from physicskit.units import geometrized_units
>>> sun = geometrized_units(mass_kg=1.98847e30)
>>> r = Result(np.linspace(0.0, 10.0, 11), np.zeros((11, 2)), units={"times": "time"}, unit_system=sun)
>>> round(float(r.to_si().times[-1]) * 1e6, 2) # 10 M in microseconds
49.26
- class physicskit.results.Result(times, states, metadata=<factory>, units=<factory>, unit_system=None, arrays=<factory>)[source]#
Bases:
objectTime series or other array output, with metadata and units.
- Parameters:
times (
NDArray[Any] |None) – Sample times, shape(n,), or None for output with no time axis (an eigenvalue spectrum, say).states (
NDArray[Any]) – The main output array. Whentimesis given, its first axis must have lengthn.metadata (
dict[str,Any]) – JSON-compatible information such as the integrator name, parameters and provenance. It must be JSON-compatible forphysicskit.io.save()to store it.units (
dict[str,str]) – Maps an array name ("times","states"or a key ofarrays) to a dimension name fromphysicskit.units.DIMENSIONS. Arrays without an entry are treated as dimensionless or of unknown dimension, andconvert()leaves them unchanged.unit_system (
UnitSystem|None) – The system the dimensioned arrays are expressed in. None means unspecified;physicskit.units.SImeans SI.arrays (
dict[str,NDArray[Any]]) – Further named arrays, such as momenta, energies or a spatial grid.
- Raises:
ValueError – If lengths disagree, an array name is reserved or invalid, or a
unitsentry names an unknown array or dimension.
Examples
>>> r = Result([0.0, 0.5, 1.0], [[1.0], [0.5], [0.0]], arrays={"energy": [2.0, 2.0, 2.0]}) >>> r.names ['times', 'states', 'energy'] >>> r["energy"].shape (3,)
- convert(system)[source]#
Return a copy with every dimensioned array expressed in
system.Arrays listed in
unitsare converted through SI; all other arrays and the metadata are copied unchanged.- Parameters:
system (
UnitSystem) – Target unit system.- Return type:
- Returns:
Result
- Raises:
ValueError – If
unitsis non-empty butunit_systemis None, or either system leaves a needed dimension undetermined.
Examples
>>> from physicskit.units import SI, statphys_units >>> r = Result(None, [1.0, 2.0], units={"states": "temperature"}, unit_system=statphys_units(temperature_k=300.0)) >>> r.convert(SI).states array([300., 600.])
- property names: list[str]#
Names of all arrays held, in the order times, states, extras.
- Returns:
list of str
- to_si()[source]#
Return a copy with every dimensioned array in SI units.
Shorthand for
convert(physicskit.units.SI).- Return type:
- Returns:
Result
- unit_system: UnitSystem | None = None#
- physicskit.results.from_eigen_result(result, *, metadata=None, units=None, unit_system=None)[source]#
Wrap a quantum
EigenResult.There is no time axis.
statesholds the wavefunctions, shape(n_states, len(x)), andarraysholdsxandenergies.- Parameters:
result (
Any) – Output ofsolve().metadata (
Mapping[str,Any] |None) – Seefrom_integrator().units (
Mapping[str,str] |None) – Seefrom_integrator().unit_system (
UnitSystem|None) – Seefrom_integrator().
- Return type:
- Returns:
Result
Examples
>>> import numpy as np >>> from physicskit.quantum.core.eigensolvers import NumerovSolver, infinite_well >>> eig = NumerovSolver(np.linspace(0.0, 1.0, 201), infinite_well()).solve(n_states=3) >>> r = from_eigen_result(eig) >>> r.times is None, r.states.shape, r["energies"].shape (True, (3, 201), (3,))
- physicskit.results.from_integrator(output, *, method=None, metadata=None, units=None, unit_system=None)[source]#
Wrap the tuple returned by a
physicskit.integratorsfunction.Accepts
(times, states)fromrk4_integrate(),dopri5_integrate()and the chaos flows’trajectory()methods, or(times, positions, velocities)fromleapfrog_integrate()andyoshida4_integrate(). For the latter,statesis the phase-space trajectory[positions, velocities]stacked along the last axis, and the two halves are also kept asarrays["positions"]andarrays["velocities"].- Parameters:
- Return type:
- Returns:
Result
Examples
>>> import numpy as np >>> r = from_integrator((np.array([0.0, 0.1]), np.ones((2, 1)), np.zeros((2, 1))), method="leapfrog") >>> r.states.shape, r.metadata["method"] ((2, 2), 'leapfrog')
- physicskit.results.from_map_orbit(orbit, *, metadata=None, units=None, unit_system=None)[source]#
Wrap the orbit returned by a chaos map’s
trajectory().Maps are discrete, so
timesis the iteration index0, 1, ...andmetadata["time_kind"]is"iteration".- Parameters:
orbit (
ArrayLike) – The map’s orbit.metadata (
Mapping[str,Any] |None) – Seefrom_integrator().units (
Mapping[str,str] |None) – Seefrom_integrator().unit_system (
UnitSystem|None) – Seefrom_integrator().
- Return type:
- Returns:
Result
Examples
>>> from physicskit.chaos.systems.maps import LogisticMap >>> r = from_map_orbit(LogisticMap(r=3.9).trajectory(n_iter=5)) >>> r.times array([0, 1, 2, 3, 4, 5])
- physicskit.results.from_simulation_result(result, *, metadata=None, units=None, unit_system=None)[source]#
Wrap a classical
SimulationResult.tbecomestimesandybecomesstates.q,pandenergy, when present, go toarrays. Entries ofextrago toarraysif they are arrays and tometadata["extra"]otherwise; values that are not JSON scalars are stored as theirrepr.- Parameters:
result (
Any) – Output of a classical system’sintegrate().metadata (
Mapping[str,Any] |None) – Seefrom_integrator().units (
Mapping[str,str] |None) – Seefrom_integrator().unit_system (
UnitSystem|None) – Seefrom_integrator().
- Return type:
- Returns:
Result
Examples
>>> from physicskit.classical.systems.hamiltonian import HenonHeilesSystem >>> sim = HenonHeilesSystem(q0=[0.1, 0.0], p0=[0.0, 0.2]).integrate((0.0, 1.0), dt=0.01) >>> r = from_simulation_result(sim) >>> r.names, r.metadata["method"] (['times', 'states', 'q', 'p', 'energy'], 'yoshida4')
- physicskit.results.from_spectrum(spectrum, *, metadata=None)[source]#
Wrap an rmt
Spectrum.There is no time axis.
statesholds the raw eigenvalues, shape(n_samples, n).n,beta,ensembleandscalego tometadata, andeigenvectors(if sampled) toarrays. Random-matrix spectra are dimensionless, so no units are attached.- Parameters:
- Return type:
- Returns:
Result
Examples
>>> import physicskit.rmt as rmt >>> r = from_spectrum(rmt.ensembles.GOE(n=4, seed=1).sample(n_samples=3)) >>> r.states.shape, r.metadata["ensemble"], r.metadata["beta"] ((3, 4), 'GOE', 1.0)
Save and load Result objects.
Two formats are supported, chosen by file extension:
.npz(NumPy’s zipped archive), always available. Loading never unpickles anything (allow_pickle=False), so a file from an untrusted source cannot execute code..h5/.hdf5, whenh5pyis installed (pip install "physicskit[hdf5]"). Arrays become datasets that other HDF5 tools can read directly.
Both store the same thing: the times, states and extra arrays,
plus a JSON header with the metadata, units, unit system and a format
version. The metadata must therefore be JSON-compatible. NumPy scalars are
converted to Python numbers, and tuples come back as lists.
Examples
>>> import numpy as np, tempfile, pathlib
>>> from physicskit.results import Result
>>> from physicskit.io import save, load
>>> r = Result(np.linspace(0, 1, 5), np.eye(5), metadata={"method": "rk4"})
>>> with tempfile.TemporaryDirectory() as d:
... back = load(save(r, pathlib.Path(d) / "run.npz"))
>>> back.metadata["method"], np.array_equal(back.states, r.states)
('rk4', True)
- physicskit.io.FORMAT_VERSION = 1#
Version of the on-disk layout written by
save().load()refuses files written by a newer version.
- physicskit.io.load(path, *, format=None)[source]#
Read a
Resultwritten bysave().- Parameters:
- Return type:
- Returns:
Result
- Raises:
ValueError – If the file is not a physicskit result, or was written by a newer format version.
ImportError – For HDF5 when
h5pyis not installed.
- physicskit.io.save(result, path, *, format=None)[source]#
Write
resulttopath, overwriting any existing file.- Parameters:
- Return type:
- Returns:
pathlib.Path – The path written.
- Raises:
TypeError – If the metadata is not JSON-compatible or an array is not numeric or boolean.
ImportError – For HDF5 when
h5pyis not installed.