Pressure Broadening#

pyROX can handle several descriptions of the pressure broadening. In this notebook, we’ll explore three approaches: reading broadening coefficients from files, using constant values, and using a parameterisation for the coefficients.

[1]:
from pyROX import utils, cross_sections

Coefficients from a file#

In the “Getting Started” notebook, we already saw an example of reading broadening coefficients from a file. For AlH, ExoMol provides coefficients for the so-called “m0” broadening diet (see Tennyson et al. 2024), which is taken into account by pyROX. This means that \(\gamma\) and \(n\) are dependent on the (rotational) quantum numbers, resulting in transition-specific broadening coefficients.

Note

pyROX currently supports the “a0” and “m0” broadening diets. For other diets, pyROX uses the average broadening coefficient in the files.

In the next cell, we’ll load the AlH example configuration and modify the PT-grid and perturber_info. Finally, the cross-sections output will be stored in the broadening_from_file sub-directory.

[2]:
# Basic information on database and species
database = 'exomol' # Can be ['exomol', 'hitran', 'hitemp', 'kurucz']
species  = 'alh'    # Species name
mass = 27.98948     # Can be found in *.def.json file

N_CPUs = 4 # Number of CPUs for parallelisation

# Input directory
input_data_dir  = '../../examples/exomol_alh/input_data/'

# Instructions to download from ExoMol database
urls = [
    'https://www.exomol.com/db/AlH/27Al-1H/AloHa/27Al-1H__AloHa.def.json',
    'https://www.exomol.com/db/AlH/27Al-1H/27Al-1H__H2.broad',
    'https://www.exomol.com/db/AlH/27Al-1H/27Al-1H__He.broad',
]

# Input-data files
files = dict(
    transitions = f'{input_data_dir}/27Al-1H__AloHa.trans.bz2',
    states      = f'{input_data_dir}/27Al-1H__AloHa.states.bz2',
    partition_function = f'{input_data_dir}/27Al-1H__AloHa.pf',
)

import numpy as np
# Pressure and temperature grids
P_grid = 10**np.array([0.,1.,2.]) # [bar]
T_grid = np.array([2000]) # [K]

# Wavenumber grid
wave_min = 0.3; wave_max = 28.0 # [um]
delta_nu = 0.01 # [cm^-1]
adaptive_nu_grid = True # Switch to sparser wavenumber grid for high broadening?

# Line-strength cutoffs
global_cutoff = 1e-45 # [cm^-1 / (molecule cm^-2)]
local_cutoff  = 0.25

# Function with arguments gamma_V [cm^-1], and P [bar]
wing_cutoff = lambda gamma_V, P: 25 if P<=200 else 100 # Gharib-Nezhad et al. (2024)
[ ]:
# Change the output directory
output_data_dir = '../../examples/exomol_alh/broadening_from_file/'

# Pressure-broadening information
perturber_info = dict(
    H2 = dict(VMR=0.85, file=f'{input_data_dir}/27Al-1H__H2.broad'), # Read from file
    He = dict(VMR=0.15, file=f'{input_data_dir}/27Al-1H__He.broad'),
)

# Setup a configuration object (done automatically when running pyROX from the command line)
config = utils.update_config_with_args(
    database=database,
    species=species,
    mass=mass,

    input_data_dir=input_data_dir,
    output_data_dir=output_data_dir,
    urls=urls,
    files=files,

    P_grid=P_grid,
    T_grid=T_grid,
    wave_min=wave_min,
    wave_max=wave_max,
    delta_nu=delta_nu,
    adaptive_nu_grid=adaptive_nu_grid,

    perturber_info=perturber_info,

    local_cutoff=local_cutoff,
    global_cutoff=global_cutoff,
    wing_cutoff=wing_cutoff,

    N_CPUs=N_CPUs,
)

# Load the data object and calculate the opacity cross-sections
data_broadening_from_file = cross_sections.load_data_object(config, download=True)
data_broadening_from_file.calculate_temporary_outputs(progress_bar=True)
data_broadening_from_file.save_combined_outputs()

