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
def test_broadening_methods_different_wstep(verbose=True, plot=False, *args, **kwargs): ''' Test direct Voigt broadening vs convolution of Gaussian x Lorentzian for different spectral grid resolution ''' if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # Conditions T = 3000 p = 1 wmin = 2150 # cm-1 wmax = 2152 # cm-1 broadening_max_width = 10 # cm-1 for i, wstep in enumerate([0.01, 0.1, 0.5]): # %% 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=False, warnings={'MissingSelfBroadeningWarning':'ignore', 'NegativeEnergiesWarning':'ignore', 'HighTemperatureWarning':'ignore', 'GaussianBroadeningWarning':'ignore'} ) # 0.2) sf.load_databank('HITRAN-CO-TEST') # s = pl.non_eq_spectrum(Tvib=T, Trot=T, Ttrans=T) sf._broadening_method = 'voigt' s_voigt = sf.eq_spectrum(Tgas=T, name='direct') sf._broadening_method = 'convolve' s_convolve = sf.eq_spectrum(Tgas=T, name='convolve') res = get_residual(s_voigt, s_convolve, 'abscoeff') if verbose: print('Residual:', res) # plot the last one if plot: plot_diff(s_voigt, s_convolve, 'abscoeff', nfig='test_voigt_broadening_methods'+str(i), title='P {0} bar, T {1} K, wstep {2} cm-1'.format(p, T, wstep)) assert res < 2e-4
def test_visualTestBaseline(plot=True, *args, **kwargs): s = load_spec(getTestFile("CO_Tgas1500K_mole_fraction0.01.spec"), binary=True) s.update('radiance_noslit', verbose=False) s.apply_slit(0.1) s = Radiance_noslit(s) assert s.units['radiance'] == 'mW/cm2/sr/nm' s2 = sub_baseline(s, 2e-4, -2e-4, name='sub_arb_baseline') if plot: plot_diff(s, s2)
def test_offset(plot=True): s = load_spec(getTestFile("CO_Tgas1500K_mole_fraction0.01.spec"), binary=True) s.update('radiance_noslit', verbose=False) s.apply_slit(0.1) s2 = offset(s, 10, 'nm', name='offset_10nm') if plot: plot_diff(s, s2) assert np.allclose(s2.get_wavelength(which='convoluted'), s.get_wavelength(which='convoluted') + 10) assert np.allclose(s2.get_wavelength(which='non_convoluted'), s.get_wavelength(which='non_convoluted') + 10) # Test inplace version s.offset(10, 'nm') assert np.allclose(s2.get_wavelength(which='convoluted'), s.get_wavelength(which='convoluted'))
def test_broadening_methods_different_wstep(verbose=True, plot=False, *args, **kwargs): """ Test direct Voigt broadening vs convolution of Gaussian x Lorentzian for different spectral grid resolution """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # Conditions T = 3000 p = 1 wmin = 2150 # cm-1 wmax = 2152 # cm-1 broadening_max_width = 10 # cm-1 for i, wstep in enumerate([0.01, 0.1, 0.5]): # %% 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", optimization=None, verbose=False, warnings={ "MissingSelfBroadeningWarning": "ignore", "NegativeEnergiesWarning": "ignore", "HighTemperatureWarning": "ignore", "GaussianBroadeningWarning": "ignore", "AccuracyError": "ignore", "AccuracyWarning": "ignore", }, ) # 0.2) sf.load_databank("HITRAN-CO-TEST") # s = pl.non_eq_spectrum(Tvib=T, Trot=T, Ttrans=T) sf.params.broadening_method = "voigt" s_voigt = sf.eq_spectrum(Tgas=T, name="direct") sf.params.broadening_method = "convolve" s_convolve = sf.eq_spectrum(Tgas=T, name="convolve") res = get_residual(s_voigt, s_convolve, "abscoeff") if verbose: print("Residual:", res) # plot the last one if plot: plot_diff( s_voigt, s_convolve, "abscoeff", nfig="test_voigt_broadening_methods" + str(i), title="P {0} bar, T {1} K, wstep {2} cm-1".format(p, T, wstep), ) assert res < 2e-4
def test_broadening_methods_different_conditions(verbose=True, plot=False, *args, **kwargs): """ Test direct Voigt broadening vs convolution of Gaussian x Lorentzian for different spectral grid resolution Notes ----- Reference broadening calculated manually with the HWHM formula of `HITRAN.org <https://hitran.org/docs/definitions-and-units/>`_ """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # Conditions wstep = 0.005 wmin = 2150.4 # cm-1 wmax = 2151.4 # cm-1 broadening_max_width = 2 # cm-1 for (T, p, fwhm_lorentz, fwhm_gauss) in [ # K, bar, expected FWHM for Lotentz, gauss (cm-1) (3000, 1, 0.02849411, 0.01594728), (300, 1, 0.16023415, 0.00504297), (3000, 0.01, 0.00028494, 0.01594728), ]: # %% 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=False, warnings={ "MissingSelfBroadeningWarning": "ignore", "NegativeEnergiesWarning": "ignore", "HighTemperatureWarning": "ignore", "OutOfRangeLinesWarning": "ignore", "GaussianBroadeningWarning": "ignore", "CollisionalBroadeningWarning": "ignore", }, ) sf.load_databank("HITRAN-CO-TEST") # Manually filter line database, keep one line only: sf.df0.drop(sf.df0[sf.df0.vu != 1].index, inplace=True) assert isclose(sf.df0.wav, 2150.856008) # Calculate spectra (different broadening methods) sf.params.broadening_method = "voigt" s_voigt = sf.eq_spectrum(Tgas=T, name="direct") # assert broadening FWHM are correct assert isclose(2 * float(sf.df1.hwhm_gauss), fwhm_gauss) assert isclose(2 * float(sf.df1.hwhm_lorentz), fwhm_lorentz) sf.params.broadening_method = "convolve" s_convolve = sf.eq_spectrum(Tgas=T, name="convolve") # assert broadening FWHM are correct assert isclose(2 * float(sf.df1.hwhm_gauss), fwhm_gauss) assert isclose(2 * float(sf.df1.hwhm_lorentz), fwhm_lorentz) res = get_residual(s_voigt, s_convolve, "abscoeff") if verbose: print( "{0} K, {1} bar: FWHM lorentz = {2:.3f} cm-1, FWHM gauss = {3:.3f} cm-1" .format(T, p, 2 * float(sf.df1.hwhm_lorentz), 2 * float(sf.df1.hwhm_gauss))) if plot: plot_diff( s_voigt, s_convolve, "abscoeff", title= r"T {0} K, p {1} bar: w$_\mathrm{{L}}$ {2:.3f}, w$_\mathrm{{G}}$ {3:.3f} cm$^{{-1}}$" .format(T, p, 2 * float(sf.df1.hwhm_lorentz), float(sf.df1.hwhm_gauss)), ) # assert all broadening methods match assert res < 2e-4
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)
def test_broadening(rtol=1e-2, verbose=True, plot=False, *args, **kwargs): ''' Test broadening against HAPI and tabulated data We're looking at CO(0->1) line 'R1' at 2150.86 cm-1 ''' from radis.io.hapi import db_begin, fetch, tableList, absorptionCoefficient_Voigt if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # Conditions T = 3000 p = 0.0001 wstep = 0.001 wmin = 2150 # cm-1 wmax = 2152 # cm-1 broadening_max_width = 10 # cm-1 # %% HITRAN calculation # ----------- # Generate HAPI database locally db_begin(join(dirname(__file__), __file__.replace('.py', '_HAPIdata'))) if not 'CO' in tableList(): # only if data not downloaded already fetch('CO', 5, 1, wmin - broadening_max_width / 2, wmax + broadening_max_width / 2) # HAPI doesnt correct for side effects # Calculate with HAPI nu, coef = absorptionCoefficient_Voigt( SourceTables='CO', Environment={ 'T': T, # K 'p': p / 1.01325, # atm }, WavenumberStep=wstep, HITRAN_units=False) s_hapi = Spectrum.from_array(nu, coef, 'abscoeff', 'cm-1', 'cm_1', conditions={'Tgas': T}, name='HAPI') # %% 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], warnings={ 'MissingSelfBroadeningWarning': 'ignore', 'NegativeEnergiesWarning': 'ignore', 'HighTemperatureWarning': 'ignore', 'GaussianBroadeningWarning': 'ignore' }) # 0.2) sf.load_databank('HITRAN-CO-TEST') # s = pl.non_eq_spectrum(Tvib=T, Trot=T, Ttrans=T) s = sf.eq_spectrum(Tgas=T, name='RADIS') if plot: # plot broadening of line of largest linestrength sf.plot_broadening(i=sf.df1.S.idxmax()) # Plot and compare res = abs(get_residual_integral(s, s_hapi, 'abscoeff')) if plot: plot_diff(s, s_hapi, var='abscoeff', title='{0} bar, {1} K (residual {2:.2g}%)'.format( p, T, res * 100), show_points=False) plt.xlim((wmin, wmax)) if verbose: printm('residual:', res) assert res < rtol
SourceTables=molecule, Environment={ "T": T, "p": pressure_bar / 1.01315, }, # K # atm GammaL="gamma_self", WavenumberStep=dnu, HITRAN_units=False, ) return nu, coef t0 = time() nu, coef = calc_hapi() t0 = time() - t0 print(("Calculated with HAPI in {0:.2f}s".format(t0))) s_hapi = Spectrum.from_array(nu, coef, "abscoeff", waveunit="cm-1", unit="cm-1") s_hapi.name = "HAPI ({0:.1f}s)".format(t0) plot_diff(s_hapi, s, "abscoeff") print(("Calculated with RADIS in {0:.2f}s".format( s.conditions["calculation_time"]))) print(("Number of lines in RADIS:", len(sf.df0))) # plt.savefig('radis_vs_hapi_test_large_ch4.pdf')
def test_broadening_DLM_FT(verbose=True, plot=False, *args, **kwargs): """ Test use of DLM with and without Fourier Transform Ensures that results are the same, and compare calculation times. """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # Conditions T = 3000 p = 1 wstep = 0.002 wmin = 2000 # cm-1 wmax = 2300 # 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=verbose, chunksize="DLM", warnings={ "MissingSelfBroadeningWarning": "ignore", "NegativeEnergiesWarning": "ignore", "HighTemperatureWarning": "ignore", "GaussianBroadeningWarning": "ignore", }, ) # 0.2) sf.load_databank("HITRAN-CO-TEST") # DLM, real space if verbose: print("\nConvolve version \n") sf._broadening_method = "convolve" s_dlm = sf.eq_spectrum(Tgas=T) s_dlm.name = "DLM ({0:.2f}s)".format(s_dlm.conditions["calculation_time"]) # DLM , with Fourier if verbose: print("\nFFT version \n") sf.params.broadening_method = "fft" s_dlm_fft = sf.eq_spectrum(Tgas=T) s_dlm_fft.name = "DLM FFT ({0:.2f}s)".format( s_dlm_fft.conditions["calculation_time"]) # Compare res = get_residual(s_dlm, s_dlm_fft, "abscoeff") if verbose: print("Residual:", res) # plot if plot: plot_diff(s_dlm, s_dlm_fft, "abscoeff") plt.legend() assert res < 5e-6
def test_validation_vs_specair(rtol=1e-2, verbose=True, plot=False, *args, **kwargs): ''' Test RADIS output on CO IR bands against SPECAIR Test is only performed on integrals of absorption coefficient RADIS doesnt actually match Specair exactly, but this is due to line intensity differences (Specair has no rovibrational specific intensities) rather than differences in populations calculations, as evidenced by the partition functions comparison in the RADIS presentation article. ''' setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # %% Specair calculation # ----------- specair_300_300 = load_spec(getValidationCase( join('test_validation_vs_specair_noneqCO_data', 'specair_CO_IR_Tvib300_Trot300.spec')), binary=True) specair_300_2000 = load_spec(getValidationCase( join('test_validation_vs_specair_noneqCO_data', 'specair_CO_IR_Tvib300_Trot2000.spec')), binary=True) specair_2000_300 = load_spec(getValidationCase( join('test_validation_vs_specair_noneqCO_data', 'specair_CO_IR_Tvib2000_Trot300.spec')), binary=True) article_version = False # just for the article # %% Compare with RADIS # ---------- wstep = 0.002 pl = SpectrumFactory( wavelength_min=4400, wavelength_max=4900, mole_fraction=1, pressure=0.01, # bar path_length=1, # we dont care for abscoeff anyway parallel=False, cutoff=1e-30, wstep=wstep, isotope=1, # '1,2,3', medium='vacuum') # 0.2) pl.warnings['MissingSelfBroadeningWarning'] = 'ignore' if article_version: pl.load_databank('HITEMP-CO-DUNHAM') else: pl.load_databank('HITRAN-CO-TEST') # Available on all systems, convenient for fast testing, but you # will be missing some small lines for T ~ 2000 K . print( 'Using HITRAN: small lines will be missing at T ~ 2000K. Use HITEMP if you want them' ) s_300_300 = pl.eq_spectrum(300, name='RADIS') s_2000_300 = pl.non_eq_spectrum(Tvib=2000, Trot=300, Ttrans=300, name='RADIS') s_300_2000 = pl.non_eq_spectrum(Tvib=300, Trot=2000, Ttrans=2000, name='RADIS') # %% Test # Compare integrals b1 = np.isclose(specair_300_300.get_integral('abscoeff'), s_300_300.get_integral('abscoeff'), rtol=rtol) b1 *= np.isclose(specair_2000_300.get_integral('abscoeff'), s_2000_300.get_integral('abscoeff'), rtol=rtol) b1 *= np.isclose(specair_300_2000.get_integral('abscoeff'), s_300_2000.get_integral('abscoeff'), rtol=rtol) # Compare partition functions to hardcoded values b2 = np.isclose(s_2000_300.lines.Q, 139, atol=1) # Specair: 139 b2 *= np.isclose(s_300_2000.lines.Q, 727, atol=1) # Specair: 727 if verbose: printm( '>>> comparing RADIS vs SPECAIR on CO: integrals of abscoeff is are close' + ' to within {0:.1f}%: {1} ({2:.1f}%, {3:.1f}%, {4:.1f}%)'.format( rtol * 100, bool(b1), abs( specair_300_300.get_integral('abscoeff') / s_300_300.get_integral('abscoeff') - 1) * 100, abs( specair_2000_300.get_integral('abscoeff') / s_2000_300.get_integral('abscoeff') - 1) * 100, abs( specair_300_2000.get_integral('abscoeff') / s_300_2000.get_integral('abscoeff') - 1) * 100, )) printm('>>> comparing RADIS vs SPECAIR on CO: partition functions ' + 'are equal to round error: {0}'.format(bool(b2))) if plot: plot_diff( specair_300_300, s_300_300, title=r'T$_\mathregular{vib}$ 300 K, T$_\mathregular{rot}$ 300 K', diff_window=int( 0.02 // wstep ), # compensate for small shifts in both codes. we're comparing intensities here. lw_multiplier=1, #0.75, wunit='nm_vac', plot_medium=True, ) plt.xlim((4500, 4900)) if article_version: plt.savefig( 'out/test_validation_vs_specair_noneqCO_Tvib300_Trot300.png') plt.savefig( 'out/test_validation_vs_specair_noneqCO_Tvib300_Trot300.pdf') plot_diff( specair_2000_300, s_2000_300, title=r'T$_\mathregular{vib}$ 2000 K, T$_\mathregular{rot}$ 300 K', diff_window=int( 0.02 // wstep ), # compensate for small shifts in both codes. we're comparing intensities here. lw_multiplier=1, #0.75, wunit='nm_vac', plot_medium=True, ) plt.xlim((4500, 4900)) if article_version: plt.savefig( 'out/test_validation_vs_specair_noneqCO_Tvib2000_Trot300.png') plt.savefig( 'out/test_validation_vs_specair_noneqCO_Tvib2000_Trot300.pdf') plot_diff( specair_300_2000, s_300_2000, title=r'T$_\mathregular{vib}$ 300 K, T$_\mathregular{rot}$ 2000 K', diff_window=int( 0.02 // wstep ), # compensate for small shifts in both codes. we're comparing intensities here. lw_multiplier=1, #0.75, wunit='nm_vac', plot_medium=True, ) plt.xlim((4500, 4900)) if article_version: plt.savefig( 'out/test_validation_vs_specair_noneqCO_Tvib300_Trot2000.png') plt.savefig( 'out/test_validation_vs_specair_noneqCO_Tvib300_Trot2000.pdf') return bool(b1 * b2)
def calc_hapi(): nu, coef = absorptionCoefficient_Voigt( SourceTables=molecule, Environment={ 'T': T, # K 'p': pressure_bar / 1.01315, # atm }, GammaL='gamma_self', WavenumberStep=dnu, HITRAN_units=False) return nu, coef t0 = time() nu, coef = calc_hapi() t0 = time() - t0 print(('Calculated with HAPI in {0:.2f}s'.format(t0))) s_hapi = Spectrum.from_array(nu, coef, 'abscoeff', waveunit='cm-1', unit='cm-1') s_hapi.name = 'HAPI ({0:.1f}s)'.format(t0) plot_diff(s_hapi, s, 'abscoeff') print(('Calculated with RADIS in {0:.2f}s'.format( s.conditions['calculation_time']))) print(('Number of lines in RADIS:', len(sf.df0))) # plt.savefig('radis_vs_hapi_test_large_ch4.pdf')
def test_abscoeff_continuum(plot=False, verbose=2, warnings=True, threshold=0.1, *args, **kwargs): """ Test calculation with pseudo-continuum Assert results on abscoeff 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_abscoeff_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.eq_spectrum(Tgas=2000) 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 = threshold s2 = sf.eq_spectrum(Tgas=2000) s2.name = "Semi-continuum + {0} lines ({1:.1f}s)".format( s2.conditions["lines_calculated"], s2.conditions["calculation_time"]) assert s2.conditions["pseudo_continuum_threshold"] == threshold assert "abscoeff_continuum" in s2.get_vars() # Plot if plot: plot_diff( s1, s2, "radiance_noslit", Iunit="µW/cm2/sr/nm", nfig="test_abscoeff_continuum: diff", ) s2.plot( "abscoeff", label="Full spectrum", nfig="test_abscoeff_continuum: show continuum", force=True, ) s2.plot( "abscoeff_continuum", nfig="same", label="Pseudo-continuum".format( s2.conditions["lines_in_continuum"]), force=True, ) plt.legend() # Compare res = get_residual(s1, s2, "abscoeff") if verbose: printm("residual:", res) globals().update(locals()) assert res < 1.32e-6 except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_line_broadening(rtol=1e-3, verbose=True, plot=False, *args, **kwargs): r""" Plot absorption coefficient (cm-1) of CO at high temperature (2000 K) with RADIS, and compare with calculations from HAPI using the HITRAN database Notes ----- In this example no data is needed. Everything is downloaded from the HITRAN database directly using either the HAPI ``fetch`` function, or the RADIS :meth:`~neq.spec.factory.fetch_databank` method. """ from hapi import ( absorptionCoefficient_Voigt, db_begin, fetch, tableList, transmittanceSpectrum, ) setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # Conditions molecule = "CO2" mol_id = get_molecule_identifier(molecule) iso = 1 T = 1500 p = 0.1 L = 0.1 # M = 0.001 # mole fraction (dont know where to put that ) dnu = 0.0001 wmin = nm2cm(4372.69 + 0.2) # cm-1 wmax = nm2cm(4372.69 - 0.2) # cm-1 # broadening_max_width = 6 # cm-1 broadening_max_width = 0.5 # cm-1 # %% HITRAN calculation # ----------- # Generate HAPI database locally HAPIdb = join(dirname(__file__), __file__.replace(".py", "_HAPIdata")) def calc_hapi(): """ Calc spectrum under HAPI """ clean_after_run = not exists(HAPIdb) and False try: db_begin(HAPIdb) if not molecule in tableList( ): # only if data not downloaded already fetch( molecule, mol_id, iso, wmin - broadening_max_width / 2, wmax + broadening_max_width / 2, ) # HAPI doesnt correct for side effects # Calculate with HAPI nu, coef = absorptionCoefficient_Voigt( SourceTables="CO2", Environment={ "T": T, "p": p / 1.01325, }, # K # atm WavenumberStep=dnu, HITRAN_units=False, GammaL="gamma_self", ) nu, trans = transmittanceSpectrum( nu, coef, Environment={ "l": L, }, ) # cm s_hapi = Spectrum.from_array( nu, trans, "transmittance_noslit", "cm-1", "1", conditions={"Tgas": T}, name="HAPI", ) except: raise finally: if clean_after_run: shutil.rmtree(HAPIdb) return s_hapi s_hapi = calc_hapi() def calc_radis(): # %% Calculate with RADIS # ---------- pl = SpectrumFactory( wavenum_min=wmin, wavenum_max=wmax, mole_fraction=1, path_length=L, wstep=dnu, molecule=molecule, pressure=p, broadening_max_width=broadening_max_width, cutoff=1e-23, isotope=iso, ) pl.warnings["MissingSelfBroadeningWarning"] = "ignore" pl.warnings["HighTemperatureWarning"] = "ignore" pl.fetch_databank( source="hitran", load_energies=False, db_use_cached=True, ) s = pl.eq_spectrum(Tgas=T) # , Ttrans=300) s.name = "RADIS" if plot: pl.plot_broadening() return s s = calc_radis() # %% Compare # also shrinks HAPI range to the valid one s_hapi.resample(s.get_wavenumber(), unit="cm-1", energy_threshold=0.1) save = False # just used in the article if plot or save: from radis import plot_diff # title = '{0} bar, {1} K, {2} cm'.format(p, T, L) if save else None fig, [ax0, ax1] = plot_diff(s, s_hapi, var="transmittance_noslit", method="ratio", show=plot) ax0.annotate( r"[P64](00$^\mathregular{0}$0)$\rightarrow $(00$^\mathregular{0}$1)", (2286.945, 0.76), (2286.94, 0.8), arrowprops=dict(arrowstyle="->", facecolor="black"), ) ax0.annotate( r"[P53](01$^\mathregular{1}$0)$\rightarrow $(01$^\mathregular{1}$1)", (2286.9, 0.78), (2286.9, 0.82), arrowprops=dict(arrowstyle="->", facecolor="black"), horizontalalignment="right", ) ax1.set_ylim(0.95, 1.05) if save: fig.savefig("out/test_RADIS_vs_HAPI_line_broadening.pdf") # Compare integrals diff = abs( s.get_integral("transmittance_noslit") / s_hapi.get_integral("transmittance_noslit") - 1) b = diff < rtol if verbose: printm("Integral difference ({0:.2f}%) < {1:.2f}%: {2}".format( diff * 100, rtol * 100, b)) return b
s_opt.update() # compare times t_ref = s_ref.conditions['calculation_time'] t_opt = s_opt.conditions['calculation_time'] t_dlm = s_dlm.conditions['calculation_time'] #%% plt.ion() #%% _, [ax0, ax1] = plot_diff( s_ref, s_dlm, 'transmittance_noslit', method='ratio', label1='Reference {1} lines ({0:.0f}s)'.format( t_ref, str_fmt(s_ref.conditions['lines_calculated'])), label2='New method {1} lines ({0:.0f}s)'.format( t_dlm, str_fmt(s_dlm.conditions['lines_calculated'])), ) #legendargs={'loc':'lower left', 'handlelength':1, 'fontsize':16.5}) ax0.set_ylim((0.87, 1)) ax1.set_ylim((0.999, 1.001)) handles, labels = ax0.get_legend_handles_labels() leg = ax0.legend(frameon=False, fontsize=16, loc=3) axins = ax0.inset_axes([0.60, 0.125, 0.35, 0.45]) axins.ticklabel_format(useOffset=False, axis='x') axins.tick_params(which='major', labelsize=14) axins.get_yaxis().set_visible(False) axins.plot(*s_ref.get('transmittance_noslit', wunit='cm-1'), color='k', lw=2)
def test_broadening_vs_hapi(rtol=1e-2, verbose=True, plot=False, *args, **kwargs): """ Test broadening against HAPI and tabulated data We're looking at CO(0->1) line 'R1' at 2150.86 cm-1 """ from hapi import absorptionCoefficient_Voigt, db_begin, fetch, tableList if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # Conditions T = 3000 p = 0.0001 wstep = 0.001 wmin = 2150 # cm-1 wmax = 2152 # cm-1 broadening_max_width = 10 # cm-1 # %% HITRAN calculation # ----------- # Generate HAPI database locally hapi_data_path = join(dirname(__file__), __file__.replace(".py", "_HAPIdata")) db_begin(hapi_data_path) if not "CO" in tableList(): # only if data not downloaded already fetch("CO", 5, 1, wmin - broadening_max_width / 2, wmax + broadening_max_width / 2) # HAPI doesnt correct for side effects # Calculate with HAPI nu, coef = absorptionCoefficient_Voigt( SourceTables="CO", Environment={ "T": T, "p": p / 1.01325, }, # K # atm WavenumberStep=wstep, HITRAN_units=False, ) s_hapi = Spectrum.from_array(nu, coef, "abscoeff", "cm-1", "cm-1", conditions={"Tgas": T}, name="HAPI") # %% 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], warnings={ "MissingSelfBroadeningWarning": "ignore", "NegativeEnergiesWarning": "ignore", "HighTemperatureWarning": "ignore", "GaussianBroadeningWarning": "ignore", }, ) # 0.2) sf.load_databank(path=join(hapi_data_path, "CO.data"), format="hitran", parfuncfmt="hapi") # s = pl.non_eq_spectrum(Tvib=T, Trot=T, Ttrans=T) s = sf.eq_spectrum(Tgas=T, name="RADIS") if plot: # plot broadening of line of largest linestrength sf.plot_broadening(i=sf.df1.S.idxmax()) # Plot and compare res = abs(get_residual_integral(s, s_hapi, "abscoeff")) if plot: plot_diff( s, s_hapi, var="abscoeff", title="{0} bar, {1} K (residual {2:.2g}%)".format(p, T, res * 100), show_points=False, ) plt.xlim((wmin, wmax)) if verbose: printm("residual:", res) assert res < rtol
def test_broadening_DLM(verbose=True, plot=False, *args, **kwargs): """ Test use of lineshape template for broadening calculation. Ensures that results are the same with and without DLM. """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there # Conditions T = 3000 p = 1 wstep = 0.002 wmin = 2150 # cm-1 wmax = 2152 # 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=False, warnings={ "MissingSelfBroadeningWarning": "ignore", "NegativeEnergiesWarning": "ignore", "HighTemperatureWarning": "ignore", "GaussianBroadeningWarning": "ignore", }, ) # 0.2) sf.load_databank("HITRAN-CO-TEST") # Reference: calculate without DLM assert sf.misc["chunksize"] is None s_ref = sf.eq_spectrum(Tgas=T) s_ref.name = "Reference ({0:.2f}s)".format( s_ref.conditions["calculation_time"]) # DLM: sf.misc["chunksize"] = "DLM" sf.params.broadening_method = "convolve" s_dlm = sf.eq_spectrum(Tgas=T) s_dlm.name = "DLM ({0:.2f}s)".format(s_dlm.conditions["calculation_time"]) # DLM Voigt with Whiting approximation: sf.params.broadening_method = "voigt" s_dlm_voigt = sf.eq_spectrum(Tgas=T) s_dlm_voigt.name = "DLM Whiting ({0:.2f}s)".format( s_dlm_voigt.conditions["calculation_time"]) # Compare res = get_residual(s_ref, s_dlm, "abscoeff") res_voigt = get_residual(s_dlm, s_dlm_voigt, "abscoeff") if verbose: print("Residual:", res) # plot the last one if plot: plot_diff(s_ref, s_dlm, "abscoeff") plt.legend() plot_diff(s_dlm, s_dlm_voigt, "abscoeff") assert res < 1.2e-5 assert res_voigt < 1e-5
Nlines = 1e4 #%% Calculate normal for width in broadening_max_widths: spectra_default[width] = load_spec('../spec_fig78/spectra_default[{0}].spec'.format(width), binary=True) spectra_convolve[width] = load_spec('../spec_fig78/spectra_convolve[{0}].spec'.format(width), binary=True) spectra_DLM_opt = load_spec('../spec_fig78/spectra_DLM_opt.spec') plt.ion() ##fig, [ax0, ax1] = plot_diff(spectra_default[broadening_max_widths[1]], spectra_DLM_opt, 'abscoeff', figsize=(10,6)) fig, [ax0, ax1] = plot_diff(spectra_default[broadening_max_widths[1]], spectra_DLM_opt, 'abscoeff', figsize=(10,6)) ax0.set_ylim((0, 0.9)) ax1.set_ylim((-0.0025, 0.0025)) from mpl_toolkits.axes_grid1.inset_locator import inset_axes axins = ax0.inset_axes([0.115, 0.25, 0.35, 0.45]) axins.ticklabel_format(useOffset=False, axis='x') axins.tick_params(which='major', labelsize=14) axins.get_yaxis().set_visible(False) axins.plot(*spectra_default[broadening_max_widths[1]].get('abscoeff', wunit='cm-1'), color='k', lw=2) axins.plot(*spectra_DLM_opt.get('abscoeff', wunit='cm-1'), color='r', lw=1) axins.set_xlim((2235, 2238.5))
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
spectra_default = {} spectra_DLM = {} spectra_DLM_opt = {} Nlines = [101, 1001, 10017, 100725, 1813040, 1813040] plt.ion() for N in Nlines: spectra_default[N] = load_spec( '../spec/spectra_default_[{0}].spec'.format(N), binary=True) spectra_DLM_opt[N] = load_spec( '../spec/spectra_DLM_opt[{0}].spec'.format(N), binary=True) # %% Plot last spectra (opt) fig, [ax0, ax1] = plot_diff(spectra_default[N], spectra_DLM_opt[N], 'abscoeff') ax0.set_ylim((0, 0.5)) ax1.set_ylim((-0.005, 0.005)) axins = ax0.inset_axes([0.06, 0.3, 0.3, 0.4]) axins.ticklabel_format(useOffset=False, axis='x') axins.tick_params(which='major', labelsize=14) axins.get_yaxis().set_visible(False) axins.plot(*spectra_default[N].get('abscoeff', wunit='cm-1'), color='k', lw=2) axins.plot(*spectra_DLM_opt[N].get('abscoeff', wunit='cm-1'), color='r', lw=1) axins.set_xlim((2200, 2205)) axins.set_ylim((0.0125, 0.32)) ax0.indicate_inset_zoom(axins) fig.savefig('output/Fig6a.pdf')