.. _optical_hitranchemical:
HITRAN Molecules
================
Calculates the optical absorption and extinction of various atmospheric molecules using the Voigt line-shape and the HITRAN spectral line database.
The object supports all of the HITRAN species specified in the HITRAN database. The current version uses the database files downloaded by the
`Hitran HAPI `_ interface. Automatic download support for the HAPI interface is built into the Sasktran Python implementation.
The general notation is to replace the *XXX* in* HITRANCHEMICAL_XXX* with the uppercase chemical name (e.g. H2O) to produce HITRANCHEMICAL_H2O. The exception
to the rule is the NO+ molecule (hitran index 36) which is specified as HITRANCHEMICAL_NOPLUS.
================================== ================================ ====================== ===================
SasktranIF Name Molecule Notes Molecule Number
================================== ================================ ====================== ===================
HITRANCHEMICAL_H2O H\ :sub:`2`\ O Water 1
HITRANCHEMICAL_CO2 CO\ :sub:`2` Carbon Dioxide 2
HITRANCHEMICAL_O3 O\ :sub:`3` Ozone 3
HITRANCHEMICAL_N2O N\ :sub:`2`\ O Nitrogen oxide 4
HITRANCHEMICAL_CO CO Carbon Monoxide 5
HITRANCHEMICAL_CH4 CH\ :sub:`4` Methane 6
HITRANCHEMICAL_O2 O\ :sub:`2` Oxygen 7
HITRANCHEMICAL_NO NO Nitric Oxide 8
HITRANCHEMICAL_SO2 SO\ :sub:`2` Sulfur Dioxide 9
HITRANCHEMICAL_NO2 NO\ :sub:`2` Nitrogen Dioxide 10
HITRANCHEMICAL_NH3 NH\ :sub:`3` Ammonia 11
HITRANCHEMICAL_HNO3 HNO\ :sub:`3` Nitric Acid 12
HITRANCHEMICAL_OH OH Hydroxyl 13
HITRANCHEMICAL_HF HF Hydrogen Fluoride 14
HITRANCHEMICAL_HCL HCl Hydrogen Chloride 15
HITRANCHEMICAL_HBR HBr Hydrogen Bromide 16
HITRANCHEMICAL_HI HI Hydrogen Iodide 17
HITRANCHEMICAL_CLO ClO Chlorine Monoxide 18
HITRANCHEMICAL_OCS OCS Carbonyl Sulfide 19
HITRANCHEMICAL_H2CO H\ :sub:`2`\ CO Formaldehyde 20
HITRANCHEMICAL_HOCL HOCl Hypochlorous Acid 21
HITRANCHEMICAL_N2 N\ :sub:`2` Nitrogen 22
HITRANCHEMICAL_HCN HCN Hydrogen Cyanide 23
HITRANCHEMICAL_CH3CL CH\ :sub:`3`\ Cl Methyl Chloride 24
HITRANCHEMICAL_H2O2 H\ :sub:`2`\ O\ :sub:`2` Hydrogen Peroxide 25
HITRANCHEMICAL_C2H2 C\ :sub:`2`\ H\ :sub:`2` Acetylene 26
HITRANCHEMICAL_C2H6 C\ :sub:`2`\ H\ :sub:`6` Ethane 27
HITRANCHEMICAL_PH3 PH\ :sub:`3` Phosphine 28
HITRANCHEMICAL_COF2 COF\ :sub:`2` Carbonyl Fluoride 29
HITRANCHEMICAL_SF6 SF\ :sub:`6` Sulfur Hexafluoride 30
HITRANCHEMICAL_H2S H\ :sub:`2`\ S Hydrogen Sulfide 31
HITRANCHEMICAL_HCOOH HCOOH Formic Acid 32
HITRANCHEMICAL_HO2 HO\ :sub:`2` Hydroperoxyl 33
HITRANCHEMICAL_O O Oxygen Atom 34
HITRANCHEMICAL_CLONO2 ClONO\ :sub:`2`\ Chlorine Nitrate 35
HITRANCHEMICAL_NOPLUS NO\ :sup:`+`\ Nitric Oxide Cation 36
HITRANCHEMICAL_HOBR HOBr Hypobromous Acid 37
HITRANCHEMICAL_C2H4 C\ :sub:`2`\ H\ :sub:`4` Ethylene 38
HITRANCHEMICAL_CH3OH CH\ :sub:`3`\ OH Methanol 39
HITRANCHEMICAL_CH3BR CH\ :sub:`3`\ Br Methyl Bromide 40
HITRANCHEMICAL_CH3CN CH\ :sub:`3`\ CN Acetonitrile 41
HITRANCHEMICAL_CF4 CF\ :sub:`4`\ CFC-14 42
HITRANCHEMICAL_C4H2 C\ :sub:`4`\ H\ :sub:`2` Diacetylene 43
HITRANCHEMICAL_HC3N HC\ :sub:`3`\ N Cyanoacetylene 44
HITRANCHEMICAL_H2 H\ :sub:`2`\ Hydrogen 45
HITRANCHEMICAL_CS CS Carbon Monosulfide 46
HITRANCHEMICAL_SO3 SO\ :sub:`3`\ Sulfur trioxide 47
HITRANCHEMICAL_C2N2 C\ :sub:`2`\ N\ :sub:`2` Cyanogen 48
HITRANCHEMICAL_COCl2 COCl\ :sub:`2`\ Phosgene 49
================================== ================================ ====================== ===================
Example using the Sasktran Python interface::
import numpy as np
import matplotlib.pyplot as plt
import sasktran as sk
wavenum = np.arange( 5900.0, 6200.0, 0.001)
wavelen = 1.0E7/wavenum
atmos = sk.MSIS90()
heights = 5000
hitran = sk.HITRANChemical('CH4', line_tolerance=1.0E-09)
hitran._iskopticalproperty.SetProperty('setwavenumberrange', [5900.0, 6200.0] )
hitran._iskopticalproperty.SetProperty('enablecachedcrosssections', wavenum)
xs = hitran.calculate_cross_sections(atmos, latitude=52.1315, longitude=-106.6335, altitude=heights, mjd=58290.75000000, wavelengths=wavelen)
plt.plot( wavenum, np.log10(skfullxs.absorption), 'k-' )
plt.title('CH4 log10(cross-sections) at {:f} km'.format(heights/1000.0))
plt.xlabel('Wavenumber cm-1')
plt.ylabel('Log10(Cross-sections) cm2')
plt.show()
Micro-Windows
-------------
The HITRAN CHEMICAL class works on the concept of a micro-window and adjusts its Voigt line-shape calculations so that
distant weak lines within the micro-window are ignored once they are below a threshold criterion. This generates a
significant computational saving when used properly but can generate choppy signals when set too aggressively.
The micro-window is specified using property :py:func:`~HitranChemical.SetWavenumberRange`. By default the micro-window
is set from the first call to CalculateCrossSections; the micro window is set from the min and max values of wavenumber. If only
one value is passed (as a scalar) it subtracts and adds 10 cm-1 to make a window 20 wavenumbers wide. This default is
reasonable for one calculation but may be inappropriate for subsequent calculations especially if they are outside this
default window. The micro-window must be initialized before any cross-section calculations or calls to SetLocation.
Tolerance
^^^^^^^^^
The HITRAN CEHMICAL implements a tolerance scheme so it can quickly reject weak/distant lines within a micro-window. The code uses two parameters to control this algorithm,
* Maximum Line Strength in the micro-window
* Tolerance of the calculation precision
By default the system disables this optimization as it is difficult to ensure sensible values across a broad range of scenarios.
We do recommend that users who plan to do multiple calculations within a given micro-window region spend some timeenabling and tuning this feature
as there can be significant speed increases.
By default the precision tolerance is disabled and the contribution from every selected line is used, however small. Setting a value of 1.0E-06 to 1.0E-09
will usually speed up most calculations with no significant loss of accuracy.
The algorithm, when enabled, is straightforward. The code finds the maximum line strength from the strongest line in the
micro-window, excluding lines in the margins. The approximate contribution from each line to any wavenumber within the micro-window is estimated using a simplified
(quick) far-field Voigt formulae and is compared to the maximum line strength. The line is rejected from the calculation if the nominal contribution is less than the
product of the maxlimum line strength in the micro-window and the tolerance setting. Any line within 5 half widths of a given wavenumber location
is always included in the full Voigt calculation regardless of line strength or tolerance. The tolerance can be
adjusted and enabled by calling property :py:func:`~HitranChemical.SetLineTolerance`. The user, if they wish, can manually set the
maximum line strength used by the algoritym by calling property :py:func:`~HitranChemical.SetMaxLineShapeStrength` otherwise the code will use
the maximum value in the micro-window.
The current algorithm works well for relatively narrow micro-windows dominated by a few strong lines but may need
adjustment if the window is wide and has regions well removed from the strongest feature. The line-rejection/tolerance
feature can be disabled by setting the :py:func:`~HitranChemical.SetLineTolerance` to 0.0 which guarantees that all lines
in the micro-window and margin contribute to the signal regardless of size.
Edge and Margin Effects
^^^^^^^^^^^^^^^^^^^^^^^
The HITRAN CHEMICAL code ignores any spectral lines that lie outside the micro-window and this may cause inaccuracy if
there are strong or significant lines just outside the micro-window, see figures below. To assist with this problem we automatically extend
the upper and lower wavenumber bounds of the micro-window by the margin value set in property :py:func:`~HitranChemical.SetMicroWindowMargin`.
The lines in the margin region are treated exactly the same as lines in the micro-window region except they do not
participate in setting values for the tolerance algorithm described above.
.. figure:: images/co2_absorption_no_margin.png
CO2 absorption using no margin. The calculation completely misses a strong line just outside the window
.. figure:: images/co2_absorption_4cm_margin.png
CO2 absorption using 4 nm margin. The effect of the strongline is readily evident.
The default value for the margin region is 10 wavenumbers (cm-1) at both ends of the micro-window. This is a fairly large margin
and can be easily reduced to significantly smaller values for many scenarios. We strongly recommend users survey the
spectral environment in the vicinity of their desired micro-window and set the margin values to appropriate values to
properly account for nearby spectral lines.
Isotopes
--------
Most molecules in the HITRAN database have several isotopic forms. By default we use all isotopes associated with the
molecule and use the abundance values implicitly set within the HITRAN database entries. The experimental property
:py:func:`~HitranChemical.SetIsotopeFilter` allows you to select just one isotope of the molecule although we do not
have any mechanisms to adjust for natural abundance. Please use this option with care as it is experimental.
Implementation Details
----------------------
The code works with the 2016 (and onwards) HITRAN database.
* It uses the 160 column files generated by the HAPI interface. The text based HAPI files are automatically scanned
and cached as needed as binary files on the local disk system. This provides a significant speed advantage when
reusing database entries. The same HITRAN database files are, by default, shared between different conda and python environments.
* The code implements a multi-threaded C++ implementation of the Kuntz Voigt profile and includes published errata.
* The results have been successfully compared to the HAPI Voigt profile calculations.
* The code code uses the 2017 TIPS (Total Internal Partions) fortran code provided by the `HITRAN website `_.
The TIPS values between 70 K and 350K for each isotope are calculated and cached on a local disk at 1/64 Kelvin. This
provides a significant speed advantage.
The location of the HITRAN HAPI database and the local HITRAN binary cache are controlled by registry settings. These can be
modified by the user. With the Python implementation they can be modified with
the `sasktran_core.update_settings.modify()` function. The sasktran HITRAN implementation caches the HITRAN text files as binary
files for rapid loading.
.. figure:: sasktran-hapi-20000km.png
Comparison of Sasktran code and HAPI code for the methane band. Note that the Sasktran results are the same as the HAPI
results. The Sasktran code was approximately 100 times faster than HAPI.
Properties
----------
.. py:module:: HitranChemical
SetIsotopeFilter
^^^^^^^^^^^^^^^^
.. py:function:: SetIsotopeFilter( int isotopenumner)
Allows the HITRAN object to load in just one isotope of the requested molecule.
The value set must match one of the isotope labels used for the given molecule in the
HITRAN database file, `molparam.txt`. Note that the code does not adjust the line strength
for isotopic abundance but uses the line strength value as given in the HITRAN database. This means users
will have to account for the isotopic abundance themselves if they do not wish to use the value built into
the HITRAN database line strength values.
:param int isotopenumber:
The index of the required isotope.
SetLineTolerance
^^^^^^^^^^^^^^^^
.. py:function:: SetLineTolerance( double tolerance)
Allows the user to set the tolerance factor used to reject weak lines from the current micro-window as part of a
speed optimization strategy. The default value is 0.0 which disables the optimization. A larger value will speed up calculation of spectra but may result
in choppy spectra at smaller intensities, especially in extinction/absorption spectra which typically
follow the log of the cross-secton. A smaller value will reduce choppiness but increase computational speed.
Only values greater than or equal to zero are acceptable. A value of 1.0E-09 is a good starting value if you
want to enable or explore this optimization.
:param float tolerance:
The tolerance value. [ Default value is 0.0]
SetMaxLineStrength
^^^^^^^^^^^^^^^^^^
.. py:function:: SetMaxLineStrength( double maxstrength)
Allows the user to manually set the maximum line strength within a micro-window which is used as part of a speed
optimization strategy. By default, the object will set this value from the strongest line in the micro-window. The
value is used with the line tolerance to reject weak lines from spectral calculations. Reducing the value of the maximum
line strength can reduce choppiness in the spectra. It is only used in conjunction with property
:py:func:`~HitranChemical.SetLineTolerance`. Only values greater than zero are acceptable while a value of zero will
disable the manual setting and reinstate usage of the default.
SetWavenumberRange
^^^^^^^^^^^^^^^^^^
.. py:function:: SetWavenumberRange( array(2) )
A 2 element array specifying the lowest and highest wavenumber of interest. This will define
the micro-window used by subsequent calculations and is an important optimization. The object will discard spectral
lines outside this range apart from the ones inside the marginal boundary regions neighbouring the micro-window. The
value must be set during initialization before cross-sections are calculated or the location specified. The default
is for the code to set the micro-window range from the minimum and maximum wavenumbers in the first call to
:meth:`~ISKOpticalProperty.CalculateCrossSections`.
EnableCachedCrossSections
^^^^^^^^^^^^^^^^^^^^^^^^^
.. py:function:: EnableCachedCrossSections( array_of_wavenumbers(N) )
An optimization to assist Sasktran engines realize the speed optimizations that are built into the Hitran code. There is a significant
speed advantage to calculate the cross-sections at one location for all wavelengths of interest in one function call. This is not possible in many
engines as they internally support calculating cross-sections at one wavelength only at each location.
This parameter enables internal caching of the full array of cross-sections for all wavenumbers of interest at all the different locations in the atmosphere used
by the engine. All subsequent calls to :meth:`~ISKOpticalProperty.SetLocation` will either result in either generating a new cache entry if it is a new location
or fetching a previously calculated cache entry if is not. All calls to :meth:`~ISKOpticalProperty.CalculateCrossSections` will only use cross-sections
stored in the cache at the current location.
The input array specifies all of the wavenumbers (in cm-1) that will be stored in the caches. Users should ensure that all the
wavenumbers they plan to use in subsequent calls to :meth:`~ISKOpticalProperty.CalculateCrossSections` are in the array. The wavenumbers in the array
can be in any order and do not have to be in ascending order. Needless to say, users should be careful not to request too many wavenumbers
at too many locations as the resulting storage requirements may be prohibitive.
SetMicroWindowMargin
^^^^^^^^^^^^^^^^^^^^
.. py:function:: SetMicroWindowMargin( double margin )
Sets the margin of the micro-window in wavenumbers. This margin extends the upper and lower bounds of the micro-window once it is loaded
into memory. The margin value is used to ensure that cross-section calculations near the edge of the micro-window are accurate and have
contributions from lines outside the micro-window. The default value is 10 wavenumbers. It is the users responsibility to choose a value
for the margin that provides the necessary accuracy for their aplication. The margin value must be set before any calls to :meth:`~ISKOpticalProperty.SetLocation`
or :meth:`~ISKOpticalProperty.CalculateCrossSections` .
References
----------
**I.E. Gordon**, L.S. Rothman, C. Hill, R.V. Kochanov, Y. Tan, P.F. Bernath, M. Birk, V. Boudon, A. Campargue, K.V. Chance, B.J. Drouin,
J.-M. Flaud, R.R. Gamache, J.T. Hodges, D. Jacquemart, V.I. Perevalov, A. Perrin, K.P. Shine, M.-A.H. Smith, J. Tennyson, G.C. Toon,
H. Tran, V.G. Tyuterev, A. Barbe, A.G. Császár, V.M. Devi, T. Furtenbacher, J.J. Harrison, J.-M. Hartmann, A. Jolly, T.J. Johnson,
T. Karman, I. Kleiner, A.A. Kyuberis, J. Loos, O.M. Lyulin, S.T. Massie, S.N. Mikhailenko, N. Moazzen-Ahmadi, H.S.P. Müller,
O.V. Naumenko, A.V. Nikitin, O.L. Polyansky, M. Rey, M. Rotger, S.W. Sharpe, K. Sung, E. Starikova, S.A. Tashkun, J. Vander Auwera,
G. Wagner, J. Wilzewski, P. Wcis?o, S. Yu, E.J. Zak.
The HITRAN2016 molecular spectroscopic database, Journal* of Quantitative Spectroscopy and Radiative Transfer*, **203**, 3-69, (2017), `doi.org/10.1016/j.jqsrt.2017.06.038 `_.
**M. Kuntz**, "A new implementation of the Humlicek algorithm for the calculation of the Voigt profile function",
*Journal of Quantitative Spectroscopy and Radiative Transfer*, **57**, 6, 819-824, (1997), `doi.org/10.1016/S0022-4073(96)00162-8 `_
**Wim Ruyten**, Comment on “A new implementation of the Humlicek algorithm for the calculation of the Voigt profile function” by M. Kuntz [JQSRT 57(6) (1997) 819–824],
*Journal of Quantitative Spectroscopy and Radiative Transfer*, **86**, 2, 231-233, (2004), `doi.org/10.1016/j.jqsrt.2003.12.027 `_.
**R.V. Kochanov**, I.E. Gordon, L.S. Rothman, P. Wcislo, C. Hill, J.S. Wilzewski,
HITRAN Application Programming Interface (HAPI): A comprehensive approach to working with spectroscopic data,
*J. Quant. Spectrosc. Radiat. Transfer*, **177**, 15-30 (2016), `doi.org/10.1016/j.jqsrt.2016.03.005 `_