Ejemplo n.º 1
0
def nm_air2cm(wl_nm_air):
    '''(air) nm to cm-1
    
    References
    ----------
    
    :func:`~radis.phys.air.air2vacuum'
    '''
    return nm2cm(air2vacuum(wl_nm_air))
Ejemplo n.º 2
0
def nm_air2cm(wl_nm_air):
    """(air) nm to cm-1.

    References
    ----------

    :func:`~radis.phys.air.air2vacuum'
    """
    return nm2cm(air2vacuum(wl_nm_air))
Ejemplo n.º 3
0
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, export_lines, **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 not medium in ["air", "vacuum"]:
        raise NotImplementedError(
            "Unknown propagating medium: {0}".format(medium))

    if wavenum_min is None and wavenum_max is None:
        assert wavelength_max is not None
        assert wavelength_min is not None
        if medium == "vacuum":
            wavenum_min = nm2cm(wavelength_max)
            wavenum_max = nm2cm(wavelength_min)
        else:
            wavenum_min = nm2cm(air2vacuum(wavelength_max))
            wavenum_max = nm2cm(air2vacuum(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,
                         export_lines=export_lines,
                         **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
        # Details to identify lines
        conditions["parse_local_global_quanta"] = (
            not _equilibrium) or export_lines
        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") or databank.endswith(".hdf5"):
            if verbose:
                print("Infered {0} is a HDF5 file with RADISDB columns format".
                      format(databank))
            conditions["format"] = "hdf5-radisdb"
            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
Ejemplo n.º 4
0
def sPlanck(wavenum_min=None,
            wavenum_max=None,
            wavelength_min=None,
            wavelength_max=None,
            T=None,
            eps=1,
            wstep=0.01,
            medium="air",
            **kwargs):
    """Return a RADIS Spectrum object with blackbody radiation.

    It's easier to plug in a MergeSlabs / SerialSlabs config than the Planck
    radiance calculated by iPlanck. And you don't need to worry about units as
    they are handled internally.

    See radis.lbl.Spectrum documentation for more information

    Parameters
    ----------

    wavenum_min / wavenum_max: (cm-1)
        minimum / maximum wavenumber to be processed in cm^-1.

    wavelength_min / wavelength_max: (nm)
        minimum / maximum wavelength to be processed in nm

    T: float (K)
        blackbody temperature

    eps: float [0-1]
        blackbody emissivity. Default 1

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

    wstep: float (cm-1 or nm)
        wavespace step for calculation

    **kwargs: other keyword inputs
        all are forwarded to spectrum conditions. For instance you can add
        a 'path_length=1' after all the other arguments

    Example
    -------

    Generate Earth blackbody::

        s = sPlanck(wavelength_min=3000, wavelength_max=50000,
                    T=288, eps=1)
        s.plot()
    """

    from radis.spectrum.spectrum import Spectrum

    # Check inputs
    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("You cannot give both wavelengths and wavenumbers")

    if wavenum_min is not None and wavenum_max is not None:
        assert wavenum_min < wavenum_max
        waveunit = "cm-1"
    else:
        assert wavelength_min < wavelength_max
        if medium == "air":
            waveunit = "nm"
        elif medium == "vacuum":
            waveunit = "nm_vac"
        else:
            raise ValueError(medium)

    if T is None:
        raise ValueError("T must be defined")

    if not (eps >= 0 and eps <= 1):
        raise ValueError("Emissivity must be in [0-1]")

    # Test range is correct:
    if waveunit == "cm-1":
        # generate the vector of wavenumbers (shape M)
        w = arange(wavenum_min, wavenum_max + wstep, wstep)
        Iunit = "mW/sr/cm2/cm-1"
        I = planck_wn(w, T, eps=eps, unit=Iunit)
    else:
        # generate the vector of lengths (shape M)
        w = arange(wavelength_min, wavelength_max + wstep, wstep)
        Iunit = "mW/sr/cm2/nm"
        if waveunit == "nm_vac":
            w_vac = w
        elif waveunit == "nm":
            w_vac = air2vacuum(w)
        # calculate planck with wavelengths in vacuum
        I = planck(w_vac, T, eps=eps, unit=Iunit)

    conditions = {"wstep": wstep}
    # add all extra parameters in conditions (ex: path_length)
    conditions.update(**kwargs)

    return Spectrum(
        quantities={
            "radiance_noslit": (w, I),
            "transmittance_noslit": (w, zeros_like(w)),
            "absorbance": (w, ones_like(w) * inf),
        },
        conditions=conditions,
        units={
            "radiance_noslit": Iunit,
            "transmittance_noslit": "",
            "absorbance": ""
        },
        cond_units={"wstep": waveunit},
        waveunit=waveunit,
        name="Planck {0}K, eps={1:.2g}".format(T, eps),
    )
Ejemplo n.º 5
0
def sPlanck(
    wavenum_min=None,
    wavenum_max=None,
    wavelength_min=None,
    wavelength_max=None,
    T=None,
    eps=1,
    wstep=0.01,
    medium="air",
    **kwargs
):
    r"""Return a RADIS :py:class:`~radis.spectrum.spectrum.Spectrum` object with blackbody radiation.

    It's easier to plug in a :py:func:`~radis.los.slabs.SerialSlabs` line-of-sight than the Planck
    radiance calculated by :py:func:`~radis.phys.blackbody.planck`.
    And you don't need to worry about units as they are handled internally.

    See :py:class:`~radis.spectrum.spectrum.Spectrum` documentation for more information

    Parameters
    ----------
    wavenum_min / wavenum_max: ():math:`cm^{-1}`)
        minimum / maximum wavenumber to be processed in :math:`cm^{-1}`.
    wavelength_min / wavelength_max: (:math:`nm`)
        minimum / maximum wavelength to be processed in :math:`nm`.
    T: float (K)
        blackbody temperature
    eps: float [0-1]
        blackbody emissivity. Default ``1``

    Other Parameters
    ----------------
    wstep: float (cm-1 or nm)
        wavespace step for calculation
    **kwargs: other keyword inputs
        all are forwarded to spectrum conditions. For instance you can add
        a 'path_length=1' after all the other arguments

    Examples
    --------
    Generate Earth blackbody::

        s = sPlanck(wavelength_min=3000, wavelength_max=50000,
                    T=288, eps=1)
        s.plot()

    Examples using sPlanck :

    .. minigallery:: radis.sPlanck

    References
    ----------
    In wavelength:

    .. math::
        \epsilon \frac{2h c^2}{{\lambda}^5} \frac{1}{\operatorname{exp}\left(\frac{h c}{\lambda k T}\right)-1}

    In wavenumber:

    .. math::
        \epsilon 2h c^2 {\nu}^3 \frac{1}{\operatorname{exp}\left(\frac{h c \nu}{k T}\right)-1}

    See Also
    --------
    :py:func:`~radis.phys.blackbody.planck`, :py:func:`~radis.phys.blackbody.planck_wn`

    """
    from radis.spectrum.spectrum import Spectrum

    # Check inputs
    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("You cannot give both wavelengths and wavenumbers")

    if wavenum_min is not None and wavenum_max is not None:
        assert wavenum_min < wavenum_max
        waveunit = "cm-1"
    else:
        assert wavelength_min < wavelength_max
        if medium == "air":
            waveunit = "nm"
        elif medium == "vacuum":
            waveunit = "nm_vac"
        else:
            raise ValueError(medium)

    if T is None:
        raise ValueError("T must be defined")

    if not (eps >= 0 and eps <= 1):
        raise ValueError("Emissivity must be in [0-1]")

    # Test range is correct:
    if waveunit == "cm-1":
        # generate the vector of wavenumbers (shape M)
        w = arange(wavenum_min, wavenum_max + wstep, wstep)
        Iunit = "mW/sr/cm2/cm-1"
        I = planck_wn(w, T, eps=eps, unit=Iunit)
    else:
        # generate the vector of lengths (shape M)
        w = arange(wavelength_min, wavelength_max + wstep, wstep)
        Iunit = "mW/sr/cm2/nm"
        if waveunit == "nm_vac":
            w_vac = w
        elif waveunit == "nm":
            w_vac = air2vacuum(w)
        # calculate planck with wavelengths in vacuum
        I = planck(w_vac, T, eps=eps, unit=Iunit)

    conditions = {"wstep": wstep}
    # add all extra parameters in conditions (ex: path_length)
    conditions.update(**kwargs)

    return Spectrum(
        quantities={
            "radiance_noslit": (w, I),
            "transmittance_noslit": (w, zeros_like(w)),
            "absorbance": (w, ones_like(w) * inf),
        },
        conditions=conditions,
        units={"radiance_noslit": Iunit, "transmittance_noslit": "", "absorbance": ""},
        cond_units={"wstep": waveunit},
        waveunit=waveunit,
        name="Planck {0}K, eps={1:.2g}".format(T, eps),
    )