def test_broadening_DLM_noneq(verbose=True, plot=False, *args, **kwargs):
    '''
    Test Noneq version of DLM and makes sure it gives the same results as the eq
    one when used with Tvib=Trot 
    
    '''

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        plt.ion()

    setup_test_line_databases()  # add HITRAN-CO2-TEST in ~/.radis if not there

    # Conditions
    p = 1
    wstep = 0.002
    wmin = 2380  # cm-1
    wmax = 2400  # cm-1
    broadening_max_width = 10  # cm-1

    # %% Calculate with RADIS
    # ----------
    sf = SpectrumFactory(
        wavenum_min=wmin,
        wavenum_max=wmax,
        mole_fraction=1,
        path_length=1,   # doesnt change anything
        wstep=wstep,
        pressure=p,
        broadening_max_width=broadening_max_width,
        isotope='1',
        verbose=3,
        warnings={'MissingSelfBroadeningWarning':'ignore',
                  'NegativeEnergiesWarning':'ignore',
                  'HighTemperatureWarning':'ignore',
                  'GaussianBroadeningWarning':'ignore'}
        )  # 0.2)
    sf.load_databank('HITRAN-CO2-TEST')
    
    # DLM:
    sf.misc['chunksize'] = 'DLM'
    s_dlm_eq = sf.eq_spectrum(Tgas=3000)
    s_dlm_eq.name = 'DLM eq ({0:.2f}s)'.format(s_dlm_eq.conditions['calculation_time'])
    
    s_dlm_noneq = sf.non_eq_spectrum(Tvib=3000, Trot=3000)
    s_dlm_noneq.name = 'DLM noneq ({0:.2f}s)'.format(s_dlm_noneq.conditions['calculation_time'])
    
    # Compare
    res = get_residual(s_dlm_eq, s_dlm_noneq, 'radiance_noslit')
    
    if verbose:
        print('Residual:', res)

    # plot
    if plot:
        plot_diff(s_dlm_eq, s_dlm_noneq)
    
    assert res <= 4e-5 
示例#2
0
def test_noneq_continuum(plot=False,
                         verbose=2,
                         warnings=True,
                         *args,
                         **kwargs):
    """
    Test calculation with pseudo-continuum under nonequilibrium

    Assert results on emisscoeff dont change


    Notes
    -----

    Uses HITRAN so it can deployed and tested on `Travis CI <https://travis-ci.com/radis/radis>`_, but we should switch
    to HITEMP if some HITEMP files can be downloaded automatically at the
    execution time.

    """

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        plt.ion()

    if verbose:
        printm(">>> test_noneq_continuum")

    sf = SpectrumFactory(
        wavelength_min=4200,
        wavelength_max=4500,
        cutoff=1e-23,
        molecule="CO2",
        isotope="1,2",
        broadening_max_width=10,
        path_length=0.1,
        mole_fraction=1e-3,
        medium="vacuum",
        optimization=None,
        verbose=verbose,
    )
    sf.warnings.update({
        "MissingSelfBroadeningWarning": "ignore",
        "NegativeEnergiesWarning": "ignore",
        "LinestrengthCutoffWarning": "ignore",
        "HighTemperatureWarning": "ignore",
    })
    sf.fetch_databank(
        "hitran"
    )  # uses HITRAN: not really valid at this temperature, but runs on all machines without install
    #        sf.load_databank('HITEMP-CO2-DUNHAM')       # to take a real advantage of abscoeff continuum, should calculate with HITEMP
    sf._export_continuum = True  # activate it

    # Calculate one without pseudo-continuum
    sf.params.pseudo_continuum_threshold = 0
    s1 = sf.non_eq_spectrum(Tvib=2000, Trot=1000)
    s1.name = "All lines resolved ({0}) ({1:.1f}s)".format(
        s1.conditions["lines_calculated"], s1.conditions["calculation_time"])
    assert s1.conditions["pseudo_continuum_threshold"] == 0

    # Calculate one with pseudo-continuum
    sf.params.pseudo_continuum_threshold = 0.05
    s2 = sf.non_eq_spectrum(Tvib=2000, Trot=1000)
    s2.name = "Semi-continuum + {0} lines ({1:.1f}s)".format(
        s2.conditions["lines_calculated"], s2.conditions["calculation_time"])
    assert s2.conditions["pseudo_continuum_threshold"] == 0.05
    assert "abscoeff_continuum" in s2.get_vars()
    assert "emisscoeff_continuum" in s2.get_vars()

    # Plot
    if plot:
        plot_diff(
            s1,
            s2,
            "radiance_noslit",
            Iunit="µW/cm2/sr/nm",
            nfig="test_noneq_continuum: diff",
        )

        plt.figure("test_noneq_continuum: show continuum").clear()
        s2.plot("emisscoeff",
                label=s2.name,
                nfig="test_noneq_continuum: show continuum")
        s2.plot(
            "emisscoeff_continuum",
            nfig="same",
            label="Pseudo-continuum (aggreg. {0:g} lines)".format(
                s2.conditions["lines_in_continuum"]),
            force=True,
        )

    # Compare
    res = get_residual(s1, s2, "abscoeff") + get_residual(s1, s2, "emisscoeff")
    if verbose:
        printm("residual:", res)

    assert res < 5.2e-6