Updating configuration with new parameters
[pyROXWarning] Adding parameter "database" as "exomol".
[pyROXWarning] Adding parameter "species" as "alh".
[pyROXWarning] Adding parameter "mass" as 27.98948.
[pyROXWarning] Adding parameter "input_data_dir" as "../../examples/exomol_alh/input_data/".
[pyROXWarning] Adding parameter "output_data_dir" as "../../examples/exomol_alh/broadening_from_file/".
[pyROXWarning] Adding parameter "urls" as ['https://www.exomol.com/db/AlH/27Al-1H/AloHa/27Al-1H__AloHa.def.json', 'https://www.exomol.com/db/AlH/27Al-1H/27Al-1H__H2.broad', 'https://www.exomol.com/db/AlH/27Al-1H/27Al-1H__He.broad'].
[pyROXWarning] Adding parameter "files" as {'transitions': '../../examples/exomol_alh/input_data//27Al-1H__AloHa.trans.bz2', 'states': '../../examples/exomol_alh/input_data//27Al-1H__AloHa.states.bz2', 'partition_function': '../../examples/exomol_alh/input_data//27Al-1H__AloHa.pf'}.
[pyROXWarning] Adding parameter "P_grid" as [  1.  10. 100.].
[pyROXWarning] Adding parameter "T_grid" as [2000].
[pyROXWarning] Adding parameter "wave_min" as 0.3.
[pyROXWarning] Adding parameter "wave_max" as 28.0.
[pyROXWarning] Adding parameter "delta_nu" as 0.01.
[pyROXWarning] Adding parameter "adaptive_nu_grid" as True.
[pyROXWarning] Adding parameter "perturber_info" as {'H2': {'VMR': 0.85, 'file': '../../examples/exomol_alh/input_data//27Al-1H__H2.broad'}, 'He': {'VMR': 0.15, 'file': '../../examples/exomol_alh/input_data//27Al-1H__He.broad'}}.
[pyROXWarning] Adding parameter "local_cutoff" as 0.25.
[pyROXWarning] Adding parameter "global_cutoff" as 1e-45.
[pyROXWarning] Adding parameter "wing_cutoff" as <function <lambda> at 0x7f089d513a00>.
[pyROXWarning] Adding parameter "N_CPUs" as 4.

------------------------------------------------------------
  Line-by-line Absorption from ExoMol
------------------------------------------------------------


Downloading data from ExoMol
[pyROXWarning] File "../../examples/exomol_alh/input_data/27Al-1H__AloHa.def.json" already exists, skipping download.
[pyROXWarning] File "../../examples/exomol_alh/input_data/27Al-1H__H2.broad" already exists, skipping download.
[pyROXWarning] File "../../examples/exomol_alh/input_data/27Al-1H__He.broad" already exists, skipping download.
[pyROXWarning] File "../../examples/exomol_alh/input_data/27Al-1H__AloHa.pf" already exists, skipping download.
[pyROXWarning] File "../../examples/exomol_alh/input_data/27Al-1H__AloHa.states.bz2" already exists, skipping download.
[pyROXWarning] File "../../examples/exomol_alh/input_data/27Al-1H__AloHa.trans.bz2" already exists, skipping download.

Reading parameters from the configuration file
[pyROXWarning] Please make sure that the following parameters are given in the expected units:
[pyROXWarning] - P_grid [bar]
[pyROXWarning] - T_grid [K]
[pyROXWarning] - delta_nu [cm^-1]
[pyROXWarning] - global_cutoff [cm^-1 / (molecule cm^-2)]
[pyROXWarning] - mass [amu]
[pyROXWarning] - wave_max [um]
[pyROXWarning] - wave_min [um]
[pyROXWarning] - wing_cutoff [cm^-1]


Wavelength-grid:
  Wavelength: 0.30 - 28 um
  Wavenumber: 357 - 33333 cm^-1
  Fixed wavenumber-spacing: 0.010 cm^-1
  Number of grid points: 3297620
  Adaptive grid: True

Pressure broadening info:
  - H2: VMR=0.85, mass=2.02 amu | "../../examples/exomol_alh/input_data/27Al-1H__H2.broad"
  - He: VMR=0.15, mass=4.00 amu | "../../examples/exomol_alh/input_data/27Al-1H__He.broad"
  Mean molecular weight of perturbers: 2.31 amu

PT-grid:
  P: [  1.  10. 100.] bar
  T: [2000] K

