Cross section computation using the Discrete Integral Transform (DIT) for rapid spectral synthesis ================================================================================================== We demonstarte the Discrete Integral Transform (DIT) method proposed by D.C.M van den Bekerom and E.Pannier. DIT takes advantage especially for the case that the number of the molecular line is large (typically > 10,000). We here compare the results by DIT with the direct computation (LPF). .. code:: ipython3 import numpy as np import matplotlib.pyplot as plt Here, we use FP64, but if you want you can use FP32 (but slightly large errors): .. code:: ipython3 from jax import config config.update("jax_enable_x64", True) .. code:: ipython3 from exojax.spec.hitran import line_strength from exojax.spec.hitran import doppler_sigma from exojax.spec.hitran import gamma_hitran from exojax.spec.hitran import gamma_natural from exojax.utils.grids import wavenumber_grid from exojax.utils.constants import Tref_original from exojax.spec import api # Setting wavenumber bins and loading HITRAN database nus, wav, resolution = wavenumber_grid( 1900.0, 2300.0, 350000, unit="cm-1", xsmode="dit" ) mdbCO = api.MdbHitran( "CO", nus, isotope=1, gpu_transfer=True ) # here we use the isotope=1 (12C16O) in DIT. # set T, P and partition function Mmol = mdbCO.molmass Tfix = 1000.0 # we assume T=1000K Pfix = 1.0e-3 # we compute P=1.e-3 bar Ppart = Pfix # partial pressure of CO. here we assume a 100% CO atmosphere. qt = mdbCO.qr_interp_lines( Tfix, Tref_original ) # use all isotopes as a partition function # compute Sij, gamma_L, sigmaD Sij = line_strength( Tfix, mdbCO.logsij0, mdbCO.nu_lines, mdbCO.elower, qt, Tref_original ) gammaL = gamma_hitran( Pfix, Tfix, Ppart, mdbCO.n_air, mdbCO.gamma_air, mdbCO.gamma_self ) + gamma_natural(mdbCO.A) sigmaD = doppler_sigma(mdbCO.nu_lines, Tfix, Mmol) .. parsed-literal:: xsmode = dit xsmode assumes ESLIN in wavenumber space: xsmode=dit ====================================================================== The wavenumber grid should be in ascending order. The users can specify the order of the wavelength grid by themselves. Your wavelength grid is in *** descending *** order ====================================================================== radis engine = vaex DIT uses a grid of sigmaD, gammaL, and wavenumber. set_ditgrid.ditgrid_log_interval makes a 1D grid for sigmaD and gamma. .. code:: ipython3 from exojax.spec.set_ditgrid import ditgrid_log_interval sigmaD_grid = ditgrid_log_interval(sigmaD) gammaL_grid = ditgrid_log_interval(gammaL) # we can change the resolution using res option # sigmaD_grid=set_ditgrid(sigmaD,res=0.1) # gammaL_grid=set_ditgrid(gammaL,res=0.1) .. code:: ipython3 # show the grids plt.plot(sigmaD, gammaL, ".") for i in sigmaD_grid: plt.axvline(i, lw=1, alpha=0.5, color="C1") for i in gammaL_grid: plt.axhline(i, lw=1, alpha=0.5, color="C1") .. image:: Cross_Section_using_Discrete_Integral_Transform_files/Cross_Section_using_Discrete_Integral_Transform_8_0.png We need to precompute the contribution for wavenumber. Also, pmarray is needed. These can be computed using init_dit. .. code:: ipython3 from exojax.spec import initspec cnu, indexnu, pmarray = initspec.init_dit(mdbCO.nu_lines, nus) Then, let’s compute a cross section! .. code:: ipython3 from exojax.spec.dit import xsvector xs = xsvector(cnu, indexnu, pmarray, sigmaD, gammaL, Sij, nus, sigmaD_grid, gammaL_grid) Also, we here try the direct computation using Direct-LPF for the comparison purpose .. code:: ipython3 from exojax.spec.opacalc import OpaDirect opa = OpaDirect(mdbCO, nus) xsv = opa.xsvector(Tfix, Pfix, Ppart) The difference is <~ 1%. .. code:: ipython3 fig = plt.figure(figsize=(10, 5)) ax = fig.add_subplot(211) plt.plot(nus, xs, lw=1, alpha=0.5, label="DIT") plt.plot(nus, xsv, lw=1, alpha=0.5, label="Direct LPF") plt.legend(loc="upper right") plt.ylabel("Cross Section (cm2)") ax = fig.add_subplot(212) # plt.plot(nus,xsv-xs,lw=2,alpha=0.5,label="precomputed") plt.plot(nus, xsv - xs, lw=2, alpha=0.5) plt.ylabel("LPF - DIT (cm2)") plt.legend(loc="upper left") plt.show() .. parsed-literal:: /tmp/ipykernel_809841/4022811313.py:11: UserWarning: No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument. plt.legend(loc="upper left") .. image:: Cross_Section_using_Discrete_Integral_Transform_files/Cross_Section_using_Discrete_Integral_Transform_16_1.png