示例#3
0
def test_noneq_continuum(plot=False,
                         verbose=2,
                         warnings=True,
                         *args,
                         **kwargs):
    ''' 
    Test calculation with pseudo-continuum under nonequilibrium

    Assert results on emisscoeff dont change

    
    Notes
    -----
    
    Uses HITRAN so it can deployed and tested on [Travis]_, but we should switch
    to HITEMP if some HITEMP files can be downloaded automatically at the 
    execution time. 

    '''

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        plt.ion()

    try:
        if verbose:
            printm('>>> test_noneq_continuum')

        sf = SpectrumFactory(wavelength_min=4200,
                             wavelength_max=4500,
                             parallel=False,
                             bplot=False,
                             cutoff=1e-23,
                             molecule='CO2',
                             isotope='1,2',
                             db_use_cached=True,
                             broadening_max_width=10,
                             path_length=0.1,
                             mole_fraction=1e-3,
                             medium='vacuum',
                             verbose=verbose)
        sf.warnings.update({
            'MissingSelfBroadeningWarning': 'ignore',
            'NegativeEnergiesWarning': 'ignore',
            'LinestrengthCutoffWarning': 'ignore',
            'HighTemperatureWarning': 'ignore'
        })
        sf.fetch_databank(
        )  # uses HITRAN: not really valid at this temperature, but runs on all machines without install
        #        sf.load_databank('HITEMP-CO2-DUNHAM')       # to take a real advantage of abscoeff continuum, should calculate with HITEMP
        sf._export_continuum = True  # activate it

        # Calculate one without pseudo-continuum
        sf.params.pseudo_continuum_threshold = 0
        s1 = sf.non_eq_spectrum(Tvib=2000, Trot=1000)
        s1.name = 'All lines resolved ({0}) ({1:.1f}s)'.format(
            s1.conditions['lines_calculated'],
            s1.conditions['calculation_time'])
        assert s1.conditions['pseudo_continuum_threshold'] == 0

        # Calculate one with pseudo-continuum
        sf.params.pseudo_continuum_threshold = 0.05
        s2 = sf.non_eq_spectrum(Tvib=2000, Trot=1000)
        s2.name = 'Semi-continuum + {0} lines ({1:.1f}s)'.format(
            s2.conditions['lines_calculated'],
            s2.conditions['calculation_time'])
        assert s2.conditions['pseudo_continuum_threshold'] == 0.05
        assert 'abscoeff_continuum' in s2.get_vars()
        assert 'emisscoeff_continuum' in s2.get_vars()

        # Plot
        if plot:
            plot_diff(s1,
                      s2,
                      'radiance_noslit',
                      Iunit='µW/cm2/sr/nm',
                      nfig='test_noneq_continuum: diff')

            s2.plot('emisscoeff',
                    label=s2.name,
                    nfig='test_noneq_continuum: show continuum')
            s2.plot('emisscoeff_continuum',
                    nfig='same',
                    label='Pseudo-continuum (aggreg. {0:g} lines)'.format(
                        s2.conditions['lines_in_continuum']),
                    force=True)

        # Compare
        res = get_residual(s1, s2, 'abscoeff') + get_residual(
            s1, s2, 'emisscoeff')
        if verbose:
            printm('residual:', res)

        assert res < 5e-6

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
示例#4
0
文件: calc.py 项目: BlehMaks/radis-1
def _calc_spectrum(
    wavenum_min,
    wavenum_max,
    wavelength_min,
    wavelength_max,
    Tgas,
    Tvib,
    Trot,
    pressure,
    overpopulation,
    molecule,
    isotope,
    mole_fraction,
    path_length,
    databank,
    medium,
    wstep,
    broadening_max_width,
    cutoff,
    optimization,
    name,
    use_cached,
    verbose,
    mode,
    **kwargs
):
    """See :py:func:`~radis.lbl.calc.calc_spectrum`"""

    # Check inputs

    # ... wavelengths / wavenumbers
    if (wavelength_min is not None or wavelength_max is not None) and (
        wavenum_min is not None or wavenum_max is not None
    ):
        raise ValueError("Wavenumber and Wavelength both given... it's time to choose!")

    if wavenum_min is None and wavenum_max is None:
        assert wavelength_max is not None
        assert wavelength_min is not None
        wavenum_min = nm2cm(wavelength_max)
        wavenum_max = nm2cm(wavelength_min)
    else:
        assert wavenum_min is not None
        assert wavenum_max is not None

    # ... temperatures

    if Tgas is None and Trot is None:
        raise ValueError(
            "Choose either Tgas (equilibrium) or Tvib / Trot (non equilibrium)"
        )

    if Tvib is None and Trot is not None or Tvib is not None and Trot is None:
        raise ValueError("Choose both Tvib and Trot")

    # ... others
    if databank is None:
        raise ValueError("Give a databank name")

    if not "save_memory" in kwargs:
        # no need to save intermediary results as
        # factory is used once only
        kwargs["save_memory"] = True

    if "chunksize" in kwargs:
        raise DeprecationWarning("use optimization= instead of chunksize=")

    def _is_at_equilibrium():
        try:
            assert Tvib is None or Tvib == Tgas
            assert Trot is None or Trot == Tgas
            assert overpopulation is None
            if "self_absorption" in kwargs:
                assert kwargs["self_absorption"]  # == True
            return True
        except AssertionError:
            return False

    _equilibrium = _is_at_equilibrium()

    # which columns to keep when loading line database
    if kwargs["save_memory"] >= 2 and _equilibrium:
        drop_columns = "all"
    else:
        drop_columns = "auto"

    # Run calculations
    sf = SpectrumFactory(
        wavenum_min,
        wavenum_max,
        medium=medium,
        molecule=molecule,
        isotope=isotope,
        pressure=pressure,
        wstep=wstep,
        broadening_max_width=broadening_max_width,
        cutoff=cutoff,
        verbose=verbose,
        optimization=optimization,
        **kwargs
    )
    if databank in [
        "fetch",
        "hitran",
        "hitemp",
    ]:  # mode to get databank without relying on  Line databases
        # Line database :
        if databank in ["fetch", "hitran"]:
            conditions = {"source": "hitran"}
        elif databank in ["hitemp"]:
            conditions = {"source": "hitemp"}
        # Partition functions :
        conditions.update(
            **{
                "parfuncfmt": "hapi",  # use HAPI (TIPS) partition functions for equilibrium
                "levelsfmt": None,  # no need to load energies by default
                "db_use_cached": use_cached,
            }
        )
        # Rovibrational energies :
        if not _equilibrium:
            # calculate partition functions with energy levels from built-in
            # constants (not all molecules are supported!)
            conditions["levelsfmt"] = "radis"
            conditions["lvl_use_cached"] = use_cached
        sf.fetch_databank(**conditions)
    elif exists(databank):
        conditions = {
            "path": databank,
            "drop_columns": drop_columns,
            "parfuncfmt": "hapi",  # use HAPI (TIPS) partition functions for equilibrium
            "levelsfmt": None,  # no need to load energies by default
            "db_use_cached": use_cached,
        }
        # Guess format
        if databank.endswith(".par"):
            if verbose:
                print("Infered {0} is a HITRAN-format file.".format(databank))
            conditions["format"] = "hitran"
            # If non-equilibrium we'll also need to load the energy levels.
            if not _equilibrium:
                # calculate partition functions with energy levels from built-in
                # constants (not all molecules are supported!)
                conditions["levelsfmt"] = "radis"
                conditions["lvl_use_cached"] = use_cached
        elif databank.endswith(".h5"):
            conditions["format"] = "hdf5"
            if not _equilibrium:
                conditions["levelsfmt"] = "radis"
        else:
            raise ValueError(
                "Couldnt infer the format of the line database file: {0}. ".format(
                    databank
                )
                + "Create a user-defined database in your ~/.radis file "
                + "and define the format there. More information on "
                + "https://radis.readthedocs.io/en/latest/lbl/lbl.html#configuration-file"
            )

        sf.load_databank(**conditions)

    else:  # manual mode: get from user-defined line databases defined in ~/.radis
        sf.load_databank(
            databank,
            load_energies=not _equilibrium,  # no need to load/calculate energies at eq.
            drop_columns=drop_columns,
        )

    #    # Get optimisation strategies
    #    if lineshape_optimization == 'auto':        # NotImplemented: finally we use DLM all the time as default.
    #        if len(sf.df0) > 1e5:
    #            lineshape_optimization = 'DLM'
    #        else:
    #            lineshape_optimization = None
    #        sf.params['chunksize'] = lineshape_optimization

    # Use the standard eq_spectrum / non_eq_spectrum functions
    if _equilibrium:
        if mode == "cpu":
            s = sf.eq_spectrum(
                Tgas=Tgas,
                mole_fraction=mole_fraction,
                path_length=path_length,
                name=name,
            )
        else:
            s = sf.eq_spectrum_gpu(
                Tgas=Tgas,
                mole_fraction=mole_fraction,
                pressure=pressure,
                path_length=path_length,
                name=name,
            )
    else:
        s = sf.non_eq_spectrum(
            Tvib=Tvib,
            Trot=Trot,
            Ttrans=Tgas,
            overpopulation=overpopulation,
            mole_fraction=mole_fraction,
            path_length=path_length,
            name=name,
        )

    return s