Calculating cross-sections
  Reading states file
  Reading states from "../../examples/exomol_alh/input_data/27Al-1H__AloHa.states.bz2"
  Reading transitions from "../../examples/exomol_alh/input_data/27Al-1H__AloHa.trans.bz2"
  Number of lines loaded: 29725
100%|████████████████████| 3/3 [00:12<00:00,  4.27s/it, N_lines_computed=28486, P=1e+00 bar, T=2000 K]
  Saving temporary cross-sections to "/net/lem/data2/regt/pyROX/examples/exomol_alh/broadening_from_file/tmp/xsec_27Al-1H__AloHa.trans.hdf5"

Combining temporary files and saving final output
  Merging 1 temporary files into a single grid
  Temporary files:
    - "xsec_27Al-1H__AloHa.trans.hdf5"
  Combining PT-grids of temporary files
  Saving final output to "/net/lem/data2/regt/pyROX/examples/exomol_alh/broadening_from_file/xsec.hdf5"

Constant coefficients#

If no broadening coefficients exist on the ExoMol website, you can use the constant gamma and nu values provided in the definition-file, in this case input_data/27Al-1H__AloHa.def.json. We’ll create another data object data_broadening_from_constant in the cell below.

Important

If gamma is given as a constant or is given in the broadening-coefficients file, it should have units cm\(^{-1}\). Internally, pyROX will convert this into SI units.

[4]:
# Set the broadening parameters
perturber_info = dict(
    H2 = dict(VMR=0.85, gamma=0.07, n=0.5), # From *.def.json file ("broad")
    He = dict(VMR=0.15, gamma=0.07, n=0.5), # gamma = [cm^-1]
)

# Change the output directory
output_data_dir = '../../examples/exomol_alh/broadening_from_constant/'

## Update the configuration object
config = utils.update_config_with_args(
    config=config,
    output_data_dir=output_data_dir,
    perturber_info=perturber_info,
)

# Load the data object and calculate the opacity cross-sections
data_broadening_from_constant = cross_sections.load_data_object(config, download=False)
data_broadening_from_constant.calculate_temporary_outputs(progress_bar=True)
data_broadening_from_constant.save_combined_outputs()

Updating configuration with new parameters
[pyROXWarning] Overwriting parameter "output_data_dir" from ../../examples/exomol_alh/broadening_from_file/ to "../../examples/exomol_alh/broadening_from_constant/".
[pyROXWarning] Overwriting parameter "perturber_info" from {'H2': {'VMR': 0.85, 'file': '../../examples/exomol_alh/input_data//27Al-1H__H2.broad', 'mass': 3.3474474982544496e-27}, 'He': {'VMR': 0.15, 'file': '../../examples/exomol_alh/input_data//27Al-1H__He.broad', 'mass': 6.64647699833733e-27}} to {'H2': {'VMR': 0.85, 'gamma': 0.07, 'n': 0.5}, 'He': {'VMR': 0.15, 'gamma': 0.07, 'n': 0.5}}.

------------------------------------------------------------
  Line-by-line Absorption from ExoMol
------------------------------------------------------------


Reading parameters from the configuration file
[pyROXWarning] Please make sure that the following parameters are given in the expected units:
[pyROXWarning] - P_grid [bar]
[pyROXWarning] - T_grid [K]
[pyROXWarning] - delta_nu [cm^-1]
[pyROXWarning] - global_cutoff [cm^-1 / (molecule cm^-2)]
[pyROXWarning] - mass [amu]
[pyROXWarning] - wave_max [um]
[pyROXWarning] - wave_min [um]
[pyROXWarning] - wing_cutoff [cm^-1]


Wavelength-grid:
  Wavelength: 0.30 - 28 um
  Wavenumber: 357 - 33333 cm^-1
  Fixed wavenumber-spacing: 0.010 cm^-1
  Number of grid points: 3297620
  Adaptive grid: True

Pressure broadening info:
  - H2: VMR=0.85, mass=2.02 amu | constant(s) from dictionary
  - He: VMR=0.15, mass=4.00 amu | constant(s) from dictionary
  Mean molecular weight of perturbers: 2.31 amu

PT-grid:
  P: [  1.  10. 100.] bar
  T: [2000] K

