skyscapes.physical_model.exojax.components#
Composable physics components for ExoJaxPhysicalModel.
Each component encapsulates one piece of atmospheric physics (temperature-pressure profile, line absorption, Rayleigh scattering, clouds, surface) and exposes a uniform contract:
compute_*(per_planet_args, ...) -> Contribution
where Contribution carries the per-layer optical-property
arrays (dtau_total, dtau_scatter, g_weighted_num) that the
atmosphere combines before passing to the 2-stream RT solver. Surface
and T-P components have analogous compute methods that return their
respective quantities.
To swap physics: replace one component instance with another that
implements the same contract (e.g. GrayCloud -> NoCloud,
RayleighScattering -> NullScattering). Per-planet PyTree leaves
live on the components themselves, so HMC over their parameters
“just works” with eqx.filter_vmap or jax.vmap.
Submodules#
- skyscapes.physical_model.exojax.components.absorption
- skyscapes.physical_model.exojax.components.base
- skyscapes.physical_model.exojax.components.clouds
- skyscapes.physical_model.exojax.components.mie_cloud
- skyscapes.physical_model.exojax.components.mmr_profile
- skyscapes.physical_model.exojax.components.scattering
- skyscapes.physical_model.exojax.components.species
- skyscapes.physical_model.exojax.components.surface
- skyscapes.physical_model.exojax.components.tp
Attributes#
Classes#
Sum of per-species line-list / cross-section absorption. |
|
Per-layer absorption opacity from line lists / cross-sections. |
|
Per-layer cloud opacity (mixed scattering + absorption). |
|
Per-layer scattering opacity (e.g. Rayleigh). |
|
Bottom-of-atmosphere reflectivity. |
|
Temperature-pressure profile. |
|
Per-layer optical-property contribution from one component. |
|
Single-layer gray-scattering cloud. |
|
Disable cloud opacity: zero contribution. |
|
Single-layer cloud with Mie-scattering optical properties. |
|
Per-species mass-mixing-ratio profile evaluated at layer pressures. |
|
Well-mixed gas: constant mmr at every layer. |
|
Gaussian-in-log-pressure peak; canonical for O3. |
|
Constant below a step pressure, drops sharply above; canonical for H2O. |
|
Disable scattering entirely: contributes zero opacity. |
|
Rayleigh scattering from tracked species + optional bulk residual. |
|
Build instructions for the implicit residual gas. |
|
Implicit residual gas filling the unallocated mass fraction. |
|
One atmospheric molecule with an altitude-resolved mixing ratio. |
|
Build instructions for one molecule. |
|
Wavelength-independent (gray) Lambertian surface. |
|
Wavelength-dependent surface reflectivity. |
|
Power-law T-P profile: |
Functions#
|
Build a Mie cloud component by pre-computing Mie params. |
|
Construct (molmass, rayleigh_xs) for the implicit residual gas. |
|
Construct (molmass, opa, rayleigh_xs) for one molecule. |
Package Contents#
- class skyscapes.physical_model.exojax.components.Absorption[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractAbsorptionSum of per-species line-list / cross-section absorption.
Iterates over the species tuple, skipping any with
opa is None(e.g. a species included purely for its Rayleigh contribution).- compute(species, Tarr, pressure, gravity, rt_engine)[source]#
Sum per-species absorption optical depth.
- Parameters:
species (tuple[skyscapes.physical_model.exojax.components.species.MolecularSpecies, Ellipsis])
Tarr (jaxtyping.Array)
pressure (jaxtyping.Array)
gravity (jaxtyping.Array)
- Return type:
skyscapes.physical_model.exojax.components.base.Contribution
- class skyscapes.physical_model.exojax.components.AbstractAbsorption[source]#
Bases:
equinox.ModulePer-layer absorption opacity from line lists / cross-sections.
Concrete implementations iterate over the atmosphere’s
MolecularSpeciestuple, calling each species’opaengine and summing the contributions.- abstractmethod compute(species, Tarr, pressure, gravity, rt_engine)[source]#
Absorption contribution.
dtau_scatterandg_weighted_numare zero for pure absorbers, but the return shape is the same as for scattering components so the atmosphere can combine them uniformly.- Parameters:
species (tuple[skyscapes.physical_model.exojax.components.species.MolecularSpecies, Ellipsis])
Tarr (jaxtyping.Array)
pressure (jaxtyping.Array)
gravity (jaxtyping.Array)
- Return type:
- class skyscapes.physical_model.exojax.components.AbstractClouds[source]#
Bases:
equinox.ModulePer-layer cloud opacity (mixed scattering + absorption).
- abstractmethod compute(log_pressure_bar_scalar, log_opt_depth_scalar, pressure, n_nu)[source]#
Cloud contribution.
For a single-scattering-albedo cloud the scattering and absorption parts are both nonzero; for a purely scattering cloud
dtau_total == dtau_scatter.- Parameters:
log_pressure_bar_scalar (jaxtyping.Array)
log_opt_depth_scalar (jaxtyping.Array)
pressure (jaxtyping.Array)
n_nu (int)
- Return type:
- class skyscapes.physical_model.exojax.components.AbstractScattering[source]#
Bases:
equinox.ModulePer-layer scattering opacity (e.g. Rayleigh).
- abstractmethod compute(species, bulk, gravity, rt_engine, n_layers, n_nu)[source]#
Scattering contribution from tracked species + optional bulk gas.
For a pure scatterer
dtau_total == dtau_scatter;g_weighted_numis zero for isotropic Rayleigh.- Parameters:
species (tuple[skyscapes.physical_model.exojax.components.species.MolecularSpecies, Ellipsis])
bulk (skyscapes.physical_model.exojax.components.species.BulkGasResidual | None)
gravity (jaxtyping.Array)
n_layers (int)
n_nu (int)
- Return type:
- class skyscapes.physical_model.exojax.components.AbstractSurface[source]#
Bases:
equinox.ModuleBottom-of-atmosphere reflectivity.
- class skyscapes.physical_model.exojax.components.AbstractTPProfile[source]#
Bases:
equinox.ModuleTemperature-pressure profile.
- class skyscapes.physical_model.exojax.components.Contribution[source]#
Bases:
NamedTuplePer-layer optical-property contribution from one component.
- Fields:
- dtau_total: Layer optical depth this component adds to the total
opacity budget, shape
(n_layers, n_nu).- dtau_scatter: Subset of
dtau_totalthat is scattering (non-absorbing), shape
(n_layers, n_nu). For a pure absorber this is zero. For Rayleighssa=1so it equalsdtau_total. For a partly-absorbing cloud with single- scattering albedossa_c, this isssa_c * dtau_cloud.- g_weighted_num:
g * dtau_scatternumerator for the weighted- average asymmetry parameter, shape
(n_layers, n_nu). Rayleigh contributes zero (isotropic,g=0). A cloud with asymmetryg_ccontributesg_c * ssa_c * dtau_cloud.
- dtau_total: jaxtyping.Array#
- dtau_scatter: jaxtyping.Array#
- g_weighted_num: jaxtyping.Array#
- class skyscapes.physical_model.exojax.components.GrayCloud[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractCloudsSingle-layer gray-scattering cloud.
The total cloud scattering optical depth is distributed across layers via a Gaussian in log-pressure (softmax-normalised so the weights are well-defined even when the cloud pressure is far outside the layer grid – useful for ablation runs with
log_opt_depth = -inf).Wavelength-grey: the cloud’s cross-section is constant across the spectrum. A Mie cloud with composition-dependent scattering would be a separate component implementing the same contract.
- Attributes (PyTree leaves, fittable):
log_pressure_bar: Log10 cloud-deck pressure [bar], shape
(K,). log_opt_depth: Log10 of the vertically-integrated cloudscattering optical depth, shape
(K,).- Static attributes (configuration):
ssa: Single-scattering albedo (default 1.0, pure scattering). g: Asymmetry parameter (default 0.85, forward-peaked). log_sigma: Vertical-distribution width in log10(P) [dex].
- log_pressure_bar: jaxtyping.Array#
- log_opt_depth: jaxtyping.Array#
- compute(log_pressure_bar_scalar, log_opt_depth_scalar, pressure, n_nu)[source]#
Gray cloud contribution at a single pressure level.
- Parameters:
log_pressure_bar_scalar (jaxtyping.Array)
log_opt_depth_scalar (jaxtyping.Array)
pressure (jaxtyping.Array)
n_nu (int)
- Return type:
skyscapes.physical_model.exojax.components.base.Contribution
- class skyscapes.physical_model.exojax.components.NoCloud[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractCloudsDisable cloud opacity: zero contribution.
Equivalent to a
GrayCloudwithlog_opt_depth = -infbut structurally explicit, so thatisinstance(atm.clouds, NoCloud)documents intent in code that builds cloud-free atmospheres.- compute(log_pressure_bar_scalar, log_opt_depth_scalar, pressure, n_nu)[source]#
Return zero-everywhere cloud contribution.
log_pressure_bar_scalarandlog_opt_depth_scalarare accepted for parity withGrayCloudbut unused.- Parameters:
log_pressure_bar_scalar (jaxtyping.Array)
log_opt_depth_scalar (jaxtyping.Array)
pressure (jaxtyping.Array)
n_nu (int)
- Return type:
skyscapes.physical_model.exojax.components.base.Contribution
- class skyscapes.physical_model.exojax.components.MieCloud[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractCloudsSingle-layer cloud with Mie-scattering optical properties.
The total cloud scattering optical depth is distributed vertically via a softmax-Gaussian in log-pressure (same as
GrayCloud). What’s different is that the single-scattering albedo and asymmetry parameter come from pre-computed Mie cross-sections rather than being scalar constants – they vary with wavelength according to the condensate’s refractive index n(lambda) + k(lambda).- Attributes (PyTree leaves, fittable):
log_pressure_bar: Log10 cloud-deck pressure [bar], shape
(K,). log_opt_depth: Log10 of the vertically-integrated cloudextinction optical depth, shape
(K,).
Pre-computed Mie quantities (built at engine time, shared across planets):
- ssa_grid: Single-scattering albedo on the wavenumber grid,
shape
(n_nu,).sigma_scattering / sigma_extinction.- g_grid: Asymmetry parameter on the wavenumber grid,
shape
(n_nu,).
- Static config:
- condensate: Condensate name (
"H2O","H2O_ice", "MgSiO3", etc.). Matters for the repr; the actual Mie params are baked into ssa_grid and g_grid.
rg_um: Geometric mean particle radius [um]. sigmag: Geometric standard deviation of the lognormal size
distribution.
- log_sigma: Cloud-deck vertical Gaussian half-width in
log10(pressure) [dex].
- condensate: Condensate name (
- log_pressure_bar: jaxtyping.Array#
- log_opt_depth: jaxtyping.Array#
- ssa_grid: jaxtyping.Array#
- g_grid: jaxtyping.Array#
- compute(log_pressure_bar_scalar, log_opt_depth_scalar, pressure, n_nu)[source]#
Mie-cloud contribution: gray-depth distribution, spectral ssa/g.
- Parameters:
log_pressure_bar_scalar (jaxtyping.Array)
log_opt_depth_scalar (jaxtyping.Array)
pressure (jaxtyping.Array)
n_nu (int)
- Return type:
skyscapes.physical_model.exojax.components.base.Contribution
- skyscapes.physical_model.exojax.components.build_mie_cloud(*, nu_grid, log_pressure_bar, log_opt_depth, condensate='H2O', rg_um=10.0, sigmag=2.0, log_sigma=DEFAULT_CLOUD_LOG_SIGMA)[source]#
Build a Mie cloud component by pre-computing Mie params.
On first use for a given condensate this triggers two downloads / computations cached under
./.database/particulates/virga/:Refractive-index file (small, fetched from Zenodo).
Mie-grid lookup table (built locally via PyMieScatt; takes a couple of minutes per condensate). Subsequent calls reuse the cache.
- Args:
- nu_grid: Wavenumber grid [cm^-1] from
build_exojax_engines().
log_pressure_bar: Per-planet log10 cloud pressure [bar]. log_opt_depth: Per-planet log10 total cloud extinction tau. condensate: Condensate name. ExoJAX/Virga ships e.g.
"H2O","H2O_ice","NH3","MgSiO3","Mg2SiO4","Fe","KCl","Na2S","ZnS","MnS","Cr","Al2O3","TiO2".- rg_um: Mean particle radius [um] of the lognormal size
distribution.
sigmag: Geometric standard deviation of the size distribution. log_sigma: Vertical-distribution Gaussian half-width [dex].
- Returns:
A
MieCloudinstance ready to drop intoExoJaxPhysicalModel.
- class skyscapes.physical_model.exojax.components.AbstractMmrProfile[source]#
Bases:
equinox.ModulePer-species mass-mixing-ratio profile evaluated at layer pressures.
- class skyscapes.physical_model.exojax.components.ConstantMmr[source]#
Bases:
AbstractMmrProfileWell-mixed gas: constant mmr at every layer.
Use for gases with chemical lifetimes longer than mixing timescales in the modelled pressure range (CO2, CH4, O2, N2, etc. in troposphere + lower stratosphere).
- Attributes:
log_mmr: Log10 mass-mixing ratio, shape
(K,)(per planet).
- log_mmr: jaxtyping.Array#
- class skyscapes.physical_model.exojax.components.StratosphericPeakMmr[source]#
Bases:
AbstractMmrProfileGaussian-in-log-pressure peak; canonical for O3.
mmr(P) = 10**log_peak_mmr * exp(-0.5 * ((log10(P) - log_peak_pressure_bar) / log_sigma_decades)**2).For Earth’s O3:
log_peak_pressure_bar = log10(0.01) = -2(10 mbar, ~30 km altitude),log_sigma_decades = 0.5.- Attributes:
log_peak_mmr: Log10 of the peak mmr, shape
(K,). log_peak_pressure_bar: Log10 pressure [bar] at peak,(K,). log_sigma_decades: Gaussian width in log10-pressure,(K,).
- log_peak_mmr: jaxtyping.Array#
- log_peak_pressure_bar: jaxtyping.Array#
- log_sigma_decades: jaxtyping.Array#
- class skyscapes.physical_model.exojax.components.TroposphericMmr[source]#
Bases:
AbstractMmrProfileConstant below a step pressure, drops sharply above; canonical for H2O.
Uses a sigmoid in log-pressure for smooth transition (differentiable for HMC retrievals). For Earth’s H2O: tropospheric ~3e-3 below 0.1 bar, ~3e-6 above.
- Attributes:
log_mmr_below: Log10 mmr at high pressure (below cold trap),
(K,). log_mmr_above: Log10 mmr at low pressure (above cold trap),(K,). log_pressure_step_bar: Log10 transition pressure [bar],(K,). log_transition_width_decades: Width of the sigmoid transitionin log10-pressure,
(K,). Smaller = sharper step.
- log_mmr_below: jaxtyping.Array#
- log_mmr_above: jaxtyping.Array#
- log_pressure_step_bar: jaxtyping.Array#
- log_transition_width_decades: jaxtyping.Array#
- class skyscapes.physical_model.exojax.components.NullScattering[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractScatteringDisable scattering entirely: contributes zero opacity.
Useful for ablation studies (e.g. quantifying how much Rayleigh affects a retrieval) and for atmospheres where scattering is negligible.
- compute(species, bulk, gravity, rt_engine, n_layers, n_nu)[source]#
Return zero-everywhere contribution.
- Parameters:
species (tuple[skyscapes.physical_model.exojax.components.species.MolecularSpecies, Ellipsis])
bulk (skyscapes.physical_model.exojax.components.species.BulkGasResidual | None)
gravity (jaxtyping.Array)
n_layers (int)
n_nu (int)
- Return type:
skyscapes.physical_model.exojax.components.base.Contribution
- class skyscapes.physical_model.exojax.components.RayleighScattering[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractScatteringRayleigh scattering from tracked species + optional bulk residual.
Iterates over the atmosphere’s species tuple plus the bulk gas (if present), computing each gas’s contribution from its own
rayleigh_xsandmolmass. The bulk gas’s mass-mixing ratio is computed dynamically asmax(0, 1 - sum(tracked mmrs)).To disable per-species Rayleigh while keeping the bulk: set the species’
rayleigh_xsto zeros. To disable scattering entirely: useNullScattering.- compute(species, bulk, gravity, rt_engine, n_layers, n_nu)[source]#
Sum tracked-species + bulk-gas Rayleigh contributions.
Bulk gas mmr is computed per-layer as
max(0, 1 - sum(species profiles at this pressure)), so altitude variation of the tracked species translates into altitude variation of the bulk-gas residual.- Parameters:
species (tuple[skyscapes.physical_model.exojax.components.species.MolecularSpecies, Ellipsis])
bulk (skyscapes.physical_model.exojax.components.species.BulkGasResidual | None)
gravity (jaxtyping.Array)
n_layers (int)
n_nu (int)
- Return type:
skyscapes.physical_model.exojax.components.base.Contribution
- skyscapes.physical_model.exojax.components.BULK_GAS_RECIPES: dict[str, BulkGasRecipe]#
- skyscapes.physical_model.exojax.components.MOLECULE_RECIPES: dict[str, MoleculeRecipe]#
- class skyscapes.physical_model.exojax.components.BulkGasRecipe[source]#
Build instructions for the implicit residual gas.
- Attributes:
- name: Gas name; must match an ExoJAX polarizability key (or
provide
polarizability_override).
molmass: Molar mass [g/mol]. polarizability_override: Override polarizability if missing
from ExoJAX’s table.
- class skyscapes.physical_model.exojax.components.BulkGasResidual[source]#
Bases:
equinox.ModuleImplicit residual gas filling the unallocated mass fraction.
The mass-mixing ratio is computed dynamically as
max(0, 1 - sum(tracked species mmrs)). Contributes only to Rayleigh scattering (no line-list absorption is associated with the bulk gas in this model – N2 is essentially transparent across 300–1100 nm, H2/He likewise).- Attributes:
name: Gas name, e.g.
"N2"for Earth or"H2"for gas giants. molmass: Molar mass [g/mol]. rayleigh_xs: Rayleigh cross-section [cm^2/molecule] on theatmosphere’s wavenumber grid, shape
(n_nu,).
- rayleigh_xs: jaxtyping.Array#
- class skyscapes.physical_model.exojax.components.MolecularSpecies[source]#
Bases:
equinox.ModuleOne atmospheric molecule with an altitude-resolved mixing ratio.
The mixing ratio is encoded as a profile component (e.g.
ConstantMmrfor well-mixed gases,StratosphericPeakMmrfor O3,TroposphericMmrfor H2O) rather than a single scalar, so altitude variation is represented explicitly.- Attributes:
- profile: Per-species mmr profile. Owns the fittable
log-mixing-ratio leaves.
name: Molecule name, e.g.
"H2O". molmass: Molar mass [g/mol]. opa: Opacity engine. Either an ExoJAXOpaPremodit(forHITRAN-backed line-list molecules) or
O3ChappuisOpacity(for visible cross-section absorbers like O3). May beNoneif the species contributes only Rayleigh scattering.- rayleigh_xs: Pre-computed Rayleigh cross-section
[cm^2/molecule] on the atmosphere’s wavenumber grid, shape
(n_nu,). Set to all-zeros to disable per-species Rayleigh contribution.
- opa: Any#
- rayleigh_xs: jaxtyping.Array#
- class skyscapes.physical_model.exojax.components.MoleculeRecipe[source]#
Build instructions for one molecule.
- Attributes:
- name: Molecule name (must match ExoJAX’s HITRAN / polarizability
keys when those tables apply).
- psg_xs_url: If set, use a PSG cross-section file at this URL
(
PsgCrossSectionOpacity) instead of an ExoJAX line-list opa. Required for species whose absorption is dominated by electronic transitions in the visible/NIR (e.g. O3 Chappuis, SO2 UV).- psg_xs_molmass: Molar mass [g/mol]; required when
psg_xs_url is set since we can’t extract it from HITRAN in that case.
- polarizability_override: Explicit polarizability [cm^3] for the
Rayleigh cross-section, used when ExoJAX’s table doesn’t have an entry.
NoneletsOpaRayleighlook it up.
- skyscapes.physical_model.exojax.components.build_bulk_prebuilt(*, name, nu_grid)[source]#
Construct (molmass, rayleigh_xs) for the implicit residual gas.
- skyscapes.physical_model.exojax.components.build_species_prebuilt(*, name, nu_grid, nu_min, nu_max, databases_dir, crit)[source]#
Construct (molmass, opa, rayleigh_xs) for one molecule.
Used by
build_exojax_engines; not typically called by users directly. Returns the static parts of aMolecularSpecies(everything exceptlog_mmr).
- class skyscapes.physical_model.exojax.components.FlatSurface[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractSurfaceWavelength-independent (gray) Lambertian surface.
Equivalent to
WavelengthDependentSurfacewith a flat spectrum but structurally explicit; useful when callers want to document “I am intentionally using a featureless surface”.- Attributes:
log_albedo: Log10 surface albedo per planet, shape
(K,).
- log_albedo: jaxtyping.Array#
- class skyscapes.physical_model.exojax.components.WavelengthDependentSurface[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractSurfaceWavelength-dependent surface reflectivity.
The bottom-of-atmosphere reflectivity is
10**log_albedo * spectrum: thelog_albedoPyTree leaf is a per-planet fittable scaling, andspectrumis a fixed wavelength-dependent profile (vegetation red-edge, water absorption, snow/ice, …) shared across planets.- Attributes:
log_albedo: Log10 surface albedo scaling per planet, shape
(K,). spectrum: Wavelength-dependent reflectivity profile,shape
(n_nu,). Defaults to flat ones for “no spectral shape; albedo is constant across the band”.
- log_albedo: jaxtyping.Array#
- spectrum: jaxtyping.Array#
- compute_refl(log_albedo_scalar, n_nu)[source]#
Return wavelength-dependent surface reflectivity.
n_nuis accepted for parity withFlatSurfacebut unused – the wavelength axis comes fromself.spectrum.- Parameters:
log_albedo_scalar (jaxtyping.Array)
n_nu (int)
- Return type:
jaxtyping.Array
- class skyscapes.physical_model.exojax.components.PowerLawTPProfile[source]#
Bases:
skyscapes.physical_model.exojax.components.base.AbstractTPProfilePower-law T-P profile:
T(P) = T_eq * P^alpha.The two parameters are PyTree leaves but they are passed to
compute_Tarr()as scalar args rather than being read fromselfso the atmosphere can vmap over per-planet axes without extra plumbing.- Attributes:
T_eq_K: Reference temperature at 1 bar [K], shape
(K,). T_alpha: Power-law exponent, shape(K,).
- T_eq_K: jaxtyping.Array#
- T_alpha: jaxtyping.Array#