示例#5
0
文件: calc.py 项目: ulyssed/radis
def calc_spectrum(
    wavenum_min=None,
    wavenum_max=None,
    wavelength_min=None,
    wavelength_max=None,
    Tgas=None,
    Tvib=None,
    Trot=None,
    pressure=1.01325,
    overpopulation=None,
    molecule="",
    isotope="all",
    mole_fraction=1,
    path_length=1,
    databank="fetch",
    medium="air",
    wstep=0.01,
    broadening_max_width=10,
    lineshape_optimization="DLM",
    name=None,
    use_cached=True,
    verbose=True,
    **kwargs
):
    """ Multipurpose function to calculate :class:`~radis.spectrum.spectrum.Spectrum`
    under equilibrium, or non-equilibrium, with or without overpopulation. 
    It's a wrapper to :class:`~radis.lbl.factory.SpectrumFactory` class. 
    For advanced used, please refer to the aforementionned class. 

    Parameters
    ----------

    wavenum_min: float(cm^-1) or `~astropy.units.quantity.Quantity`
        minimum wavenumber.
    wavenum_max: float(cm^-1) or `~astropy.units.quantity.Quantity`
        maximum wavenumber.

    wavelength_min: float(nm) or `~astropy.units.quantity.Quantity`
        minimum wavelength. Wavelength in ``'air'`` or 
        ``'vacuum'`` depending of the value of the parameter ``'medium='``
    wavelength_max: float(nm) or `~astropy.units.quantity.Quantity`
        maximum wavelength. Wavelength in ``'air'`` or 
        ``'vacuum'`` depending of the value of the parameter ``'medium='``

    Tgas: float(K) or `~astropy.units.quantity.Quantity`
        Gas temperature. If non equilibrium, is used for Ttranslational. 
        Default ``300`` K

    Tvib: float(K) or `~astropy.units.quantity.Quantity`
        Vibrational temperature. If ``None``, equilibrium calculation is run with Tgas

    Trot: float(K) or `~astropy.units.quantity.Quantity`
        Rotational temperature. If ``None``, equilibrium calculation is run with Tgas

    pressure: float(bar) or `~astropy.units.quantity.Quantity`
        partial pressure of gas. Default ``1.01325`` (1 atm)

    overpopulation: dict
        dictionary of overpopulation compared to the given vibrational temperature. 
        Ex with CO2::

            overpopulation = {
            '(00`0`0)->(00`0`1)': 2.5,
                '(00`0`1)->(00`0`2)': 1,
                '(01`1`0)->(01`1`1)': 1,
                '(01`1`1)->(01`1`2)': 1,
                }

    molecule: int, str, or ``None``
        molecule id (HITRAN format) or name. If ``None``, the molecule can be infered
        from the database files being loaded. See the list of supported molecules 
        in :py:data:`~radis.io.MOLECULES_LIST_EQUILIBRIUM`
        and :py:data:`~radis.io.MOLECULES_LIST_NONEQUILIBRIUM`. 
        Default ``None``. 

    isotope: int, list, str of the form ``'1,2'``, or ``'all'``
        isotope id (sorted by relative density: (eg: 1: CO2-626, 2: CO2-636 for CO2).
        See [HITRAN-2016]_ documentation for isotope list for all species. If ``'all'``,
        all isotopes in database are used (this may result in larger computation
        times!). Default ``'all'``

    mole_fraction: float
        database species mole fraction. Default ``1``

    path_length: float(cm) or `~astropy.units.quantity.Quantity`
        slab size. Default ``1`` cm.

    databank: str
        can be either: 

        - ``'fetch'``, to fetch automatically from [HITRAN-2016]_ through astroquery. 
        
        .. warning::
            
            [HITRAN-2016]_ is valid for low temperatures (typically < 700 K). For higher
            temperatures you may need [HITEMP-2010]_ 

        - the path to a valid database file, in which case the format is inferred. 
          For instance, ``.par`` is recognized as ``hitran/hitemp`` format. 

        - the name of a spectral database registered in your ``~/.radis`` 
          configuration file. This allows to use multiple database files.
          See :ref:`Configuration file <label_lbl_config_file>`.

        Default ``'fetch'``. See :class:`~radis.lbl.loader.DatabankLoader` for more 
        information on line databases, and :data:`~radis.misc.config.DBFORMAT` for 
        your ``~/.radis`` file format 
        
        Example::
        
            databank='fetch'     # automatic download 
            databank='PATH/TO/05_HITEMP2019.par'    # path to a file 
            databank='HITEMP-2019-CO'   # user-defined database in Configuration file 

    medium: ``'air'``, ``'vacuum'``
        propagating medium when giving inputs with ``'wavenum_min'``, ``'wavenum_max'``. 
        Does not change anything when giving inputs in wavenumber. Default ``'air'``

    wstep: float (cm-1)
        Spacing of calculated spectrum. Default ``0.01`` cm-1.

    broadening_max_width: float (cm-1)
        Full width over which to compute the broadening. Large values will create
        a huge performance drop (scales as ~broadening_width^2 without DLM)
        The calculated spectral range is increased (by broadening_max_width/2
        on each side) to take into account overlaps from out-of-range lines.
        Default ``10`` cm-1.

    Other Parameters
    ----------------

    lineshape_optimization: int, ``None``, ``'DLM'``, or ``'auto'``.
        Optimizations for the calculation of the lineshapes:
        
            - If ``None``, all lineshapes are calculated at the same time (can 
              create memory errors). 
            - If ``int``, is given as the ``chunksize`` parameter of 
              :py:class:`~radis.lbl.factory.SpectrumFactory`` to split the line database 
              in several parts so that the number of ``lines * spectral grid points`` is 
              less than ``chunksize`` (reduces memory consumption). Typical values: 
              ``lineshape_optimization=1e6``.
            - If ``'DLM'``, only typical lineshapes are calculated. This can 
              result of speedups of orders of magnitude.  See more about DLM in 
              :ref:`Performance <label_lbl_performance>`. 
              
        Default ``'DLM'``.

    slit: float, str, or ``None``
        if float, FWHM of a triangular slit function. If str, path to an 
        experimental slit function. If None, no slit is applied. Default ``None``.

    plot: str
        any parameter such as 'radiance' (if slit is given), 'radiance_noslit', 
        'absorbance', etc...   Default ``None``

    name: str
        name of the case. If None, a unique ID is generated. Default ``None``

    use_cached: boolean
        use cached files for line database and energy database. Default ``True``

    verbose: boolean, or int
        If ``False``, stays quiet. If ``True``, tells what is going on. 
        If ``>=2``, gives more detailed messages (for instance, details of 
        calculation times). Default ``True``. 

    **kwargs: other inputs forwarded to SpectrumFactory
        For instance: ``warnings``. 
        See :class:`~radis.lbl.factory.SpectrumFactory` documentation for more 
        details on input. 
        For instance:

    pseudo_continuum_threshold: float
        if not 0, first calculate a rough approximation of the spectrum, then
        moves all lines whose linestrength intensity is less than this threshold
        of the maximum in a semi-continuum. Values above 0.01 can yield significant
        errors, mostly in highly populated areas. 80% of the lines can typically
        be moved in a continuum, resulting in 5 times faster spectra. If 0,
        no semi-continuum is used. Default 0.

    Returns
    -------
    
    s: :class:`~radis.spectrum.spectrum.Spectrum`
        Output spectrum.

        Use the :py:meth:`~radis.spectrum.spectrum.Spectrum.get` method to retrieve a 
        spectral quantity (``'radiance'``, ``'radiance_noslit'``, ``'absorbance'``, etc...)

        Or the :py:meth:`~radis.spectrum.spectrum.Spectrum.plot` method to plot it
        directly.

        See [1]_ to get an overview of all Spectrum methods

    References
    ----------

    .. [1] RADIS doc: `Spectrum how to? <https://radis.readthedocs.io/en/latest/spectrum/spectrum.html#label-spectrum>`__


    Examples
    --------

    Calculate a CO spectrum from the HITRAN database::

        s = calc_spectrum(1900, 2300,         # cm-1
                          molecule='CO',
                          isotope='1,2,3',
                          pressure=1.01325,   # bar
                          Tgas=1000, 
                          mole_fraction=0.1, 
                          )
        s.apply_slit(0.5, 'nm')
        s.plot('radiance')
        
    This example uses the :py:meth:`~radis.spectrum.spectrum.Spectrum.apply_slit` 
    and :py:meth:`~radis.spectrum.spectrum.Spectrum.plot` methods. See also
    :py:meth:`~radis.spectrum.spectrum.Spectrum.line_survey`:: 
        
        s.line_survey(overlay='radiance')

    Refer to the online :ref:`Examples <label_examples>` for more cases, and to 
    the :ref:`Spectrum page <label_spectrum>` for details on post-processing methods. 

    See Also
    --------
    
    :class:`~radis.lbl.factory.SpectrumFactory`, 
    the :ref:`Spectrum page <label_spectrum>`
    """

    # Check inputs

    # ... wavelengths / wavenumbers
    if (wavelength_min is not None or wavelength_max is not None) and (
        wavenum_min is not None or wavenum_max is not None
    ):
        raise ValueError("Wavenumber and Wavelength both given... it's time to choose!")

    if wavenum_min is None and wavenum_max is None:
        assert wavelength_max is not None
        assert wavelength_min is not None
        wavenum_min = nm2cm(wavelength_max)
        wavenum_max = nm2cm(wavelength_min)
    else:
        assert wavenum_min is not None
        assert wavenum_max is not None

    # ... temperatures

    if Tgas is None and Trot is None:
        raise ValueError(
            "Choose either Tgas (equilibrium) or Tvib / Trot (non equilibrium)"
        )

    if Tvib is None and Trot is not None or Tvib is not None and Trot is None:
        raise ValueError("Choose both Tvib and Trot")

    # ... others
    if databank is None:
        raise ValueError("Give a databank name")

    if not "save_memory" in kwargs:
        # no need to save intermediary results as
        # factory is used once only
        kwargs["save_memory"] = True

    if "chunksize" in kwargs:
        raise DeprecationWarning("use lineshape_optimization= instead of chunksize=")

    def _is_at_equilibrium():
        try:
            assert Tvib is None or Tvib == Tgas
            assert Trot is None or Trot == Tgas
            assert overpopulation is None
            if "self_absorption" in kwargs:
                assert kwargs["self_absorption"]  # == True
            return True
        except AssertionError:
            return False

    _equilibrium = _is_at_equilibrium()

    # which columns to keep when loading line database
    if kwargs["save_memory"] >= 2 and _equilibrium:
        drop_columns = "all"
    else:
        drop_columns = "auto"

    # Run calculations
    sf = SpectrumFactory(
        wavenum_min,
        wavenum_max,
        medium=medium,
        molecule=molecule,
        isotope=isotope,
        pressure=pressure,
        wstep=wstep,
        broadening_max_width=broadening_max_width,
        db_use_cached=use_cached,
        verbose=verbose,
        chunksize=lineshape_optimization,  #  if lineshape_optimization != 'auto' else None, #@EP: NotImplemented. DLM use all the time by default
        **kwargs
    )
    if databank == "fetch":  # mode to get databank without relying on  Line databases
        if _equilibrium:
            # Get line database from HITRAN
            # and partition functions from HAPI
            sf.fetch_databank(
                source="astroquery",
                format="hitran",
                parfuncfmt="hapi",  # use HAPI partition functions for equilibrium
                levelsfmt=None,  # no need to load energies
            )
        else:
            # Also get line database from HITRAN, and calculate partition functions
            # with energy levels from built-in constants (not all molecules
            # are supported!)
            sf.fetch_databank(
                source="astroquery",
                format="hitran",
                parfuncfmt="hapi",  # use HAPI partition functions for equilibrium
                levelsfmt="radis",  # built-in spectroscopic constants
            )
    elif exists(databank):
        # Guess format
        if databank.endswith(".par"):
            if verbose:
                print("Infered {0} is a HITRAN-format file.".format(databank))
            # If non-equilibrium we'll also need to load the energy levels.
            if _equilibrium:
                # Get partition functions from HAPI
                sf.load_databank(
                    path=databank,
                    format="hitran",
                    parfuncfmt="hapi",  # use HAPI partition functions for equilibrium
                    levelsfmt=None,  # no need to load energies
                    drop_columns=drop_columns,
                )
            else:
                # calculate partition functions with energy levels from built-in
                # constants (not all molecules are supported!)
                sf.load_databank(
                    path=databank,
                    format="hitran",
                    parfuncfmt="hapi",  # use HAPI partition functions for equilibrium
                    levelsfmt="radis",  # built-in spectroscopic constants
                    drop_columns=drop_columns,
                )
        else:
            raise ValueError(
                "Couldnt infer the format of the line database file: {0}. ".format(
                    databank
                )
                + "Create a user-defined database in your ~/.radis file "
                + "and define the format there. More information on "
                + "https://radis.readthedocs.io/en/latest/lbl/lbl.html#configuration-file"
            )

    else:  # manual mode: get from user-defined line databases defined in ~/.radis
        sf.load_databank(
            databank,
            load_energies=not _equilibrium,  # no need to load/calculate energies at eq.
            drop_columns=drop_columns,
        )

    #    # Get optimisation strategies
    #    if lineshape_optimization == 'auto':        # NotImplemented: finally we use DLM all the time as default.
    #        if len(sf.df0) > 1e5:
    #            lineshape_optimization = 'DLM'
    #        else:
    #            lineshape_optimization = None
    #        sf.params['chunksize'] = lineshape_optimization

    # Use the standard eq_spectrum / non_eq_spectrum functions
    if _equilibrium:
        s = sf.eq_spectrum(
            Tgas=Tgas, mole_fraction=mole_fraction, path_length=path_length, name=name
        )
    else:
        s = sf.non_eq_spectrum(
            Tvib=Tvib,
            Trot=Trot,
            Ttrans=Tgas,
            overpopulation=overpopulation,
            mole_fraction=mole_fraction,
            path_length=path_length,
            name=name,
        )

    return s
