Source code for veris.model.physical_constants

"""Registry-backed physical and empirical law constants.

Defaults preserve the legacy settings.py parameterizations, including independently
rounded gas constants and latent heats. Exact dependencies are recomputed on
host construction and replacement. Independent values form a frozen JAX PyTree;
dtype is static and dependent laws are reconstructed from those values.
"""

from __future__ import annotations

from dataclasses import dataclass, field, fields
from numbers import Real
from typing import Any

import jax
import jax.numpy as jnp
import numpy as np
from jax.core import Tracer
from jax.typing import ArrayLike

from veris.model.configuration import SETTINGS
from veris.model.metadata import (
    FROM_REGISTRY,
    registry_defaults,
)
from veris.model.physical_parameters import (
    _require_runtime_precision,
    _update_dependencies,
    _validate_host_constants,
)
from veris.model.types import Parameter

PHYSICALCONSTANTS: dict[str, Parameter] = {
    "pressReplFac": Parameter(
        1.0,
        float,
        "Weight of strain-dependent replacement pressure in the ice constitutive law",
        "1",
    ),
    "evpStressRelaxation": Parameter(
        1.0,
        float,
        "Stress damping coefficient setting the EVP constitutive equilibrium",
        "1",
    ),
    "evpShearRelaxation": Parameter(
        0.25,
        float,
        "Deviatoric stress forcing coefficient setting the EVP constitutive equilibrium",
        "1",
    ),
    "minLWdown": Parameter(
        60.0, float, "minimum downward longwave radiation", ":math:`W/m^2`"
    ),
    "maxTIce": Parameter(
        30.0, float, "maximum ice temperature", ":math:`{}^\\circ\\,C`"
    ),
    "minTIce": Parameter(
        -50.0, float, "minimum ice temperature", ":math:`{}^\\circ\\,C`"
    ),
    "minTAir": Parameter(
        -50.0, float, "minimum air temperature", ":math:`{}^\\circ\\,C`"
    ),
    "Area_reg": Parameter(
        0.0225,
        float,
        "Squared ice-concentration regularization (dimensionless)",
        "-",
    ),
    "hIce_reg": Parameter(
        0.010000000000000002,
        float,
        "regularization value for the ice thickness",
        ":math:`m^2`",
    ),
    "wSpeedMin": Parameter(1e-10, float, "minimum wind speed", ":math:`m/s`"),
    "hIce_min": Parameter(1e-05, float, "'minimum' ice thickness", ":math:`m`"),
    "Area_min": Parameter(1e-05, float, "'minimum' ice cover fraction", "-"),
    "cDragMin": Parameter(
        0.25,
        float,
        "minimum of linear ice-ocean drag coefficient",
        ":math:`kg/(m^2\\,s)`",
    ),
    "seaIceLoadFac": Parameter(1.0, float, "factor to scale sea ice loading", "-"),
    "deltaMin": Parameter(
        2e-09, float, "Minimum strain-rate invariant", ":math:`s^{-1}`"
    ),
    "umin_o": Parameter(
        0.5, float, "minimum atm. wind speed over ocean surface", ":math:`m/s`"
    ),
    "umin_i": Parameter(
        1.0, float, "minimum atm. wind speed over ice surface", ":math:`m/s`"
    ),
    "zref": Parameter(10.0, float, "reference height for wind speed", ":math:`m`"),
    "ztref": Parameter(2.0, float, "reference height for air temperature", ":math:`m`"),
    "minActualIceThickness": Parameter(
        0.05,
        float,
        "Minimum actual ice thickness used in thermodynamic growth",
        ":math:`m`",
    ),
    "basalDragSmoothing": Parameter(
        10.0,
        float,
        "Inverse thickness scale of the basal-drag smooth positive part",
        ":math:`m^{-1}`",
    ),
    "basalDragMinArea": Parameter(
        0.01, float, "Minimum ice concentration that enables basal drag", "1"
    ),
    "bulkStabilityLimit": Parameter(
        10.0, float, "Maximum absolute height-to-Obukhov-length ratio", "1"
    ),
    "lanlMinWindSpeed": Parameter(
        1.0,
        float,
        "Minimum open-ocean wind speed in LANL bulk fluxes",
        ":math:`m\\,s^{-1}`",
    ),
    "hCut": Parameter(
        0.15,
        float,
        "Snow thickness at the transition to optically opaque snow albedo",
        ":math:`m`",
    ),
    "rhoIce": Parameter(900.0, float, "density of ice", ":math:`kg/m^3`"),
    "rhoFresh": Parameter(1000.0, float, "density of fresh water", ":math:`kg/m^3`"),
    "rhoSea": Parameter(1026.0, float, "density of sea water", ":math:`kg/m^3`"),
    "rhoAir": Parameter(1.3, float, "density of air", ":math:`kg/m^3`"),
    "rhoSnow": Parameter(330.0, float, "density of snow", ":math:`kg/m^3`"),
    "recip_rhoFresh": Parameter(0.001, float, "1 / rhoFresh", ":math:`m^3/kg`"),
    "recip_rhoSea": Parameter(
        0.0009746588693957114, float, "1 / rhoSea", ":math:`m^3/kg`"
    ),
    "rhoIce2rhoSnow": Parameter(
        2.727272727272727, float, "Ice-to-snow density ratio (dimensionless)", "-"
    ),
    "rhoIce2rhoFresh": Parameter(
        0.9, float, "Ice-to-freshwater density ratio (dimensionless)", "-"
    ),
    "rhoFresh2rhoSnow": Parameter(
        3.0303030303030303,
        float,
        "Freshwater-to-snow density ratio (dimensionless)",
        "-",
    ),
    "dryIceAlb": Parameter(0.75, float, "albedo of dry ice", "-"),
    "dryIceAlb_south": Parameter(
        0.75, float, "albedo of dry ice in the southern hemisphere", "-"
    ),
    "wetIceAlb": Parameter(0.66, float, "albedo of wet ice", "-"),
    "wetIceAlb_south": Parameter(
        0.66, float, "albedo of wet ice in the southern hemisphere", "-"
    ),
    "drySnowAlb": Parameter(0.84, float, "albedo of dry snow", "-"),
    "drySnowAlb_south": Parameter(
        0.84, float, "albedo of dry snow in the southern hemisphere", "-"
    ),
    "wetSnowAlb": Parameter(0.7, float, "albedo of wet snow", "-"),
    "wetSnowAlb_south": Parameter(
        0.7, float, "albedo of wet snow in the southern hemisphere", "-"
    ),
    "wetAlbTemp": Parameter(
        0.0,
        float,
        "temperature above which the wet albedos are used",
        ":math:`{}^\\circ\\,C`",
    ),
    "lhFusion": Parameter(334000.0, float, "latent heat of fusion", ":math:`J/kg`"),
    "lhEvap": Parameter(2500000.0, float, "latent heat of evaporation", ":math:`J/kg`"),
    "lhSublim": Parameter(
        2834000.0, float, "latent heat of sublimation", ":math:`J/kg`"
    ),
    "cpAir": Parameter(1005.0, float, "heat capacity of air", ":math:`J/(kg\\,K)`"),
    "cpWater": Parameter(3986.0, float, "heat capacity of water", ":math:`J/(kg\\,K)`"),
    "stefBoltz": Parameter(
        5.67e-08, float, "Stefan-Boltzmann constant", ":math:`W/m^2/K^4`"
    ),
    "iceEmiss": Parameter(0.95, float, "longwave ice emissivity", "-"),
    "snowEmiss": Parameter(0.95, float, "longwave snow emissivity", "-"),
    "iceConduct": Parameter(
        2.1656, float, "Sea ice thermal conductivity", ":math:`W/m/K`"
    ),
    "snowConduct": Parameter(0.31, float, "Snow thermal conductivity", ":math:`W/m/K`"),
    "shortwave": Parameter(0.3, float, "shortwave ice penetration factor", "-"),
    "tempFrz": Parameter(-1.96, float, "freezing temperature", ":math:`{}^\\circ\\,C`"),
    "dtempFrz_dS": Parameter(
        0.0,
        float,
        "Derivative of freezing temperature with respect to salinity",
        ":math:`{}^\\circ\\,C/(g/kg)`",
    ),
    "saltIce_ref": Parameter(
        0.0, float, "reference salinity of sea ice", ":math:`g/kg`"
    ),
    "dalton": Parameter(
        0.00175,
        float,
        "Dalton number for sensible and latent heat transfer",
        "-",
    ),
    "celsius2K": Parameter(
        273.15,
        float,
        "Offset added to Celsius temperature to obtain kelvin",
        ":math:`K`",
    ),
    "stantonNr": Parameter(0.0056, float, "stanton number", "-"),
    "uStarBase": Parameter(
        0.0125, float, "typical friction velocity beneath sea ice", ":math:`m/s`"
    ),
    "McPheeTaperFac": Parameter(12.5, float, "tapering factor at the ice bottom", "-"),
    "h0": Parameter(0.5, float, "Lead-closing ice thickness", ":math:`m`"),
    "recip_h0": Parameter(2.0, float, "1 / h0", ":math:`m^{-1}`"),
    "h0_south": Parameter(
        0.5, float, "Lead-closing ice thickness in the southern hemisphere", ":math:`m`"
    ),
    "recip_h0_south": Parameter(2.0, float, "1 / h0_south", ":math:`m^{-1}`"),
    "airTurnAngle": Parameter(
        0.0, float, "turning angle of air-ice stress", ":math:`{}^\\circ`"
    ),
    "waterTurnAngle": Parameter(
        0.0, float, "turning angle of water-ice stress", ":math:`{}^\\circ`"
    ),
    "sinWat": Parameter(0.0, float, "sin of waterTurnAngle", "-"),
    "cosWat": Parameter(1.0, float, "cos of waterTurnAngle", "-"),
    "airIceDrag": Parameter(0.0012, float, "air-ice drag coefficient", "-"),
    "airIceDrag_south": Parameter(
        0.0012, float, "air-ice drag coefficient in the southern hemisphere", "-"
    ),
    "waterIceDrag": Parameter(0.0055, float, "water-ice drag coefficient", "-"),
    "waterIceDrag_south": Parameter(
        0.0055, float, "water-ice drag coefficient in the southern hemisphere", "-"
    ),
    "gravity": Parameter(9.81, float, "gravitational acceleration", ":math:`m/s^2`"),
    "PlasDefCoeff": Parameter(
        2.0, float, "axes ratio of the elliptical yield curve", "-"
    ),
    "pStar": Parameter(27500.0, float, "sea ice strength parameter", ":math:`Pa`"),
    "cStar": Parameter(20.0, float, "sea ice strength parameter", "-"),
    "basalDragU0": Parameter(5e-05, float, "basal drag parameter", ":math:`m/s`"),
    "basalDragK1": Parameter(8.0, float, "basal drag parameter", "-"),
    "basalDragK2": Parameter(
        0.0, float, "Basal stress per unit keel excess thickness", ":math:`Pa/m`"
    ),
    "cBasalStar": Parameter(20.0, float, "basal drag parameter", "-"),
    "tensileStrFac": Parameter(0.0, float, "sea ice tensile strength factor", "-"),
    "sideDragCoeff": Parameter(
        0.001, float, "Coastal drag acceleration coefficient", ":math:`m/s^2`"
    ),
    "sideDragU0": Parameter(0.01, float, "side drag critical velocity", ":math:`m/s`"),
    "bolzc": Parameter(
        1.38065e-23, float, "Boltzmann's constant", ":math:`J/K/molecule`"
    ),
    "avogad": Parameter(
        6.02214e26, float, "Avogadro number", ":math:`molecules/kmole`"
    ),
    "rgas": Parameter(
        8314.47, float, "avogad * bolzc - Ideal gas constant", ":math:`J/K/kmole`"
    ),
    "mwdair": Parameter(
        28.966, float, "molecular weight of dry air", ":math:`kg/kmole`"
    ),
    "mwwv": Parameter(
        18.016, float, "molecular weight water vapor", ":math:`kg/kmole`"
    ),
    "rdair": Parameter(
        287.042, float, "RGAS / MWDAIR - dry air gas constant", ":math:`J/K/kg`"
    ),
    "rwv": Parameter(
        461.505, float, "RGAS / MWWV - water vapor constant", ":math:`J/K/kg`"
    ),
    "zvir": Parameter(
        0.608,
        float,
        "(RWV / RDAIR) - 1.0 - Dry-air water-vapor molecular mass ratio",
        "-",
    ),
    "cpdair": Parameter(1004.64, float, "specific heat of dry air", ":math:`J/K/kg`"),
    "cpwv": Parameter(1810.0, float, "specific heat of water vapor", ":math:`J/K/kg`"),
    "cpvir": Parameter(
        0.802,
        float,
        "Humidity correction to dry-air specific heat (cpwv / cpdair - 1)",
        "-",
    ),
    "karman": Parameter(0.4, float, "von Karman constant", "-"),
    "latvap": Parameter(2501000.0, float, "latent heat of evaporation", ":math:`J/kg`"),
    "p0": Parameter(
        100000.0,
        float,
        "reference pressure to compute potential temperature",
        ":math:`Pa`",
    ),
    "cappa": Parameter(0.286, float, "R/Cp", "-"),
    "zzsice": Parameter(0.0005, float, "ice surface roughness", ":math:`m`"),
    "ch": Parameter(0.001, float, "bulk transfer coefficient for sensible heat", "-"),
    "ce": Parameter(0.00115, float, "bulk transfer coefficient for latent heat", "-"),
    "emissivity": Parameter(1.0, float, "surface emissivity", "-"),
    "ocean_emissivity": Parameter(0.985, float, "ocean surface emissivity", "-"),
    "snow_emissivity": Parameter(0.98, float, "snow surface emissivity", "-"),
    "ice_emissivity": Parameter(0.98, float, "ice surface emissivity", "-"),
    "tf0kel": Parameter(273.15, float, "freezing temp of fresh water", ":math:`K`"),
    "gamma_blk": Parameter(
        0.01, float, "adiabatic lapse rate", ":math:`{}^\\circ\\,C/m`"
    ),
    "ocean_albedo": Parameter(0.1, float, "ocean albedo", "-"),
    "ice_albedo": Parameter(0.7, float, "ice albedo", "-"),
    "radius": Parameter(
        6371000.0,
        float,
        "Mean spherical Earth radius used by geopotential-height conversion",
        ":math:`m`",
    ),
    "iceVaporPressureTemperature": Parameter(
        2663.5,
        float,
        "Ice saturation vapor-pressure inverse-temperature coefficient",
        ":math:`K`",
    ),
    "iceVaporPressureLog10Offset": Parameter(
        12.537, float, "Ice saturation vapor-pressure base-10 logarithmic offset", "1"
    ),
    "waterVaporDryAirMassRatio": Parameter(
        0.622,
        float,
        "Water-vapor to dry-air molecular mass ratio in saturation laws",
        "1",
    ),
    "iceSurfacePressure": Parameter(
        100000.0,
        float,
        "Fixed pressure for the ice-surface humidity parameterization",
        ":math:`Pa`",
    ),
    "iceShortwaveExtinction": Parameter(
        1.5,
        float,
        "Exponential shortwave attenuation coefficient within ice",
        ":math:`m^{-1}`",
    ),
    "McPheeTaperArea": Parameter(
        0.4, float, "Ice concentration scale of the McPhee bottom-melt taper", "1"
    ),
    "McPheeTaperSteepness": Parameter(
        7.0,
        float,
        "McPhee bottom-melt taper numerator, divided by McPheeTaperArea",
        "1",
    ),
    "lateralMeltAreaFactor": Parameter(
        0.5,
        float,
        "Lateral concentration-loss factor multiplying reciprocal ice thickness",
        "1",
    ),
    "cesmSaturationHumidityScale": Parameter(
        640380.0,
        float,
        "CESM exponential saturation specific-humidity scale",
        ":math:`kg\\,m^{-3}`",
    ),
    "cesmSaturationHumidityTemperature": Parameter(
        5107.4,
        float,
        "CESM saturation humidity inverse-temperature coefficient",
        ":math:`K`",
    ),
    "augustVaporPressureLog10Offset": Parameter(
        9.4051, float, "August saturation vapor-pressure logarithmic offset", "1"
    ),
    "augustVaporPressureTemperature": Parameter(
        2353.0,
        float,
        "August saturation vapor-pressure inverse-temperature coefficient",
        ":math:`K`",
    ),
    "mmHgToPa": Parameter(
        133.322,
        float,
        "Conversion from millimetres of mercury to pascals",
        ":math:`Pa\\,mmHg^{-1}`",
    ),
    "neutralDragInverseWind": Parameter(
        0.0027,
        float,
        "Reciprocal-wind coefficient in the neutral ocean drag law",
        ":math:`m\\,s^{-1}`",
    ),
    "neutralDragConstant": Parameter(
        0.000142, float, "Constant coefficient in the neutral ocean drag law", "1"
    ),
    "neutralDragLinearWind": Parameter(
        7.64e-05,
        float,
        "Linear-wind coefficient in the neutral ocean drag law",
        ":math:`s\\,m^{-1}`",
    ),
    "cesmUnstableMomentumOffset": Parameter(
        1.571, float, "Historically rounded CESM unstable momentum angle offset", "1"
    ),
    "longwaveHumidityPressureScale": Parameter(
        1000.0,
        float,
        "Humidity pressure scale in the ocean longwave parameterization",
        ":math:`hPa`",
    ),
    "longwaveClearSkyOffset": Parameter(
        0.39, float, "Clear-sky offset in the ocean longwave parameterization", "1"
    ),
    "longwaveHumidityCoefficient": Parameter(
        0.05,
        float,
        "Humidity coefficient in the ocean longwave parameterization",
        ":math:`hPa^{-0.5}`",
    ),
    "seawaterHumidityFactor": Parameter(
        0.98,
        float,
        "Salinity reduction factor for ocean surface saturation humidity",
        "1",
    ),
    "cesmNeutralHeatUnstable": Parameter(
        0.0327,
        float,
        "CESM unstable neutral heat-transfer square-root coefficient",
        "1",
    ),
    "cesmNeutralHeatStable": Parameter(
        0.018, float, "CESM stable neutral heat-transfer square-root coefficient", "1"
    ),
    "cesmNeutralMoisture": Parameter(
        0.0346, float, "CESM neutral moisture-transfer square-root coefficient", "1"
    ),
    "bulkUnstableStabilityCoefficient": Parameter(
        16.0, float, "Unstable Monin-Obukhov similarity coefficient", "1"
    ),
    "bulkStableStabilityCoefficient": Parameter(
        5.0, float, "Magnitude of the negative stable similarity coefficient", "1"
    ),
    "lanlSaturationHumidityScale": Parameter(
        3.797915, float, "LANL saturation specific-humidity scale", "1"
    ),
    "lanlSaturationExponentOffset": Parameter(
        7.93252e-06,
        float,
        "LANL saturation exponent offset multiplying latent heat",
        ":math:`kg\\,J^{-1}`",
    ),
    "lanlSaturationExponentTemperature": Parameter(
        0.002166847,
        float,
        "LANL inverse-temperature exponent coefficient multiplying latent heat",
        ":math:`K\\,kg\\,J^{-1}`",
    ),
    "lanlReferencePressure": Parameter(
        1013.0,
        float,
        "LANL humidity reference pressure in its original hPa convention",
        ":math:`hPa`",
    ),
    "longwaveCloudLatitudes": Parameter(
        (
            -90.0,
            -80.0,
            -70.0,
            -60.0,
            -50.0,
            -40.0,
            -30.0,
            -20.0,
            -10.0,
            -5.0,
            0.0,
            5.0,
            10.0,
            20.0,
            30.0,
            40.0,
            50.0,
            60.0,
            70.0,
            80.0,
            90.0,
        ),
        tuple,
        "Latitude knots for the ocean longwave cloud correction",
        ":math:`{}^\\circ\\mathrm{N}`",
    ),
    "longwaveCloudCoefficients": Parameter(
        (
            0.88,
            0.84,
            0.8,
            0.76,
            0.72,
            0.68,
            0.63,
            0.59,
            0.52,
            0.5,
            0.5,
            0.5,
            0.52,
            0.59,
            0.63,
            0.68,
            0.72,
            0.76,
            0.8,
            0.84,
            0.88,
        ),
        tuple,
        "Cloud correction coefficients corresponding to latitude knots",
        "1",
    ),
}


