optmat.gas.infrared#

Vibrational (infrared) contributions to the polarizability, from HITRAN.

An infrared-active molecule has, besides its electronic oscillator-strength distribution, vibrational bands whose strengths add to the polarizability. A band of integrated intensity S (cm/molecule, HITRAN’s definition, which includes the lower-state population at 296 K and stimulated emission) is a dipole oscillator of strength f = S / (pi r_e), with r_e the classical electron radius, in the same units as the electronic oscillator strengths. Each band is represented by one pole whose energy keeps both the band’s total strength and its static contribution: E = sqrt(sum S / sum(S / nu^2)). At optical frequencies the bands add -sum f / omega^2 to the polarizability, small but not negligible in a difference of polarizabilities (phase matching); at zero frequency they add sum f / E^2 (the vibrational polarizability).

Pure rotational bands are left out (their static contribution is orientation, not polarization). The poles describe the index away from the bands. CH4 and N2O also have weak overtone and combination bands in the near infrared (the tables reach 11000 cm^-1, 0.91 um), where the index has resonant structure that one pole per band does not represent.

The band tables are data/external/hitran/<gas>_bands.csv, written by tools/hitran/band_strengths.py (see PROVENANCE.md there).

Module Attributes

GAP_COLUMNS

The numeric columns of a gas's gap table.

DERIVED_TABLES

The derived tables of a gas, in the order derived_digest() hashes them.

Functions

band_systems(gas)

Return a gas's band systems and their rules (OEP 3).

bound_cells(gas)

Return a gas's representation bound per cell of its windows (OEP 3).

derived_digest(gas)

Return the SHA-256 of a gas's derived tables, as a fit records them.

derived_provenance(gas)

Return the provenance lines of a gas's derived tables.

fold_poles(m0, m_minus2, below, above)

Return two pole strengths that keep a band's \(M_0\) and \(M_{-2}\).

gap_cells(gas)

Return a fit's representation error and absorption in its gaps (OEP 3, Q13).

gap_digest(gas)

Return the SHA-256 of a gas's gap table.

gauss_rule(strengths, energies, n)

Return the n-node Gaussian quadrature of a band, as poles.

infrared_bands(gas)

Return a gas's curated infrared bands, strongest first.

infrared_polarizability_au(gas, omega)

Return the vibrational contribution to the polarizability.

infrared_windows(gas)

Return a gas's derived windows and the gaps between them, ascending (OEP 3).

qualified_windows(gas)

Return a gas's windows as qualified wavelength intervals, and its gaps' reasons.

static_infrared_polarizability_au(gas)

Return the vibrational polarizability at zero frequency.

Classes

BandSystem(system, treatment, label, where, ...)

A band system of a gas's derived rules (OEP 3), and its poles.

InfraredBand(label, strength, strength_over_nu2)

One vibrational band (or cross-section window) of a gas.

WindowRecord(kind, low_cm, high_cm, reason, ...)

A qualified window of a gas, or a gap between windows, from the derivation.

class optmat.gas.infrared.BandSystem(system, treatment, label, where, bands, n_lines, span_cm, m0, m_minus2_au, strengths, energies_au)[source]#

Bases: object

A band system of a gas’s derived rules (OEP 3), and its poles.

Attributes:
systemint

Its number in the table.

treatmentstr

rule (a band, or its part between two windows), rotational (every pure rotational line) or folded (the weak bands inside one window, on two poles outside it).

labelstr

The isotopologue and the transition, or the treatment.

wherestr

The gap or window of the derivation its lines lie in.

bandsint

How many bands (or band parts) it represents.

n_linesint

Its number of lines.

span_cmtuple of float

Its lines’ wavenumber range, cm^-1.

m0float

Its lines’ summed oscillator strength.

m_minus2_aufloat

Their summed f / E**2, hartree^-2: the static contribution.

strengthstuple of float

Its poles’ strengths.

energies_autuple of float

Its poles’ energies, hartree.

bands: int#
energies_au: tuple[float, ...]#
label: str#
m0: float#
m_minus2_au: float#
n_lines: int#
span_cm: tuple[float, float]#
strengths: tuple[float, ...]#
system: int#
treatment: str#
where: str#
optmat.gas.infrared.DERIVED_TABLES: tuple[str, ...] = ('band_rules', 'windows', 'bound', 'absorption')#

The derived tables of a gas, in the order derived_digest() hashes them.

