Source code for skyscapes.physical_model.exojax.components.absorption

"""Absorption opacity components.

``Absorption`` iterates over the atmosphere's :class:`MolecularSpecies`
tuple and sums per-molecule line-list / cross-section contributions.
Each species owns its own opa engine and altitude-resolved mmr profile;
this component is a thin orchestrator with no per-molecule state of
its own.
"""

from __future__ import annotations

import jax.numpy as jnp
from jaxtyping import Array

from .base import AbstractAbsorption, Contribution
from .species import MolecularSpecies


[docs] class Absorption(AbstractAbsorption): """Sum 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). """
[docs] def compute( self, species: tuple[MolecularSpecies, ...], Tarr: Array, pressure: Array, gravity: Array, rt_engine, ) -> Contribution: """Sum per-species absorption optical depth.""" dtau_per_mol = [ rt_engine.opacity_profile_xs( s.opa.xsmatrix(Tarr, pressure), s.profile.evaluate(pressure), s.molmass, gravity, ) for s in species if s.opa is not None ] if not dtau_per_mol: zeros = jnp.zeros((pressure.shape[0], rt_engine.nu_grid.shape[0])) return Contribution( dtau_total=zeros, dtau_scatter=zeros, g_weighted_num=zeros ) dtau = jnp.stack(dtau_per_mol, axis=0).sum(axis=0) zeros = jnp.zeros_like(dtau) return Contribution(dtau_total=dtau, dtau_scatter=zeros, g_weighted_num=zeros)