示例#6
0
def test_power_integral(verbose=True, warnings=True, *args, **kwargs):
    """Test direct calculation of power integral from Einstein coefficients
    matches integration of broadened spectrum in the optically thin case

    We compare:

    - direct calculation of power integral with equilibrium code
        :meth:`~radis.lbl.SpectrumFactory.optically_thin_power` (T)
    - direct calculation of power integral with non equilibrium code
        :meth:`~radis.lbl.SpectrumFactory.optically_thin_power` (T,T)
    - numerical integration of non equilibrium spectrum under optically thin conditions:
        :meth:`~radis.spectrum.spectrum.Spectrum.get_power`

    Test passes if error < 0.5%

    """

    if verbose:
        printm(">>> _test_power_integral")

    setup_test_line_databases()  # add HITRAN-CO-TEST in ~/.radis if not there

    sf = SpectrumFactory(
        wavelength_min=4300,
        wavelength_max=4666,
        wstep=0.001,
        cutoff=1e-30,
        path_length=10,
        mole_fraction=400e-6,
        isotope=[1],
        broadening_max_width=10,
        verbose=verbose,
    )
    sf.warnings.update(
        {
            "MissingSelfBroadeningWarning": "ignore",
            "OutOfRangeLinesWarning": "ignore",
            "HighTemperatureWarning": "ignore",
        }
    )
    sf.load_databank("HITRAN-CO-TEST", db_use_cached=True)
    unit = "µW/sr/cm2"
    T = 600

    # Calculate:

    # ... direct calculation of power integral with equilibrium code
    Peq = sf.optically_thin_power(Tgas=T, unit=unit)

    # ... direct calculation of power integral with non equilibrium code
    Pneq = sf.optically_thin_power(Tvib=T, Trot=T, unit=unit)

    # ... numerical integration of non equilibrium spectrum under optically thin
    # ... conditions
    sf.input.self_absorption = False
    s = sf.non_eq_spectrum(T, T)

    assert s.conditions["self_absorption"] == False

    # Compare
    err = abs(Peq - s.get_power(unit=unit)) / Peq
    if verbose:
        printm("Emission integral:\t{0:.4g}".format(Peq), unit)
        printm("Emission (noneq code):\t{0:.4g}".format(Pneq), unit)
        printm("Integrated spectrum:\t{0:.4g}".format(s.get_power(unit=unit)), unit)
        printm("Error: {0:.2f}%".format(err * 100))

    assert err < 0.005