Calculating cross-sections
  Reading states file
  Reading states from "../../examples/exomol_alh/input_data/27Al-1H__AloHa.states.bz2"
  Reading transitions from "../../examples/exomol_alh/input_data/27Al-1H__AloHa.trans.bz2"
  Number of lines loaded: 29725
100%|████████████████████| 3/3 [00:12<00:00,  4.08s/it, N_lines_computed=28486, P=1e+00 bar, T=2000 K]
  Saving temporary cross-sections to "/net/lem/data2/regt/pyROX/examples/exomol_alh/broadening_from_constant/tmp/xsec_27Al-1H__AloHa.trans.hdf5"

Combining temporary files and saving final output
  Merging 1 temporary files into a single grid
  Temporary files:
    - "xsec_27Al-1H__AloHa.trans.hdf5"
  Combining PT-grids of temporary files
  Saving final output to "/net/lem/data2/regt/pyROX/examples/exomol_alh/broadening_from_constant/xsec.hdf5"

Parameterised coefficients#

You can also parameterise the broadening coefficients and provide gamma and n as functions of the lower rotational quantum number, \(J_l\). In the utils module, pyROX provides the \(\gamma(J_l)\)-parameterisation described by Gharib-Nezhad et al. (2021) for the metal-hydride and -oxides AlH, CaH, MgH, CrH, FeH, TiH, SiO, TiO, and VO. In the cell below, we import this description for the H\(_2\) and He broadening of AlH.

Important

If gamma is provided as a function, it should output units of s\(^{-1}\).

[5]:
from pyROX.utils import Broaden_Gharib_Nezhad_ea_2021 as Broaden_GN

# Set the broadening parameters
perturber_info = dict(
    H2 = dict(VMR=0.85, gamma=Broaden_GN('AlH').gamma_H2, n=0.5),
    He = dict(VMR=0.15, gamma=Broaden_GN('AlH').gamma_He, n=0.5), # gamma = [s^-1]
)

# Change the output directory
output_data_dir = '../../examples/exomol_alh/broadening_from_parameterisation/'

# Update the previous configuration
config = utils.update_config_with_args(
    config=config,
    output_data_dir=output_data_dir,
    perturber_info=perturber_info,
)

# Initialise new data object and calculate opacity cross-sections
data_broadening_from_parameterisation = cross_sections.load_data_object(config, download=False)
data_broadening_from_parameterisation.calculate_temporary_outputs(progress_bar=True)
data_broadening_from_parameterisation.save_combined_outputs()

Updating configuration with new parameters
[pyROXWarning] Overwriting parameter "output_data_dir" from ../../examples/exomol_alh/broadening_from_constant/ to "../../examples/exomol_alh/broadening_from_parameterisation/".
[pyROXWarning] Overwriting parameter "perturber_info" from {'H2': {'VMR': 0.85, 'gamma': 0.07, 'n': 0.5, 'mass': 3.3474474982544496e-27}, 'He': {'VMR': 0.15, 'gamma': 0.07, 'n': 0.5, 'mass': 6.64647699833733e-27}} to {'H2': {'VMR': 0.85, 'gamma': <bound method Broaden_Gharib_Nezhad_ea_2021.gamma_H2 of <pyROX.utils.Broaden_Gharib_Nezhad_ea_2021 object at 0x7f087939a510>>, 'n': 0.5}, 'He': {'VMR': 0.15, 'gamma': <bound method Broaden_Gharib_Nezhad_ea_2021.gamma_He of <pyROX.utils.Broaden_Gharib_Nezhad_ea_2021 object at 0x7f0874471810>>, 'n': 0.5}}.

------------------------------------------------------------
  Line-by-line Absorption from ExoMol
------------------------------------------------------------


Reading parameters from the configuration file
[pyROXWarning] Please make sure that the following parameters are given in the expected units:
[pyROXWarning] - P_grid [bar]
[pyROXWarning] - T_grid [K]
[pyROXWarning] - delta_nu [cm^-1]
[pyROXWarning] - global_cutoff [cm^-1 / (molecule cm^-2)]
[pyROXWarning] - mass [amu]
[pyROXWarning] - wave_max [um]
[pyROXWarning] - wave_min [um]
[pyROXWarning] - wing_cutoff [cm^-1]


