def test_rescaling_mole_fraction(debug=False, plot=False, verbose=True, warnings=True, *args, **kwargs): """ Test rescaling functions """ from radis.lbl import SpectrumFactory if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there Tgas = 1500 sf = SpectrumFactory( wavelength_min=4400, wavelength_max=4800, # mole_fraction=1, path_length=0.1, mole_fraction=0.01, cutoff=1e-25, wstep=0.005, isotope=[1], db_use_cached=True, self_absorption=True, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.load_databank("HITRAN-CO-TEST") error = [] N = [1e-3, 1e-2, 1e-1, 0.3, 0.6, 1] # first is ref for Ni in N: s1 = sf.non_eq_spectrum(Tgas, Tgas, mole_fraction=N[0]) sN = sf.non_eq_spectrum(Tgas, Tgas, mole_fraction=Ni) s1.rescale_mole_fraction(Ni) error.append(sN.get_power() / s1.get_power()) if plot: plt.figure(fig_prefix + "Rescaling mole fractions") plt.plot(N, error, "-ok") plt.scatter( N[0], error[0], s=200, facecolors="none", edgecolors="r", label="reference", ) plt.xlabel("Mole fraction") plt.ylabel("scaled energy / ab initio energy") plt.xscale("log") plt.legend() plt.title("Effect of scaling mole fraction w/o lineshape update") plt.tight_layout() # less than 1% error when rescaling from 1e-3 to 0.6 assert abs(error[-2] - 1) < 0.01
def test_rescaling_path_length(debug=False, plot=False, verbose=True, warnings=True, *args, **kwargs): """ Test rescaling functions """ if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() try: from radis.lbl import SpectrumFactory setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there Tgas = 1500 sf = SpectrumFactory( wavelength_min=4400, wavelength_max=4800, mole_fraction=0.01, # path_length=0.1, cutoff=1e-25, wstep=0.005, isotope=[1], db_use_cached=True, self_absorption=True, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" # sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.load_databank("HITRAN-CO-TEST") s1 = sf.non_eq_spectrum(Tgas, Tgas, path_length=0.01) s2 = sf.non_eq_spectrum(Tgas, Tgas, path_length=3) s1.rescale_path_length(3) if plot: fig = plt.figure(fig_prefix + "Rescaling path length") s2.plot("radiance_noslit", nfig=fig.number, lw=3, label="L=3m") s1.plot( "radiance_noslit", nfig=fig.number, color="r", label="L=0.01m, rescaled to 3m", ) plt.title("Non optically thin rescaling") plt.legend() plt.tight_layout() if verbose: printm("Test rescaling:") printm("... Difference: {0:.2f}%".format( abs(s1.get_power() / s2.get_power() - 1) * 100)) assert np.isclose(s2.get_power(), s1.get_power(), 2e-3) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_medium(plot=False, verbose=True, debug=False, warnings=True, *args, **kwargs): """ Test effect of propagating medium """ from radis.lbl.factory import SpectrumFactory if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() T = 300 try: setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there pl = SpectrumFactory( wavenum_min=2171.5, wavenum_max=2174, mole_fraction=0.01, medium="vacuum", isotope="1,2", ) pl.warnings["MissingSelfBroadeningWarning"] = "ignore" pl.load_databank("HITRAN-CO-TEST") s = pl.non_eq_spectrum(Tvib=T, Trot=T) # , Ttrans=300) pla = SpectrumFactory( wavenum_min=2171.5, wavenum_max=2174, mole_fraction=0.01, medium="air", isotope="1,2", ) pla.load_databank("HITRAN-CO-TEST") s_air = pla.non_eq_spectrum(Tvib=T, Trot=T) # , Ttrans=300) if plot: plt.figure(fig_prefix + "Propagating medium conversions") s.plot(wunit="nm_vac", nfig="same", lw=3, label="vacuum") s.plot(wunit="nm", nfig="same", label="air") assert np.allclose(s.get_wavenumber(), s_air.get_wavenumber()) assert np.allclose(s.get_wavelength(medium="vacuum"), s_air.get_wavelength(medium="vacuum")) assert np.allclose(s.get_wavelength(medium="air"), s_air.get_wavelength(medium="air")) assert all( s.get_wavelength(medium="vacuum") > s.get_wavelength(medium="air")) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_rescaling_mole_fraction(debug=False, plot=False, verbose=True, warnings=True, *args, **kwargs): ''' Test rescaling functions ''' from radis.lbl import SpectrumFactory if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() try: setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there Tgas = 1500 sf = SpectrumFactory( wavelength_min=4400, wavelength_max=4800, # mole_fraction=1, path_length=0.1, mole_fraction=0.01, cutoff=1e-25, wstep=0.005, isotope=[1], db_use_cached=True, self_absorption=True, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.load_databank('HITRAN-CO-TEST') error = [] N = [1e-3, 1e-2, 1e-1, 0.3, 0.6, 1] # first is ref for Ni in N: s1 = sf.non_eq_spectrum(Tgas, Tgas, mole_fraction=N[0]) sN = sf.non_eq_spectrum(Tgas, Tgas, mole_fraction=Ni) s1.rescale_mole_fraction(Ni) error.append(sN.get_power() / s1.get_power()) if plot: plt.figure(fig_prefix+'Rescaling mole fractions') plt.plot(N, error, '-ok') plt.scatter(N[0], error[0], s=200, facecolors='none', edgecolors='r', label='reference') plt.xlabel('Mole fraction') plt.ylabel('scaled energy / ab initio energy') plt.xscale('log') plt.legend() plt.title('Effect of scaling mole fraction w/o lineshape update') plt.tight_layout() # less than 1% error when rescaling from 1e-3 to 0.6 assert abs(error[-2]-1) < 0.01 except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_populations(verbose=True, *args, **kwargs): """ Test that vib and rovib populations are calculated correctly """ from radis.lbl import SpectrumFactory from radis.misc.basics import all_in export = ["vib", "rovib"] sf = SpectrumFactory( 2000, 2300, export_populations=export, db_use_cached=True, cutoff=1e-25, isotope="1", ) sf.warnings.update({ "MissingSelfBroadeningWarning": "ignore", "VoigtBroadeningWarning": "ignore" }) sf.load_databank("HITRAN-CO-TEST") s = sf.non_eq_spectrum(2000, 2000) pops = sf.get_populations(export) if not all_in(["rovib", "vib"], list(pops["CO"][1]["X"].keys())): raise AssertionError( "vib and rovib levels should be defined after non_eq_spectrum calculation!" ) if not "nvib" in list(pops["CO"][1]["X"]["vib"].keys()): raise AssertionError( "Vib populations should be defined after non_eq_spectrum calculation!" ) s = sf.eq_spectrum(300) pops = sf.get_populations(export) if "nvib" in list(pops["CO"][1]["X"]["vib"].keys()): raise AssertionError( "Vib levels should not be defined anymore after eq_spectrum calculation!" ) # Any of these is True and something went wrong s = sf.non_eq_spectrum(2000, 2000) s2 = sf.non_eq_spectrum(300, 300) # printm(all(s2.get_vib_levels(isotope=1) == s.get_vib_levels(isotope=1))) assert not (s2.get_vib_levels() is s.get_vib_levels()) assert not (s2.get_rovib_levels() == s.get_rovib_levels()).all().all() assert not (s2.get_rovib_levels() is s.get_rovib_levels()) return True # if no AssertionError
def test_populations(verbose=True, *args, **kwargs): ''' Test that vib and rovib populations are calculated correctly ''' from radis.lbl import SpectrumFactory from radis.misc.basics import all_in export = ['vib', 'rovib'] sf = SpectrumFactory(2000, 2300, export_populations=export, db_use_cached=True, cutoff=1e-25, isotope='1') sf.warnings.update({ 'MissingSelfBroadeningWarning': 'ignore', 'VoigtBroadeningWarning': 'ignore' }) sf.load_databank('HITRAN-CO-TEST') s = sf.non_eq_spectrum(2000, 2000) pops = sf.get_populations(export) if not all_in(['rovib', 'vib'], list(pops['CO'][1]['X'].keys())): raise AssertionError( 'vib and rovib levels should be defined after non_eq_spectrum calculation!' ) if not 'nvib' in list(pops['CO'][1]['X']['vib'].keys()): raise AssertionError( 'Vib populations should be defined after non_eq_spectrum calculation!' ) s = sf.eq_spectrum(300) pops = sf.get_populations(export) if 'nvib' in list(pops['CO'][1]['X']['vib'].keys()): raise AssertionError( 'Vib levels should not be defined anymore after eq_spectrum calculation!' ) # Any of these is True and something went wrong s = sf.non_eq_spectrum(2000, 2000) s2 = sf.non_eq_spectrum(300, 300) #printm(all(s2.get_vib_levels(isotope=1) == s.get_vib_levels(isotope=1))) assert not (s2.get_vib_levels() is s.get_vib_levels()) assert not (s2.get_rovib_levels() == s.get_rovib_levels()).all().all() assert not (s2.get_rovib_levels() is s.get_rovib_levels()) return True # if no AssertionError
def test_load_lines_pops(plot=False, verbose=True, warnings=True, *args, **kwargs): """Test load / save Full version: save lines, populations (hundreds of MB for CO2, much less for CO), compare everything """ temp_file_name = "_test_database_co_tempfile.spec" assert not exists(temp_file_name) try: sf = SpectrumFactory( wavelength_min=4500, wavelength_max=4800, mole_fraction=400e-6, path_length=0.1, # cm isotope=[1, 2], db_use_cached=True, cutoff=1e-20, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.load_databank("HITRAN-CO-TEST") s1 = sf.non_eq_spectrum(Tvib=300, Trot=300) s1.apply_slit(2, verbose=False) s1.update() s2 = load_spec( s1.store( temp_file_name, discard=[], # we're actually saving lines and # populations here! expect hundreds # of megabytes for big molecules # :line CO2 ... here CO is fine # (by default lines and populations # are discarded) compress=True # only removes some spectral # quantities, cant change population # or lines size ), binary=True, # uncompress ) s2.update() assert s1.compare_with(s2, spectra_only=False, plot=False) # Test with json-tricks directly # Does not work yet # from json_tricks import dumps, loads # s2b = loads(dumps(s1)) # assert s1.compare_with(s2b, spectra_only=False, plot=False) finally: # cleaning if exists(temp_file_name): os.remove(temp_file_name) return True
def test_medium(plot=False, verbose=True, debug=False, warnings=True, *args, **kwargs): ''' Test effect of propagating medium ''' from radis.lbl.factory import SpectrumFactory if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() T = 300 try: setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there pl = SpectrumFactory( wavenum_min=2171.5, wavenum_max=2174, mole_fraction=0.01, medium='vacuum', isotope='1,2') pl.warnings['MissingSelfBroadeningWarning'] = 'ignore' pl.load_databank('HITRAN-CO-TEST') s = pl.non_eq_spectrum(Tvib=T, Trot=T) # , Ttrans=300) pla = SpectrumFactory( wavenum_min=2171.5, wavenum_max=2174, mole_fraction=0.01, medium='air', isotope='1,2') pla.load_databank('HITRAN-CO-TEST') s_air = pla.non_eq_spectrum(Tvib=T, Trot=T) # , Ttrans=300) if plot: plt.figure(fig_prefix+'Propagating medium conversions') s.plot(nfig='same', lw=3, medium='vacuum', label='vacuum') s.plot(nfig='same', medium='air', label='air') assert np.allclose(s.get_wavenumber(), s_air.get_wavenumber()) assert np.allclose(s.get_wavelength(medium='vacuum'), s_air.get_wavelength(medium='vacuum')) assert np.allclose(s.get_wavelength(medium='air'), s_air.get_wavelength(medium='air')) assert all(s.get_wavelength(medium='vacuum') > s.get_wavelength(medium='air')) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_eq_vs_noneq_isotope(verbose=True, plot=False, warnings=True, *args, **kwargs): ''' Test same spectrum for 2 different calculation codes (equilibrium, non-equilibrium) in the presence of isotopes Notes ----- On the old NeQ package the test used [HITEMP-2010]_ Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which is not valid for these temperatures but can be more conveniently downloaded automatically and thus executed everytime with [Travis]_ ''' try: Tgas = 1500 sf = SpectrumFactory(wavelength_min=4250, wavelength_max=4350, mole_fraction=1, path_length=1, cutoff=1e-25, molecule='CO2', isotope='1,2', db_use_cached=True, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.warnings['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') s_nq = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas, name='Non-eq') s_eq = sf.eq_spectrum(Tgas=Tgas, name='Eq') rtol = 5e-3 # 2nd isotope calculated with placeholder energies match_eq_vs_non_eq = s_eq.compare_with(s_nq, spectra_only='abscoeff', rtol=rtol, plot=plot) match_eq_vs_non_eq *= s_eq.compare_with(s_nq, spectra_only='radiance_noslit', rtol=rtol, plot=plot) if verbose: printm('Tested eq vs non-eq (<{0:.1f}% error) with isotopes: {1}'. format(rtol * 100, bool(match_eq_vs_non_eq))) assert match_eq_vs_non_eq except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def _distribute_noneq_spectrum(args): ''' Clone the Factory and calculate non_eq_spectrum over several clones ''' cast_factory, Tvib, Trot, mole_fraction, path_length = args # ... (dev) must match p.map(_distribute_noneq_spectrum...) order factory = deepcopy(cast_factory) # Update id factory._id = uuid1() return SpectrumFactory.non_eq_spectrum(factory, Tvib, Trot, mole_fraction=mole_fraction, path_length=path_length)
def test_eq_vs_noneq_isotope(verbose=True, plot=False, warnings=True, *args, **kwargs): """Test same spectrum for 2 different calculation codes (equilibrium, non-equilibrium) in the presence of isotopes Notes ----- On the old NeQ package the test used [HITEMP-2010]_ Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which is not valid for these temperatures but can be more conveniently downloaded automatically and thus executed everytime with `Travis CI <https://travis-ci.com/radis/radis>`_ """ Tgas = 1500 sf = SpectrumFactory( wavelength_min=4250, wavelength_max=4350, mole_fraction=1, path_length=1, cutoff=1e-25, molecule="CO2", isotope="1,2", db_use_cached=True, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.warnings["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') s_nq = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas, name="Non-eq") s_eq = sf.eq_spectrum(Tgas=Tgas, name="Eq") rtol = 5e-3 # 2nd isotope calculated with placeholder energies match_eq_vs_non_eq = s_eq.compare_with(s_nq, spectra_only="abscoeff", rtol=rtol, plot=plot) match_eq_vs_non_eq *= s_eq.compare_with(s_nq, spectra_only="radiance_noslit", rtol=rtol, plot=plot) if verbose: printm( "Tested eq vs non-eq (<{0:.1f}% error) with isotopes: {1}".format( rtol * 100, bool(match_eq_vs_non_eq))) assert match_eq_vs_non_eq
def _test(verbose=True, plot=False, *args, **kwargs): """ Generate scalable LevelList at 1500K. Rescale at 2000K and compare with spectrum directly calculated at 2000K """ from radis.lbl import SpectrumFactory iso = 1 sf = SpectrumFactory( wavelength_min=4170, wavelength_max=4200, mole_fraction=1, path_length=0.05, cutoff=1e-25, # isotope=[1,2], isotope=iso, db_use_cached=True, wstep=0.01, broadening_max_width=10, medium="air", verbose=verbose, ) sf.load_databank("CDSD") parfunc = sf.parsum_calc["CO2"][iso]["X"] # %% Fill levels for all bands Tref = 1500 s_bands = sf.non_eq_bands(Tvib=Tref, Trot=Tref) lvlist = LevelsList(parfunc, s_bands, sf.params.levelsfmt) # %% Test Tvib = 2000 s_resc = lvlist.non_eq_spectrum(Tvib=Tvib, Trot=Tref) s0 = sf.non_eq_spectrum(Tvib, Tref) return s0.compare_with(s_resc, spectra_only=True, plot=plot)
def test_optically_thick_limit_1iso(verbose=True, plot=True, *args, **kwargs): """ Test that we find Planck in the optically thick limit In particular, this test will fail if : - linestrength are not properly calculated - at noneq, linestrength and emission integrals are mixed up The test should be run for 1 and several isotopes, because different calculations paths are used internally, and this can lead to different errors. Also, this test is used to run with DEBUG_MODE = True, which will check that isotopes and molecule ids are what we expect in all the groupby() loops that make the production code very fast. Notes ----- switched from large band calculation with [HITRAN-2016]_ to a calculation with the embedded [HITEMP-2010]_ fragment (shorter range, but no need to download files) """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() # Force DEBUG_MODE DEBUG_MODE = radis.DEBUG_MODE radis.DEBUG_MODE = True try: wavenum_min = 2284.2 wavenum_max = 2284.6 P = 0.017 # bar wstep = 0.001 # cm-1 Tgas = 1200 # %% Generate some CO2 emission spectra # -------------- sf = SpectrumFactory( wavenum_min=wavenum_min, wavenum_max=wavenum_max, molecule="CO2", mole_fraction=1, path_length=0.05, cutoff=1e-25, broadening_max_width=1, export_populations=False, #'vib', export_lines=False, isotope=1, use_cached=True, wstep=wstep, pseudo_continuum_threshold=0, pressure=P, verbose=False, ) # sf.fetch_databank('astroquery') sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.load_databank("HITEMP-CO2-TEST") pb = ProgressBar(3, active=verbose) s_eq = sf.eq_spectrum(Tgas=Tgas, mole_fraction=1, name="Equilibrium") pb.update(1) s_2T = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas, mole_fraction=1, name="Noneq (2T)") pb.update(2) s_4T = sf.non_eq_spectrum(Tvib=(Tgas, Tgas, Tgas), Trot=Tgas, mole_fraction=1, name="Noneq (4T)") pb.update(3) s_plck = sPlanck( wavelength_min=2000, # =wavelength_min, wavelength_max= 5000, # =wavelength_max - wstep, # there is a border effect on last point T=Tgas, ) pb.done() # %% Post process: # MAke optically thick, and compare with Planck for s in [s_eq, s_2T, s_4T]: s.rescale_path_length(1e6) if plot: nfig = "test_opt_thick_limit_1iso {0}".format(s.name) plt.figure(nfig).clear() s.plot(wunit="nm", nfig=nfig, lw=4) s_plck.plot(wunit="nm", nfig=nfig, Iunit="mW/cm2/sr/nm", lw=2) plt.legend() if verbose: printm( "Residual between opt. thick CO2 spectrum ({0}) and Planck: {1:.2g}" .format( s.name, get_residual(s, s_plck, "radiance_noslit", ignore_nan=True), )) # assert get_residual(s, s_plck, 'radiance_noslit', ignore_nan=True) < 1e-3 assert get_residual(s, s_plck, "radiance_noslit", ignore_nan=True) < 0.9e-4 if verbose: printm("Tested optically thick limit is Planck (1 isotope): OK") finally: # Reset DEBUG_MODE radis.DEBUG_MODE = DEBUG_MODE
def test_populations(plot=True, verbose=True, warnings=True, *args, **kwargs): """ See wavelength difference in air and vacuum """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: if verbose: printm(">>> _test_media_line_shift") setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there sf = SpectrumFactory( wavelength_min=4500, wavelength_max=4600, wstep=0.001, parallel=False, bplot=False, cutoff=1e-30, path_length=0.1, mole_fraction=400e-6, isotope=[1], db_use_cached=True, medium="vacuum", broadening_max_width=10, export_populations="rovib", verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.load_databank("HITRAN-CO-TEST") # Populations cannot be calculated at equilibrium (no access to energy levels) s = sf.eq_spectrum(300) with pytest.raises(ValueError): # .. we expect this error here! pops = s.get_populations("CO", isotope=1, electronic_state="X") # Calculate populations using the non-equilibrium module: s = sf.non_eq_spectrum(300, 300) pops = s.get_populations("CO", isotope=1, electronic_state="X") if not "n" in list(pops["rovib"].keys()): raise ValueError("Populations not calculated") if plot: s.plot_populations() # Compare with factory # Plot populations: with pytest.raises(ValueError): sf.plot_populations() # no isotope given: error expected if plot: sf.plot_populations("rovib", isotope=1) plt.close() # no need to keep it open, we just tested the function # Test calculated quantities are there assert hasattr(sf.df1, "Qref") assert hasattr(sf.df1, "Qvib") assert hasattr(sf.df1, "Qrotu") assert hasattr(sf.df1, "Qrotl") # Test hardcoded populations assert np.isclose(pops["rovib"]["n"].iloc[0], 0.0091853446840826653) assert np.isclose(pops["rovib"]["n"].iloc[1], 0.027052543988733215) assert np.isclose(pops["rovib"]["n"].iloc[2], 0.04345502115897712) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_plot_all_CO2_bandheads(verbose=True, plot=False, *args, **kwargs): ''' In this test we use the :meth:`~radis.lbl.bands.BandFactory.non_eq_bands` method to calculate separately all vibrational bands of CO2, and compare them with the final Spectrum. ''' # Note: only with iso1 at the moment if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() verbose = True Tgas = 1000 sf = SpectrumFactory(wavelength_min=4160, wavelength_max=4220, mole_fraction=1, path_length=0.3, cutoff=1e-23, molecule='CO2', isotope=1, db_use_cached=True, lvl_use_cached=True, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.warnings['HighTemperatureWarning'] = 'ignore' sf.fetch_databank() s_tot = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas) s_bands = sf.non_eq_bands(Tvib=Tgas, Trot=Tgas) if verbose: printm('{0} bands in spectrum'.format(len(s_bands))) assert len(s_bands) == 6 # Ensure that recombining gives the same s_merged = MergeSlabs(*list(s_bands.values())) assert s_tot.compare_with(s_merged, 'radiance_noslit', plot=False) if verbose: printm('Recombining bands give the same Spectrum') # %% if plot: s_tot.apply_slit(1, 'nm') s_tot.name = 'Full spectrum' s_tot.plot(wunit='nm', lw=3) for band, s in s_bands.items(): s.plot(wunit='nm', nfig='same') plt.legend(loc='upper left') plt.ylim(ymax=0.25) # %% Compare with equilibrium bands now s_bands_eq = sf.eq_bands(Tgas) s_merged_eq = MergeSlabs(*list(s_bands_eq.values())) assert get_residual(s_tot, s_merged_eq, 'radiance_noslit') < 1e-5 return True
def test_populations_CO2_hamiltonian( plot=True, verbose=True, warnings=True, *args, **kwargs ): """Calculate nonequilibrium modes with the CO2 Hamiltonian ..warning:: as we only use a reduced set of the CO2 effective Hamiltonian (< 3000 cm-1), many levels of the Line Database will not appear in the Levels Database. We will need to either filter the Line Database beforehand, or run it a first time and remove all levels not found. This database is obviously not to be used in a Production code! """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() if verbose: printm(">>> _test_media_line_shift") setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there sf = SpectrumFactory( wavenum_min=2283.7, wavenum_max=2285.1, wstep=0.001, cutoff=1e-30, path_length=0.1, mole_fraction=400e-6, isotope=[1], medium="vacuum", broadening_max_width=10, export_populations="rovib", verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.load_databank("HITEMP-CO2-HAMIL-TEST") # First run a calculation at equilibrium s = sf.eq_spectrum(300) s.name = "equilibrium" # Now generate vibrational energies for a 2-T model # ... Note that this is arbitrary. Lookup Pannier & Dubuet 2020 for more. levels = sf.parsum_calc["CO2"][1]["X"].df levels["Evib"] = levels.Evib1 + levels.Evib2 + levels.Evib3 # Calculate populations using the non-equilibrium module: # This will crash the first time (see error in docstrings of the function). with pytest.raises(AssertionError): sf.non_eq_spectrum(300, 300) sf.df0.dropna(inplace=True) # Retry: s_noneq = sf.non_eq_spectrum(300, 300) s_noneq.name = "nonequilibrium" # Tests: # s.compare_with(s_noneq, plot=plot) assert s_noneq.get_power() > 0 # TODO: implement actual Assertions (right now we're just checking that # functions are properly parsed) # TODO. Fix below (and move in dedicated test): # s.line_survey() return True
def test_direct_overpopulation_vs_recombined_bands(verbose=True, plot=False, warnings=True, rtol=0.05, *args, **kwargs): """ Compare a non-equilibrium spectrum calculated directly with overpopulations, or by recombining pre-calculated vibrational bands. The later allows for almost instantaneous changes of the overpopulation factors, (mostly useful in fitting algorithms), but is only valid for optically thin emission spectra Expected output: when x_CO2 = 1e-3, radiance in both cases match when x_CO2 = 1, they dont """ # Notes # ----- # # On the old NeQ package the test used [HITEMP-2010]_ # # Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which # is not valid for these temperatures but can be more conveniently # downloaded automatically and thus executed everytime with [Travis]_ # # Note: only with iso1 at the moment if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: # Generate factory iso = 1 sf = SpectrumFactory( wavelength_min=4220, wavelength_max=4280, mole_fraction=1e-3, path_length=10, cutoff=1e-25, molecule="CO2", isotope=iso, db_use_cached=True, wstep=0.01, broadening_max_width=5, medium="air", verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.load_databank("CDSD-HITEMP-PCN") # sf.fetch_databank() # uses HITRAN: not really valid at this temperature, but runs on all machines without install # Generate bands to recombine parfunc = sf.parsum_calc["CO2"][iso]["X"] Tref = 1500 # , return_lines=False) s_bands = sf.non_eq_bands(Tvib=Tref, Trot=Tref) lvlist = LevelsList(parfunc, s_bands, sf.params.levelsfmt) # Compare ab initio and recombined from bands at M = 1e-3 s_recombined = lvlist.non_eq_spectrum(Tvib=Tref, Trot=Tref, overpopulation={"(4,1,3)": 3}) sref = sf.non_eq_spectrum(Tvib=Tref, Trot=Tref, overpopulation={"(4,1,3)": 1}) if verbose: printm( "Testing x_CO2 = 1e-3: ab initio ~ recombined bands (<{0:.1f}%):\t" .format(rtol * 100)) if plot: plot_diff( sref, s_recombined, var="radiance_noslit", label1="ab initio", label2="recombined bands", title="x_CO2 = 1e-3", ) assert np.allclose(s_recombined.get_radiance_noslit(), sref.get_radiance_noslit(), rtol=rtol) # Rescale and try again for x_CO2 = 1 s_recombined.rescale_mole_fraction(1) sref.rescale_mole_fraction(1) if plot: plot_diff( sref, s_recombined, var="radiance_noslit", label1="ab initio", label2="recombined bands", title="x_CO2 = 1", ) if verbose: printm( "Testing x_CO2 = 1: ab initio ~ recombined bands (<{0:.1f}%):\t{1}" .format( rtol * 100, np.allclose( s_recombined.get_radiance_noslit(), sref.get_radiance_noslit(), rtol=rtol, ), )) with pytest.raises(AssertionError): assert np.allclose( s_recombined.get_radiance_noslit(), sref.get_radiance_noslit(), rtol=rtol, ) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_plot_all_CO2_bandheads(verbose=True, plot=False, *args, **kwargs): """In this test we use the :meth:`~radis.lbl.bands.BandFactory.non_eq_bands` method to calculate separately all vibrational bands of CO2, and compare them with the final Spectrum. """ # Note: only with iso1 at the moment if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() Tgas = 1000 sf = SpectrumFactory( wavelength_min=4160, wavelength_max=4220, mole_fraction=1, path_length=0.3, cutoff=1e-23, molecule="CO2", isotope=1, optimization=None, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.warnings["HighTemperatureWarning"] = "ignore" sf.fetch_databank("hitran") s_tot = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas) s_bands = sf.non_eq_bands(Tvib=Tgas, Trot=Tgas) if verbose: printm("{0} bands in spectrum".format(len(s_bands))) assert len(s_bands) == 6 # Ensure that recombining gives the same s_merged = MergeSlabs(*list(s_bands.values())) assert s_tot.compare_with(s_merged, "radiance_noslit", plot=False) if verbose: printm("Recombining bands give the same Spectrum") # %% if plot: s_tot.apply_slit(1, "nm") s_tot.name = "Full spectrum" s_tot.plot(wunit="nm", lw=3) for band, s in s_bands.items(): s.plot(wunit="nm", nfig="same") plt.legend(loc="upper left") plt.ylim(ymax=0.25) # %% Compare with equilibrium bands now s_bands_eq = sf.eq_bands(Tgas) s_merged_eq = MergeSlabs(*list(s_bands_eq.values())) assert get_residual(s_tot, s_merged_eq, "radiance_noslit") < 1.5e-5 return True
def test_all_calc_methods_CO2pcN(verbose=True, plot=False, warnings=True, rtol=1e-3, *args, **kwargs): """Test same spectrum for 3 different calculation variants (equilibrium, non-equilibrium, per band and recombine Uses CO2 Levels database where the energy partitioning is done as follow: 2 nonequilibrium modes Evib is the minimum of a "p,c,N" group Erot = E - Evib This corresponds to the levelsfmt = 'cdsd-pcN' in :data:`~radis.lbl.loader.KNOWN_LVLFORMAT` """ from radis.misc.config import getDatabankEntries from radis.test.utils import ( define_Evib_as_min_of_polyad, discard_lines_with_na_levels, setup_test_line_databases, ) if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() #%% Tgas = 500 iso = 1 sf = SpectrumFactory( wavenum_min=2284, wavenum_max=2285, broadening_max_width=5, # TODO @EP: crashes with 0.3? mole_fraction=1, path_length=0.025, cutoff=1e-25, molecule="CO2", isotope=iso, db_use_cached=True, lvl_use_cached=True, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.warnings["HighTemperatureWarning"] = "ignore" # Preparation: setup_test_line_databases() # Generate a Levels database with p,c,N energy partitioning # ... copy "HITEMP-CO2-HAMIL-TEST" info database_kwargs = getDatabankEntries("HITEMP-CO2-HAMIL-TEST") # ... adapt it to 'cdsd-pcN' mode del database_kwargs["info"] database_kwargs["levelsfmt"] = "cdsd-pcN" # ... load the new database sf.load_databank(**database_kwargs) # Now, define Evib: Q_calc = sf.parsum_calc["CO2"][1]["X"] Q_calc.df = define_Evib_as_min_of_polyad(Q_calc.df, keys=["p", "c", "N"]) # With this Evib definition, clean the Lines database from where Evib is not defined # (because Levels does not exist in the reduced, test Level Database) discard_lines_with_na_levels(sf) # %%--------------------- # Ready, let's start the tests: s_bands = sf.non_eq_bands(Tvib=Tgas, Trot=Tgas) lvl = LevelsList(sf.parsum_calc["CO2"][iso]["X"], s_bands, sf.params.levelsfmt) s_bd = lvl.non_eq_spectrum(Tvib=Tgas, Trot=Tgas) s_nq = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas) s_eq = sf.eq_spectrum(Tgas=Tgas) # if plot: fig = plt.figure(fig_prefix + "Compare all calc methods") s_bd.plot(nfig=fig.number, color="b", lw=5, label="from bands code") s_nq.plot(nfig=fig.number, lw=3, label="non eq code") s_eq.plot(nfig=fig.number, lw=2, color="r", label="equilibrum code") plt.legend() assert np.isclose(s_bd.get_integral("abscoeff"), s_nq.get_integral("abscoeff"), rtol=rtol) assert np.isclose(s_bd.get_integral("abscoeff"), s_eq.get_integral("abscoeff"), rtol=rtol) assert np.isclose(s_nq.get_integral("abscoeff"), s_eq.get_integral("abscoeff"), rtol=rtol) # TODO @EP: assertion fail in emission. This is due to the slight shift # in intensity also observed in the Planck test (test_base.py::test_optically_thick_limit_1iso()). # assert np.isclose(s_bd.get_power(), s_nq.get_power(), rtol=rtol) # assert np.isclose(s_bd.get_power(), s_eq.get_power(), rtol=rtol) # assert np.isclose(s_nq.get_power(), s_eq.get_power(), rtol=rtol) return True
def test_3Tvib_vs_1Tvib(verbose=True, plot=False, warnings=True, *args, **kwargs): if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() try: T = 1500 iso = [1] sf = SpectrumFactory( wavenum_min=2380, wavenum_max=2400, pressure=20 * 1e-3, db_use_cached=True, cutoff=1e-25, isotope=iso, # ,2', path_length=10, mole_fraction=0.1, broadening_max_width=1, medium="vacuum", verbose=verbose, ) sf.warnings.update({ "MissingSelfBroadeningWarning": "ignore", "VoigtBroadeningWarning": "ignore", }) sf.load_databank("HITRAN-CO2-TEST") # Compare energies for I in iso: energies = sf.get_energy_levels("CO2", I, "X") assert (energies.Evib == energies.Evib1 + energies.Evib2 + energies.Evib3).all() if verbose: printm("Tested Evib == Evib1+Evib2+Evib3: OK") s3 = sf.non_eq_spectrum((T, T, T), T) s1 = sf.non_eq_spectrum(T, T) s3.name = "Tvib=({0},{0},{0}) K, Trot={0} K".format(T) s1.name = "Tvib={0} K, Trot={0} K".format(T) if plot: s1.plot( "transmittance_noslit", wunit="cm-1", color="k", lw=3, label="Tvib = {0}K".format(T), ) s3.plot( "transmittance_noslit", wunit="cm-1", color="r", lw=3, nfig="same", label="Tvib1 = Tvib2 = Tvib3 = {0}K".format(T), ) assert s1.compare_with(s3, spectra_only=True, verbose=verbose, plot=plot) if verbose: printm( "Tested Spectra 3Tvib(T1=T2=T3=T) and 1Tvib(T) are the same: OK" ) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_all_calc_methods( verbose=True, plot=False, warnings=True, rtol=1e-3, *args, **kwargs ): """ Test same spectrum for 3 different calculation variants (equilibrium, non-equilibrium, per band and recombine """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() try: Tgas = 1500 iso = 1 sf = SpectrumFactory( wavelength_min=4170, wavelength_max=4175, mole_fraction=1, path_length=0.025, cutoff=1e-25, molecule="CO2", isotope=iso, db_use_cached=True, lvl_use_cached=True, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.warnings["HighTemperatureWarning"] = "ignore" # sf.fetch_databank() # uses HITRAN: not really valid at this temperature, but runs on all machines without install sf.load_databank("CDSD-HITEMP-PC") s_bands = sf.non_eq_bands(Tvib=Tgas, Trot=Tgas) lvl = LevelsList(sf.parsum_calc["CO2"][iso]["X"], s_bands, sf.params.levelsfmt) s_bd = lvl.non_eq_spectrum(Tvib=Tgas, Trot=Tgas) s_nq = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas) s_eq = sf.eq_spectrum(Tgas=Tgas) # if plot: fig = plt.figure(fig_prefix + "Compare all calc methods") s_bd.plot(nfig=fig.number, color="b", lw=5, label="from bands code") s_nq.plot(nfig=fig.number, lw=3, label="non eq code") s_eq.plot(nfig=fig.number, lw=2, color="r", label="equilibrum code") plt.legend() assert np.isclose(s_bd.get_power(), s_nq.get_power(), rtol=rtol) assert np.isclose(s_bd.get_power(), s_eq.get_power(), rtol=rtol) if verbose: printm( "Eq == non-eq:\t", np.isclose(s_eq.get_power(), s_nq.get_power(), rtol=rtol), ) printm( "Bands == Non-eq:\t", np.isclose(s_bd.get_power(), s_nq.get_power(), rtol=rtol), ) if verbose: printm("Test all methods comparison: OK") return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
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, parallel=False, bplot=False, cutoff=1e-30, path_length=10, mole_fraction=400e-6, isotope=[1], db_use_cached=True, broadening_max_width=10, verbose=verbose, ) sf.warnings.update( { "MissingSelfBroadeningWarning": "ignore", "OutOfRangeLinesWarning": "ignore", "HighTemperatureWarning": "ignore", } ) sf.load_databank("HITRAN-CO-TEST") 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
def test_retrieve_from_database(plot=True, verbose=True, warnings=True, *args, **kwargs): """Test autoretrieve from a database: first generate an empty :py:class:`~radis.tools.database.SpecDatabase` associated to a :py:class`~radis.lbl.factory.SpectrumFactory`, then calculate a first spectrum, then calculate it again and make sure it is retrieved from the database """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() temp_database_name = "temp_spec_database" try: if verbose: printm(">>> test_retrieve_from_database") assert not exists(temp_database_name) setup_test_line_databases( ) # add HITEMP-CO2-TEST in ~/.radis if not there sf = SpectrumFactory( 2284.2, 2284.6, wstep=0.001, # cm-1 pressure=20 * 1e-3, # bar cutoff=0, path_length=0.1, mole_fraction=400e-6, molecule="CO2", isotope=[1], db_use_cached=True, medium="vacuum", broadening_max_width=10, export_populations="rovib", verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.init_databank( "HITEMP-CO2-TEST" ) # unlike load_databank, will automatically be built when needed db = sf.init_database(temp_database_name, autoretrieve=True) assert len(db) == 0 # Calculate a first spectrum s1 = sf.non_eq_spectrum(2000, 1000) assert len(db) == 1 # Note that the Spectrum in database is not s1 because populations # are not stored by default # hack: now change the `autoretrieve` status to `force` to make sure # the spectrum is retrieved. Else, an error will be raised sf.autoretrievedatabase = "force" # Calculate spectrum under the same conditions s2 = sf.non_eq_spectrum(2000, 1000) # Note that s1 == s2 won't work because populations are not stored # by default in the database assert s1.compare_with(s2, spectra_only=True) return True finally: rmtree(temp_database_name)