def nm_air2cm(wl_nm_air): '''(air) nm to cm-1 References ---------- :func:`~radis.phys.air.air2vacuum' ''' return nm2cm(air2vacuum(wl_nm_air))
def nm_air2cm(wl_nm_air): """(air) nm to cm-1. References ---------- :func:`~radis.phys.air.air2vacuum' """ return nm2cm(air2vacuum(wl_nm_air))
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
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), )
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), )