def test_compare_torch_CO2(verbose=True, plot=False, save=False, warnings=True, use_cache=True, *args, **kwargs): """Reproduce the plasma torch experiment of Packan 2003 in in atmospheric air Notes ----- Thresholds parameters are reduced for a faster calculation time. For instance: - broadening_max_width should be 50 rather than 20 - cutoff should be 1e-27 rather than 1e-25 - wstep should be 0.01 or even 0.008 rather than 0.1 Performance: - neq==0.9.20: Finished test_compare_torch_CO2 in 758.640324s - neq==0.9.21: Finished test_compare_torch_CO2 in 672s - neq==0.9.21*: (with ParallelFactory) Finished test_compare_torch_CO2 in 298s - neq==0.9.22: (Parallel + continuum) Finished in 65s RADIS 0.9.9 == neq 0.9.24 - RADIS 0.9.26: Finished test_compare_torch_CO2 in 57s (DLM, no continuum) Reference -------- Packan et al 2003 "Measurement and Modeling of OH, NO, and CO Infrared Radiation at 3400 K", JTHT """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() t0 = time() # %% Conditions wlmin = 4100 wlmax = 4900 wmin = nm2cm(wlmax) wmax = nm2cm(wlmin) wstep = 0.1 # Load concentration profile conds = pd.read_csv( getValidationCase( "test_compare_torch_CO2_data/test_compare_torch_CO2_conditions_JTHT2003.dat" ), comment="#", delim_whitespace=True, ) slab_width = 0.05 # cm, WARNING. Hardcoded (look up the table) # %% Calculate slabs # CO2 sf = ParallelFactory( wavenum_min=wmin, wavenum_max=wmax, mole_fraction=None, path_length=None, molecule="CO2", isotope="1,2", parallel=False, wstep=wstep, db_use_cached=use_cache, export_lines=False, # saves some memory export_populations=False, # saves some memory cutoff=1e-25, Nprocs=cpu_count() - 1, # warning with memory if too many procs broadening_max_width=20, # pseudo_continuum_threshold=0.01, # use pseudo-continuum, no DLM. Note : 56s on 20/08. # optimization=None, pseudo_continuum_threshold= 0, # use DLM, no pseudo-continuum. Note : 84s on 20/08 optimization="min-RMS", verbose=False, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" # # Init database: only if we want to save all spectra being calculated # (discarded for the moment) # if use_cache: # sf.init_database('test_compare_torch_CO2_SpectrumDatabase_HITEMP_1e25', # add_info=['Tgas']) sf.init_databank("HITEMP-CO2-DUNHAM", load_energies=False) # saves some memory # sf.init_databank('CDSD-4000') # CO sfco = ParallelFactory( wavenum_min=wmin, wavenum_max=wmax, mole_fraction=None, path_length=None, molecule="CO", isotope="1,2", parallel=False, wstep=wstep, db_use_cached=use_cache, export_lines=False, # saves some memory export_populations=False, # saves some memory cutoff=1e-25, Nprocs=cpu_count() - 1, broadening_max_width=20, optimization=None, verbose=False, ) sfco.warnings["MissingSelfBroadeningWarning"] = "ignore" # Init database: only if we want to save all spectra being calculated # (discarded for the moment) # if use_cache: # sfco.init_database( # 'test_compare_torch_CO_SpectrumDatabase_HITEMP_1e25', add_info=['Tgas']) sfco.init_databank("HITEMP-CO-DUNHAM") # Calculate all slabs # .. CO2 at equilibrium slabsco2 = sf.eq_spectrum(list(conds.T_K), mole_fraction=list(conds.CO2), path_length=slab_width) # .. CO at equilibrium, but with non_eq to calculate PartitionFunctions instead of using # ... tabulated ones (which are limited to 3000 K in HAPI) slabsco = sfco.non_eq_spectrum( list(conds.T_K), list(conds.T_K), mole_fraction=list(conds.CO), path_length=slab_width, ) # Room absorption with pytest.warns( UserWarning ): # we expect a "using ParallelFactory for single case" warning s0 = sf.eq_spectrum(Tgas=300, mole_fraction=330e-6, path_length=600)[0] # Warning: This slab includes the CO2 emission from the 300 K air # within the spectrometer. But experimentally it is substracted # by there the chopper (this is corrected below) # ... see RADIS Article for more details # Add radiance for everyone if not calculated (ex: loaded from database) for s in slabsco2 + slabsco + [s0]: s.update() # Merge CO + CO2 for each slab slabstot = [MergeSlabs(s, sco) for (s, sco) in zip(slabsco2, slabsco)] # %% Line-of-sight # Solve ETR along line of sight # -------- # two semi profile, + room absortion line_of_sight = slabstot[1:][::-1] + slabstot + [s0] stot = SerialSlabs(*line_of_sight) # stot = SerialSlabs(*slabstot[1:][::-1], *slabstot, s0) # Python 3 syntax only # Also calculate the contribution of pure CO # --------- s0tr = s0.copy() # transmittance only s0tr.conditions["thermal_equilibrium"] = False s0tr._q["radiance_noslit"] *= 0 # hack to remove CO2 emission s0tr._q["emisscoeff"] *= 0 # hack to remove CO2 emission line_of_sight = slabsco[1:][::-1] + slabsco + [s0tr] sco = SerialSlabs(*line_of_sight) # sco = SerialSlabs(*slabsco[1:][::-1], *slabsco, s0tr) # Python 3 syntax only # Generate Slit # ------ disp = 4 # dispersion conversion function (nm/mm) s_in = 1 # entrance slit (mm) s_out = 2.8 # exit slit (mm) top = (s_out - s_in) * disp base = (s_out + s_in) * disp slit_function = (top, base) # (nm) # Final plot unit unit = "µW/cm2/sr" norm_by = "max" # should be 'max' if unit ~ 'µW/cm2/sr', # 'area' if unit ~ 'µW/cm2/sr/nm' # Convolve with Slit # ------- sco.apply_slit(slit_function, unit="nm", norm_by=norm_by, shape="trapezoidal") stot.apply_slit(slit_function, unit="nm", norm_by=norm_by, shape="trapezoidal") # Remove emission from within the spectrometer (substracted # by the chopper experimentaly) # ------- s0spectro = s0.copy() s0spectro.rescale_path_length(75 * 4) # spectrometer length s0spectro.apply_slit(slit_function, unit="nm", norm_by=norm_by, shape="trapezoidal") _, I0spectro = s0spectro.get("radiance", Iunit=unit) wtot, Itot = stot.get("radiance", Iunit=unit) stot_corr = experimental_spectrum( wtot, Itot - I0spectro, # hack to remove # emission from within # spectrometer Iunit=unit, conditions={"medium": "air"}, ) # %% Compare with experiment data # Plot experimental data # ------ exp = pd.read_csv( getValidationCase( "test_compare_torch_CO2_data/test_compare_torch_CO2_spectrum_JTHT2003.dat" ), skiprows=5, delim_whitespace=True, ) exp.w /= 10 # Angstrom to nm exp = exp[(exp.w > wlmin) & (exp.w < wlmax)] sexp = experimental_spectrum(exp.w, exp.I, Iunit="mW/cm2/sr", conditions={"medium": "air"}) if plot: sexp.plot("radiance", wunit="nm", Iunit=unit, lw=2, label="Packan 2003") # Plot calculated # ---------- stot.plot( "radiance", wunit="nm", Iunit=unit, nfig="same", color="r", ls="--", label="All: CO$_2$+CO", ) # Plot internal spectrometer emission s0spectro.plot( "radiance", wunit="nm", Iunit=unit, nfig="same", color="b", label="CO$_2$ in Spectrometer", ) stot_corr.plot( "radiance", wunit="nm", Iunit=unit, nfig="same", color="r", lw=2, label="All-CO$_2$ in Spectro", zorder=10, ) sco.plot( "radiance", wunit="nm", Iunit=unit, nfig="same", color="g", ls="-", label="CO", ) plt.ylim((0, 9)) plt.legend(loc="upper right") if save: plt.savefig("test_compare_torch_CO2_brd20.png") plt.savefig("test_compare_torch_CO2_brd20k.pdf") assert get_residual(stot_corr, sexp, "radiance") < 0.02 if verbose: print(("Finished test_compare_torch_CO2 in {0:.0f}s".format(time() - t0)))
def test_klarenaar_validation_case(verbose=True, plot=False, warnings=True, *args, **kwargs): """ Reproduce the Klarenaar 2018 validation case, as given in the [RADIS-2018]_ article. References ---------- Klarenaar et al, "Time evolution of vibrational temperatures in a CO 2 glow discharge measured with infrared absorption spectroscopy", doi 10.1088/1361-6595/aa902e, and the references there in. """ setup_test_line_databases() # %% Data from Dang, adapted by Klarenaar s_exp = Spectrum.from_txt( getValidationCase( join( "test_CO2_3Tvib_vs_klarenaar_data", "klarenaar_2017_digitized_data.csv", )), "transmittance_noslit", waveunit="cm-1", unit="I/I0", delimiter=",", name="Klarenaar 2017", ) # %% Calculate Klarenaar test case conditions sf = SpectrumFactory( 2284.2, 2284.6, wstep=0.001, # cm-1 pressure=20 * 1e-3, # bar db_use_cached=True, cutoff=1e-25, molecule="CO2", isotope="1,2", path_length=10, # cm-1 # warning! 10% in mass fraction -> less in mole fraction mole_fraction=0.1 * 28.97 / 44.07, broadening_max_width=1, # cm-1 medium="vacuum", export_populations="vib", ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" # sf.load_databank('HITEMP-CO2-DUNHAM') sf.load_databank("HITEMP-CO2-TEST") # Calculate with Klarenaar fitted values T12 = 517 T3 = 2641 Trot = 491 s = sf.non_eq_spectrum((T12, T12, T3), Trot, Ttrans=Trot, vib_distribution="treanor", name="RADIS") if plot: plot_diff(s, s_exp, "transmittance_noslit") # plt.savefig('test_CO2_3Tvib_vs_klarenaar.png') assert get_residual(s, s_exp, "transmittance_noslit", ignore_nan=True) < 0.003 return True
def test_klarenaar_validation_case(verbose=True, plot=False, warnings=True, *args, **kwargs): ''' Reproduce the Klarenaar 2018 validation case, as given in the [RADIS-2018]_ article. References ---------- Klarenaar et al, "Time evolution of vibrational temperatures in a CO 2 glow discharge measured with infrared absorption spectroscopy", doi 10.1088/1361-6595/aa902e, and the references there in. ''' setup_test_line_databases() try: # %% Data from Dang, adapted by Klarenaar s_exp = Spectrum.from_txt(getValidationCase(join('test_CO2_3Tvib_vs_klarenaar_data', 'klarenaar_2017_digitized_data.csv')), 'transmittance_noslit', waveunit='cm-1', unit='I/I0', delimiter=',', name='Klarenaar 2017') # %% Calculate Klarenaar test case conditions sf = SpectrumFactory(2284.2, 2284.6, wstep=0.001, # cm-1 pressure=20*1e-3, # bar db_use_cached=True, cutoff=1e-25, molecule='CO2', isotope='1,2', path_length=10, # cm-1 # warning! 10% in mass fraction -> less in mole fraction mole_fraction=0.1*28.97/44.07, broadening_max_width=1, # cm-1 medium='vacuum', export_populations='vib', ) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' # sf.load_databank('HITEMP-CO2-DUNHAM') sf.load_databank('HITEMP-CO2-TEST') # Calculate with Klarenaar fitted values T12 = 517 T3 = 2641 Trot = 491 s = sf.non_eq_spectrum((T12, T12, T3), Trot, Ttrans=Trot, vib_distribution='treanor', name='RADIS') if plot: plot_diff(s, s_exp, 'transmittance_noslit') # plt.savefig('test_CO2_3Tvib_vs_klarenaar.png') assert get_residual(s, s_exp, 'transmittance_noslit', ignore_nan=True) < 0.003 return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)