Source code for scuq.constants

"""Curated physical constants represented as uncertainty-aware quantities.

The measured values in this module are pinned to the 2022 CODATA recommended
values published in NIST Reference on Constants, Units, and Uncertainty,
version 9.0 (May 2024). The exact constants use the defining values of the
International System of Units (SI), 9th edition.

Only the fine-structure constant is introduced as an independent uncertain
input. Vacuum permeability, vacuum permittivity, and vacuum impedance are
derived from that shared input and the exact defining constants. Consequently,
SCUQ retains their physical dependence during uncertainty propagation.

References
----------
NIST
    https://physics.nist.gov/constants
BIPM
    https://www.bipm.org/en/measurement-units/si-defining-constants
"""

from __future__ import annotations

from .quantities import Quantity
from .si import (
    COULOMB,
    FARAD,
    HENRY,
    JOULE,
    KELVIN,
    METER,
    MOLE,
    OHM,
    SECOND,
)
from .ucomponents import UncertainInput
from .units import ONE

CODATA_RELEASE = "2022 CODATA recommended values"
"""Pinned release used for measured physical constants."""

CODATA_SOURCE = "https://physics.nist.gov/constants"
"""Official NIST source for the pinned CODATA release."""

SI_DEFINITION_SOURCE = "https://www.bipm.org/en/measurement-units/si-defining-constants"
"""Official BIPM source for exact SI defining constants."""


[docs] class PhysicalConstant(Quantity): """A :class:`Quantity` protected against in-place mutation. Physical constants participate in ordinary SCUQ arithmetic exactly like other quantities. Arithmetic returns ordinary :class:`Quantity` objects, while augmented assignment and direct changes to the stored unit or value raise :class:`TypeError`. This protects the module-level objects from accidental process-wide modification. Parameters ---------- unit : scuq.units.Unit Canonical SI unit of the constant. value : numbers.Number or scuq.ucomponents.UncertainComponent Exact numeric value or uncertainty expression stored by the constant. """
[docs] def __init__(self, unit, value): object.__setattr__(self, "_physical_constant_locked", False) super().__init__(unit, value) object.__setattr__(self, "_physical_constant_locked", True)
def __setattr__(self, name, value): if getattr(self, "_physical_constant_locked", False) and name in { "_unit", "_value", }: raise TypeError("physical constants cannot be modified") object.__setattr__(self, name, value) def _reject_inplace(self, _other): raise TypeError("physical constants cannot be modified in place") __iadd__ = _reject_inplace __isub__ = _reject_inplace __imul__ = _reject_inplace __itruediv__ = _reject_inplace __idiv__ = _reject_inplace __ipow__ = _reject_inplace
[docs] def __setstate__(self, state): """Restore a pickled constant while preserving its protection.""" unit, value = state object.__setattr__(self, "_physical_constant_locked", False) object.__setattr__(self, "_unit", unit) object.__setattr__(self, "_value", value) object.__setattr__(self, "_physical_constant_locked", True)
def _constant_from_quantity(unit, quantity): """Return a protected constant in ``unit`` from a compatible quantity.""" source_unit = quantity.get_default_unit() return PhysicalConstant(unit, quantity.get_value(source_unit)) SPEED_OF_LIGHT = PhysicalConstant(METER / SECOND, 299_792_458.0) """Speed of light in vacuum, exactly 299 792 458 m/s in the SI.""" c = SPEED_OF_LIGHT PLANCK_CONSTANT = PhysicalConstant(JOULE * SECOND, 6.626_070_15e-34) """Planck constant, exactly 6.626 070 15e-34 J s in the SI.""" h = PLANCK_CONSTANT ELEMENTARY_CHARGE = PhysicalConstant(COULOMB, 1.602_176_634e-19) """Elementary charge, exactly 1.602 176 634e-19 C in the SI.""" e = ELEMENTARY_CHARGE BOLTZMANN_CONSTANT = PhysicalConstant(JOULE / KELVIN, 1.380_649e-23) """Boltzmann constant, exactly 1.380 649e-23 J/K in the SI.""" k_B = BOLTZMANN_CONSTANT AVOGADRO_CONSTANT = PhysicalConstant(ONE / MOLE, 6.022_140_76e23) """Avogadro constant, exactly 6.022 140 76e23 1/mol in the SI.""" N_A = AVOGADRO_CONSTANT _FINE_STRUCTURE_INPUT = UncertainInput(7.297_352_564_3e-3, 1.1e-12) FINE_STRUCTURE_CONSTANT = PhysicalConstant(ONE, _FINE_STRUCTURE_INPUT) """Fine-structure constant with its CODATA 2022 standard uncertainty.""" alpha = FINE_STRUCTURE_CONSTANT _mu_0_expression = ( 2 * FINE_STRUCTURE_CONSTANT * PLANCK_CONSTANT / (ELEMENTARY_CHARGE**2 * SPEED_OF_LIGHT) ) VACUUM_MAGNETIC_PERMEABILITY = _constant_from_quantity(HENRY / METER, _mu_0_expression) """Vacuum magnetic permeability derived from ``2 * alpha * h / (e**2 * c)``.""" mu_0 = VACUUM_MAGNETIC_PERMEABILITY _epsilon_0_expression = 1 / (VACUUM_MAGNETIC_PERMEABILITY * SPEED_OF_LIGHT**2) VACUUM_ELECTRIC_PERMITTIVITY = _constant_from_quantity( FARAD / METER, _epsilon_0_expression ) """Vacuum electric permittivity derived from ``1 / (mu_0 * c**2)``.""" epsilon_0 = VACUUM_ELECTRIC_PERMITTIVITY _Z_0_expression = VACUUM_MAGNETIC_PERMEABILITY * SPEED_OF_LIGHT VACUUM_IMPEDANCE = _constant_from_quantity(OHM, _Z_0_expression) """Vacuum impedance derived from ``mu_0 * c``.""" Z_0 = VACUUM_IMPEDANCE __all__ = [ "CODATA_RELEASE", "CODATA_SOURCE", "SI_DEFINITION_SOURCE", "PhysicalConstant", "SPEED_OF_LIGHT", "PLANCK_CONSTANT", "ELEMENTARY_CHARGE", "BOLTZMANN_CONSTANT", "AVOGADRO_CONSTANT", "FINE_STRUCTURE_CONSTANT", "VACUUM_MAGNETIC_PERMEABILITY", "VACUUM_ELECTRIC_PERMITTIVITY", "VACUUM_IMPEDANCE", "c", "h", "e", "k_B", "N_A", "alpha", "mu_0", "epsilon_0", "Z_0", ]