__all__ = ["PHYSICALCONSTANTS", "PhysicalConstants"]


[docs] @jax.tree_util.register_pytree_node_class @dataclass(frozen=True) @registry_defaults({"dtype": SETTINGS["dtype"]} | PHYSICALCONSTANTS) class PhysicalConstants: """Frozen physical-parameter PyTree initialized from the native registry. Independent scalar/table values are leaves; dtype is static metadata. Host constructors validate authored controls without device discovery. Use with_overrides inside AD; dependent laws follow the base values. """ dtype: str = field(default=FROM_REGISTRY, kw_only=True) pressReplFac: float = FROM_REGISTRY evpStressRelaxation: float = FROM_REGISTRY evpShearRelaxation: float = FROM_REGISTRY Area_min: float = FROM_REGISTRY Area_reg: float = FROM_REGISTRY basalDragMinArea: float = FROM_REGISTRY basalDragSmoothing: float = FROM_REGISTRY bulkStabilityLimit: float = FROM_REGISTRY cDragMin: float = FROM_REGISTRY deltaMin: float = FROM_REGISTRY hIce_min: float = FROM_REGISTRY hIce_reg: float = FROM_REGISTRY lanlMinWindSpeed: float = FROM_REGISTRY maxTIce: float = FROM_REGISTRY minActualIceThickness: float = FROM_REGISTRY minLWdown: float = FROM_REGISTRY minTAir: float = FROM_REGISTRY minTIce: float = FROM_REGISTRY seaIceLoadFac: float = FROM_REGISTRY umin_i: float = FROM_REGISTRY umin_o: float = FROM_REGISTRY wSpeedMin: float = FROM_REGISTRY zref: float = FROM_REGISTRY ztref: float = FROM_REGISTRY rhoIce: float = FROM_REGISTRY rhoFresh: float = FROM_REGISTRY rhoSea: float = FROM_REGISTRY rhoAir: float = FROM_REGISTRY rhoSnow: float = FROM_REGISTRY recip_rhoFresh: float = field(init=False) recip_rhoSea: float = field(init=False) rhoIce2rhoSnow: float = field(init=False) rhoIce2rhoFresh: float = field(init=False) rhoFresh2rhoSnow: float = field(init=False) dryIceAlb: float = FROM_REGISTRY dryIceAlb_south: float = FROM_REGISTRY wetIceAlb: float = FROM_REGISTRY wetIceAlb_south: float = FROM_REGISTRY drySnowAlb: float = FROM_REGISTRY drySnowAlb_south: float = FROM_REGISTRY wetSnowAlb: float = FROM_REGISTRY wetSnowAlb_south: float = FROM_REGISTRY wetAlbTemp: float = FROM_REGISTRY lhFusion: float = FROM_REGISTRY lhEvap: float = FROM_REGISTRY lhSublim: float = field(init=False) cpAir: float = FROM_REGISTRY cpWater: float = FROM_REGISTRY stefBoltz: float = FROM_REGISTRY iceEmiss: float = FROM_REGISTRY snowEmiss: float = FROM_REGISTRY iceConduct: float = FROM_REGISTRY snowConduct: float = FROM_REGISTRY shortwave: float = FROM_REGISTRY tempFrz: float = FROM_REGISTRY dtempFrz_dS: float = FROM_REGISTRY saltIce_ref: float = FROM_REGISTRY dalton: float = FROM_REGISTRY celsius2K: float = FROM_REGISTRY stantonNr: float = FROM_REGISTRY uStarBase: float = FROM_REGISTRY McPheeTaperFac: float = FROM_REGISTRY h0: float = FROM_REGISTRY recip_h0: float = field(init=False) h0_south: float = FROM_REGISTRY recip_h0_south: float = field(init=False) airTurnAngle: float = FROM_REGISTRY waterTurnAngle: float = FROM_REGISTRY sinWat: float = field(init=False) cosWat: float = field(init=False) airIceDrag: float = FROM_REGISTRY airIceDrag_south: float = FROM_REGISTRY waterIceDrag: float = FROM_REGISTRY waterIceDrag_south: float = FROM_REGISTRY gravity: float = FROM_REGISTRY PlasDefCoeff: float = FROM_REGISTRY pStar: float = FROM_REGISTRY cStar: float = FROM_REGISTRY basalDragU0: float = FROM_REGISTRY basalDragK1: float = FROM_REGISTRY basalDragK2: float = FROM_REGISTRY cBasalStar: float = FROM_REGISTRY tensileStrFac: float = FROM_REGISTRY sideDragCoeff: float = FROM_REGISTRY sideDragU0: float = FROM_REGISTRY bolzc: float = FROM_REGISTRY avogad: float = FROM_REGISTRY rgas: float = FROM_REGISTRY mwdair: float = FROM_REGISTRY mwwv: float = FROM_REGISTRY rdair: float = FROM_REGISTRY rwv: float = FROM_REGISTRY zvir: float = FROM_REGISTRY cpdair: float = FROM_REGISTRY cpwv: float = FROM_REGISTRY cpvir: float = FROM_REGISTRY karman: float = FROM_REGISTRY latvap: float = FROM_REGISTRY p0: float = FROM_REGISTRY cappa: float = FROM_REGISTRY zzsice: float = FROM_REGISTRY ch: float = FROM_REGISTRY ce: float = FROM_REGISTRY emissivity: float = FROM_REGISTRY ocean_emissivity: float = FROM_REGISTRY snow_emissivity: float = FROM_REGISTRY ice_emissivity: float = FROM_REGISTRY tf0kel: float = FROM_REGISTRY gamma_blk: float = FROM_REGISTRY ocean_albedo: float = FROM_REGISTRY ice_albedo: float = FROM_REGISTRY radius: float = FROM_REGISTRY iceVaporPressureTemperature: float = FROM_REGISTRY iceVaporPressureLog10Offset: float = FROM_REGISTRY waterVaporDryAirMassRatio: float = FROM_REGISTRY iceSurfacePressure: float = FROM_REGISTRY iceShortwaveExtinction: float = FROM_REGISTRY McPheeTaperArea: float = FROM_REGISTRY McPheeTaperSteepness: float = FROM_REGISTRY lateralMeltAreaFactor: float = FROM_REGISTRY cesmSaturationHumidityScale: float = FROM_REGISTRY cesmSaturationHumidityTemperature: float = FROM_REGISTRY augustVaporPressureLog10Offset: float = FROM_REGISTRY augustVaporPressureTemperature: float = FROM_REGISTRY mmHgToPa: float = FROM_REGISTRY neutralDragInverseWind: float = FROM_REGISTRY neutralDragConstant: float = FROM_REGISTRY neutralDragLinearWind: float = FROM_REGISTRY cesmUnstableMomentumOffset: float = FROM_REGISTRY longwaveHumidityPressureScale: float = FROM_REGISTRY longwaveClearSkyOffset: float = FROM_REGISTRY longwaveHumidityCoefficient: float = FROM_REGISTRY seawaterHumidityFactor: float = FROM_REGISTRY cesmNeutralHeatUnstable: float = FROM_REGISTRY cesmNeutralHeatStable: float = FROM_REGISTRY cesmNeutralMoisture: float = FROM_REGISTRY bulkUnstableStabilityCoefficient: float = FROM_REGISTRY bulkStableStabilityCoefficient: float = FROM_REGISTRY lanlSaturationHumidityScale: float = FROM_REGISTRY lanlSaturationExponentOffset: float = FROM_REGISTRY lanlSaturationExponentTemperature: float = FROM_REGISTRY lanlReferencePressure: float = FROM_REGISTRY longwaveCloudLatitudes: tuple[float, ...] = FROM_REGISTRY longwaveCloudCoefficients: tuple[float, ...] = FROM_REGISTRY hCut: float = FROM_REGISTRY def __post_init__(self) -> None: """Validate authored host values without creating device arrays.""" _validate_host_constants(self)
[docs] @classmethod def base_parameter_names(cls) -> tuple[str, ...]: """Return independent registry values, excluding dtype and derived laws.""" return tuple( item.name for item in fields(cls) if item.init and item.name != "dtype" )
def tree_flatten(self) -> tuple[tuple[Any, ...], str]: """Expose only independent physical values; precision remains static.""" return tuple( getattr(self, name) for name in self.base_parameter_names() ), self.dtype @classmethod def tree_unflatten(cls, dtype: str, values: tuple[Any, ...]) -> PhysicalConstants: """Reconstruct traced values without applying authored-input validation. JAX also builds placeholder/spec trees; those need no dependent algebra. Real transformations reconstruct the dependencies from their base leaves. """ result = object.__new__(cls) object.__setattr__(result, "dtype", dtype) for name, value in zip(cls.base_parameter_names(), values, strict=True): object.__setattr__(result, name, value) numeric = (Real, np.ndarray, np.generic, jax.Array, Tracer) leaves = jax.tree.leaves(values, is_leaf=lambda value: value is None) if leaves and all(isinstance(value, numeric) for value in leaves): _update_dependencies(result) return result
[docs] def with_overrides(self, **parameters: ArrayLike) -> PhysicalConstants: """Return owned base parameters with refreshed dependent quantities. Concrete overrides validate native domains on the host. Scalar tracers retain their dtype/schema for AD; advance reports runtime domain failures through physics_status. Tuples keep the registry's cloud-table contract. """ names = self.base_parameter_names() invalid = parameters.keys() - set(names) if invalid: raise ValueError( f"not independent physical parameters: {', '.join(sorted(invalid))}" ) values = {name: getattr(self, name) for name in names} | parameters traced = any(isinstance(value, Tracer) for value in jax.tree.leaves(values)) if traced: _require_runtime_precision(self.dtype) normalized: dict[str, Any] = {} for name, value in values.items(): array = jnp.asarray(value) if traced else np.asarray(value) if array.dtype.kind not in "fiu": raise TypeError(f"{name} must contain real numeric values") if PHYSICALCONSTANTS[name].type is tuple: if array.ndim != 1: raise ValueError(f"{name} must be a one-dimensional tuple") normalized[name] = ( tuple(array.astype(self.dtype)) if traced else tuple(float(v) for v in array) ) else: if array.shape != (): raise ValueError(f"{name} must be a scalar") normalized[name] = array.astype(self.dtype) if traced else float(array) if traced: return self.tree_unflatten( self.dtype, tuple(normalized[name] for name in names) ) return type(self)(dtype=self.dtype, **normalized)