optmat.gas.infrared.GAP_COLUMNS: tuple[str, ...] = ('low_cm', 'high_cm', 'b0', 'b2', 'b3', 'absorption_m')#

The numeric columns of a gas’s gap table.

class optmat.gas.infrared.InfraredBand(label, strength, strength_over_nu2)[source]#

Bases: object

One vibrational band (or cross-section window) of a gas.

Attributes:
labelstr

The isotopologue and the upper and lower vibrational quanta (or the window).

strengthfloat

Integrated intensity S, cm/molecule at 296 K, per molecule of the natural isotopic mixture.

strength_over_nu2float

sum S / nu^2, cm^3/molecule.

property energy_au: float#

Return the pole’s energy, hartree.

Returns:
float

wavenumber in atomic units.

label: str#
property oscillator_strength: float#

Return the band’s dipole oscillator strength S / (pi r_e).

Returns:
float

Dimensionless.

strength: float#
strength_over_nu2: float#
property wavenumber: float#

Return the pole’s wavenumber, sqrt(S / sum(S / nu^2)), cm^-1.

Returns:
float

The wavenumber that keeps the band’s static contribution.

class optmat.gas.infrared.WindowRecord(kind, low_cm, high_cm, reason, max_absorption_m, details)[source]#

Bases: object

A qualified window of a gas, or a gap between windows, from the derivation.

Attributes:
kindstr

window or gap.

low_cm, high_cmfloat

Its wavenumber range, cm^-1.

reasonstr

For a gap: absorption, representation, representation: kept band or width.

max_absorption_mfloat

The largest smoothed absorption of the pure gas at the reference state in it, m^-1.

detailsMapping of str to str

The table’s other columns: the criteria at the edges, the largest single-line Lorentz peak and far-wing absorption, the bound over the tolerance, the kept and folded bands.

details: Mapping[str, str]#
high_cm: float#
kind: str#
low_cm: float#
max_absorption_m: float#
reason: str#
optmat.gas.infrared.band_systems(gas)[source]#

Return a gas’s band systems and their rules (OEP 3).

Parameters:
gasGas or str

The species: CO, CO2, CH4 or N2O.

Returns:
tuple of BandSystem

In the table’s order.

optmat.gas.infrared.bound_cells(gas)[source]#

Return a gas’s representation bound per cell of its windows (OEP 3).

Parameters:
gasGas or str

The species: CO, CO2, CH4 or N2O.

Returns:
dict of str to numpy.ndarray

low_cm and high_cm, the cells’ edges (cm^-1), and b0, b2 and b3, the bound on the magnitude of D_m[model] - D_m[reference] in each (atomic units).

optmat.gas.infrared.derived_digest(gas)[source]#

Return the SHA-256 of a gas’s derived tables, as a fit records them.

Parameters:
gasGas or str

The species: CO, CO2, CH4 or N2O.

Returns:
str

The digest of the four tables’ bytes, in DERIVED_TABLES order.

Raises:
DataError

If a table is missing.

optmat.gas.infrared.derived_provenance(gas)[source]#

Return the provenance lines of a gas’s derived tables.

Parameters:
gasGas or str

The species.

Returns:
tuple of str

The # lines: the tool and its commit, the raw inputs’ SHA-256 and query, the parent fit and every setting.

optmat.gas.infrared.fold_poles(m0, m_minus2, below, above)[source]#

Return two pole strengths that keep a band’s \(M_0\) and \(M_{-2}\).

A weak band inside a window is folded onto two poles outside it, at the nearest rule nodes below and above the window (OEP 3, section 4). The strengths solve \(f_1 + f_2 = M_0\) and \(f_1/E_1^2 + f_2/E_2^2 = M_{-2}\); both are positive because the band’s \(\bar E = (M_0/M_{-2})^{1/2}\) lies between the two energies.

Parameters:
m0float

The band’s summed oscillator strength, > 0.

m_minus2float

Its summed f / E**2, hartree^-2, > 0.

belowfloat

The lower pole’s energy, hartree.

abovefloat

The upper pole’s energy, hartree.

Returns:
tuple of float

The strengths at below and above.

Raises:
ValueError

If \(\bar E\) does not lie strictly between the two energies.

Examples

>>> fold_poles(2.0, 1.25, 1.0, 2.0)
(1.0, 1.0)
optmat.gas.infrared.gap_cells(gas)[source]#

Return a fit’s representation error and absorption in its gaps (OEP 3, Q13).