Wavelength-grid:
  Wavelength: 0.30 - 28 um
  Wavenumber: 357 - 33333 cm^-1
  Fixed wavenumber-spacing: 0.010 cm^-1
  Number of grid points: 3297620
  Adaptive grid: True

Pressure broadening info:
  - H2: VMR=0.85, mass=2.02 amu | function
  - He: VMR=0.15, mass=4.00 amu | function
  Mean molecular weight of perturbers: 2.31 amu

PT-grid:
  P: [  1.  10. 100.] bar
  T: [2000] K

Calculating cross-sections
  Reading states file
  Reading states from "../../examples/exomol_alh/input_data/27Al-1H__AloHa.states.bz2"
  Reading transitions from "../../examples/exomol_alh/input_data/27Al-1H__AloHa.trans.bz2"
  Number of lines loaded: 29725
100%|████████████████████| 3/3 [00:11<00:00,  3.89s/it, N_lines_computed=28486, P=1e+00 bar, T=2000 K]
  Saving temporary cross-sections to "/net/lem/data2/regt/pyROX/examples/exomol_alh/broadening_from_parameterisation/tmp/xsec_27Al-1H__AloHa.trans.hdf5"

Combining temporary files and saving final output
  Merging 1 temporary files into a single grid
  Temporary files:
    - "xsec_27Al-1H__AloHa.trans.hdf5"
  Combining PT-grids of temporary files
  Saving final output to "/net/lem/data2/regt/pyROX/examples/exomol_alh/broadening_from_parameterisation/xsec.hdf5"

Plotting the results#

Finally, we can compare the line profiles that result from the three described approaches.

[6]:
from matplotlib.colors import LinearSegmentedColormap as LSC
cmaps = [LSC.from_list('', ['b', 'r']), LSC.from_list('', ['k', 'C1'])]
kwargs = dict(
    return_fig_ax=True, cmaps=cmaps, lw=1,
    xlim=(3.14,3.2), xscale='linear', ylim=(2e-23,1.5e-18),
)
fig, ax = data_broadening_from_file.plot_combined_outputs(**kwargs)
fig, ax = data_broadening_from_constant.plot_combined_outputs(fig=fig, ax=ax, ls='--', **kwargs)
fig, ax = data_broadening_from_parameterisation.plot_combined_outputs(fig=fig, ax=ax, ls=':', **kwargs)
fig.show()

Plotting cross-sections
../_images/notebooks_pressure_broadening_10_1.png

Here, we see that coefficients-file (solid) results in more pressure broadening compared to the constant (dashed) and parameterised coefficients (dotted).

Custom pressure broadening and line-shifts#

Lastly, pyROX supports the impact-width and -shift parameterisation of Allard et al. (2023) that describes the high-pressure perturbation of line cores via power laws as

\[\gamma = A_w\cdot T^{b_w}\cdot\left(\frac{n_\mathrm{p}}{n_\mathrm{ref}}\right) \qquad\text{and}\qquad \delta = A_d\cdot T^{b_d}\cdot\left(\frac{n_\mathrm{p}}{n_\mathrm{ref}}\right),\]

where \(n_\mathrm{p}\) and \(n_\mathrm{ref}\) are the number densities of the perturber and reference, respectively. The coefficients \(A_{w/d}\) and \(b_{w/d}\) can be provided for separate transitions and perturbers via the impact_width_info and impact_shift_info dictionaries, as in the following code-block

[ ]:
# Power-law impact-width/shift parameters gamma=A*T^b*n_perturber/n_reference
impact_width_info = dict(
    H2 = dict(VMR=0.85, A=[], b=[], nu_0=[], n_reference=1e20),
    He = dict(VMR=0.15, A=[], b=[], nu_0=[], n_reference=1e20),
)
impact_shift_info = dict(
    H2 = dict(VMR=0.85, A=[], b=[], nu_0=[], n_reference=1e20),
    He = dict(VMR=0.15, A=[], b=[], nu_0=[], n_reference=1e20),
)

Important

The parameterised impact-width and -shift of the line core should not be confused with the broad, asymmetric wings that alkali lines are known to have (e.g. Allard et al. 2016; Allard et al. 2019). Such profiles require a specialised treatment that pyROX cannot directly offer. Alternatively, pyROX supports the exclusion of certain quantum transitions (see the kurucz_k.py configuration file) which can then be replaced with custom line profiles.