Source code for pyrad.lbl.hitran.spectral_lines

from copy import copy as shallow_copy

from numpy import asarray, copy, exp, searchsorted, sqrt, zeros

from ..tips import TIPS_REFERENCE_TEMPERATURE


c2 = -1.4387768795689562  # (hc/k) [K cm].
reference_temperature = 296.  # [K].


[docs]class SpectralLines(object): """Hitran spectral line parameters for a molecule. Attributes: delta: Numpy array of air-broadended pressure shifts [cm-1 atm-1] (lines). en: Numpy array of transition lower state energies [cm-1] (lines). gamma_air: Numpy array of air-broadened halfwidths [cm-1 atm-1] (lines). gamma_self: Numpy array of self-broadened halfwidths [cm-1 atm-1] (lines). id: HITRAN molecule id. iso: Numpy array of HITRAN isotopologue ids (lines). mass: Numpy array of isotopologue masses [g] (lines). n: Numpy array of air-broadened temperature dependence powers (lines). s: Numpy array of line strengths [cm] (lines). q: TotalPartitionFunction object. v: Numpy array of transition wavenumbers [cm-1] (lines). """ def __init__(self, database, total_partition_function): """Sorts line parameters by transition wavenumber, and partially corrects the line strengths. Args: database: Hitran object. total_partition_function: TotalPartitionFunction object. Raises: EmptySpectraError: No molecular line parameters are detected. """ # Create member arrays. for x in database.parameters: setattr(self, x.shortname, copy(getattr(database, x.shortname))) # Correct for Hitran counting weirdness (1, 2, 3, ... 9, 0, a, b, ...) for i in range(self.iso.size): if self.iso[i] == 0: self.iso[i] = 10 # Get the mass of the isotopologues. self.mass = asarray([float(database.isotopologues[x-1].mass) for x in self.iso]) self.line_profile = database.line_profile self.q = total_partition_function # Partially correct line strengths. self.s[:] *= self.temperature_correct_line_strength(self.q, TIPS_REFERENCE_TEMPERATURE, self.iso, self.en, self.v)
[docs] def absorption_coefficient(self, temperature, pressure, partial_pressure, wavenumber, cut_off=25.): """Calculates the absorption coefficient. Args: temperature: Temperature [K]. pressure: Pressure [atm]. partial_pressure: Partial pressure [atm]. wavenumber: Numpy array of wavenumbers [cm-1] (wavenumber). cut_off: Distance [cm-1] from the transition frequency where the line is cut off. Returns: Numpy array of absorption coefficients [cm2] (wavenumber). """ lines = shallow_copy(self) lines.s = self.correct_line_strengths(temperature) lines.v = lines.pressure_shift_transition_wavenumbers(pressure) profile = shallow_copy(lines.line_profile) profile.update(lines, temperature, pressure, partial_pressure) k = zeros(wavenumber.size) for i in range(lines.s.size): left = searchsorted(wavenumber, lines.v[i] - cut_off, side="left") right = searchsorted(wavenumber, lines.v[i] + cut_off, side="right") k[left:right] += lines.s[i]*profile.profile(lines, wavenumber[left:right], i) return k
[docs] def correct_line_strengths(self, temperature): """Temperature-corrects the line strengths. Args: temperature: Temperature [K]. Returns: Numpy array of corrected line strengths [cm] (lines). """ return self.s[:]*(1./self.temperature_correct_line_strength(self.q, temperature, self.iso, self.en, self.v))
[docs] def pressure_shift_transition_wavenumbers(self, pressure): """Pressure-shifts transition wavenumbers. Args: pressure: Pressure [atm]. Returns: Numpy array of pressure-shifted transition wavenumbers [cm-1] (lines). """ return self.v[:] + self.d_air[:]*pressure
[docs] @staticmethod def temperature_correct_line_strength(q, t, iso, en, v): """Temperature-corrects a line strength. Args: q: TotalPartitionFunction object. t: Temperature [K]. iso: HITRAN isotopologue id. en: Transition lower state energy [cm-1]. v: Transition wavenumber [cm-1]. Returns: Temperature correction factor. """ # Divide-by-zeros may occur for transition wavenumbers close to zero, like those # for the O16-O17 isotopologue of O2. return q.total_partition_function(t, iso[:])/(exp(c2*en[:]/t)*(1. - exp(c2*v[:]/t)))