Written by tools/hitran/gap_bound.py for the stored fit, against the same smoothed line-by-line reference as bound_cells(), in the fit’s gaps from 12.5 um to the top of the absorption grid, where a mixture holding the gas as a trace may still be qualified.

Parameters:
gasGas or str

The species.

Returns:
dict of str to numpy.ndarray or None

low_cm and high_cm, the cells’ edges (cm^-1); b0, b2 and b3, the largest magnitude of D_m[fit] - D_m[reference] in each (atomic units, infinite in a cell holding a pole of the fit); absorption_m, the pure gas’s largest smoothed absorption at 101325 Pa and 296 K (m^-1); and pole, True where a pole lies in the cell. None for a gas without the table.

optmat.gas.infrared.gap_digest(gas)[source]#

Return the SHA-256 of a gas’s gap table.

Parameters:
gasGas or str

The species: CO, CO2, CH4 or N2O.

Returns:
str

The digest of <gas>_gap_bound.csv.

optmat.gas.infrared.gauss_rule(strengths, energies, n)[source]#

Return the n-node Gaussian quadrature of a band, as poles.

A band of lines of oscillator strengths \(f_\ell\) at energies \(E_\ell\) is a positive measure with weights \(w_\ell = f_\ell / E_\ell^2\) at \(x_\ell = E_\ell^2\); its contribution to the polarizability, \(\sum_\ell f_\ell / (E_\ell^2 - \omega^2)\), is the measure’s Stieltjes transform at \(s = \omega^2\) (OEP 3, section 4). The rule’s nodes and weights are the eigenvalues and the squared first eigenvector components, times the total weight, of the measure’s Jacobi matrix (Golub and Welsch 1969, eq. 2.6), which the Lanczos process builds from the lines. The rule reproduces the moments \(\mu_0, \ldots, \mu_{2n-1}\): the band’s static contribution \(M_{-2} = \mu_0\), its optical-side limit \(M_0 = \mu_1\), and \(M_2, \ldots, M_{4n-4}\). One node is the single pole per band of infrared_bands().

Parameters:
strengthsnumpy.ndarray

The lines’ oscillator strengths, dimensionless, > 0.

energiesnumpy.ndarray

Their energies, hartree, > 0.

nint

The largest number of nodes, >= 1. A band with fewer distinct lines gets its exact rule with fewer nodes.

Returns:
tuple of numpy.ndarray

The poles’ strengths W_j X_j and energies X_j**0.5, ascending in energy, every strength positive and every energy inside the lines’ span.

Raises:
ValueError

If n < 1, there are no lines, or a strength or energy is not positive.

Examples

>>> f, e = gauss_rule(np.array([1.0, 1.0]), np.array([1.0, 2.0]), 1)
>>> round(float(f[0]), 12), round(float(e[0]), 12)  # E = (M0 / M_-2)^(1/2)
(2.0, 1.264911064067)
optmat.gas.infrared.infrared_bands(gas)[source]#

Return a gas’s curated infrared bands, strongest first.

Parameters:
gasGas or str

The species.

Returns:
tuple of InfraredBand

Its bands.

Raises:
DataError

If no band table is curated for the gas (it is infrared-inactive, or not yet done).

optmat.gas.infrared.infrared_polarizability_au(gas, omega)[source]#

Return the vibrational contribution to the polarizability.

Parameters:
gasGas or str

The species.

omeganumpy.ndarray

Photon energy, hartree (away from the bands themselves).

Returns:
numpy.ndarray

sum_b f_b / (E_b^2 - omega^2), atomic units.

optmat.gas.infrared.infrared_windows(gas)[source]#

Return a gas’s derived windows and the gaps between them, ascending (OEP 3).

Parameters:
gasGas or str

The species: CO, CO2, CH4 or N2O.

Returns:
tuple of WindowRecord

Every window and gap from 12.5 um to the parent fit’s shortest wavelength.

optmat.gas.infrared.qualified_windows(gas)[source]#

Return a gas’s windows as qualified wavelength intervals, and its gaps’ reasons.

Parameters:
gasGas or str

The species: CO, CO2, CH4 or N2O.

Returns:
tuple

The intervals, vacuum wavelength in nm, ascending; and the reason of each gap between two neighbouring intervals, in the same order.

optmat.gas.infrared.static_infrared_polarizability_au(gas)[source]#

Return the vibrational polarizability at zero frequency.

Parameters:
gasGas or str

The species.

Returns:
float

sum_b f_b / E_b^2, atomic units.

Examples

>>> round(static_infrared_polarizability_au("SF6"), 1)
13.9