Exemple #1
0
def test_line_survey_CO2(verbose=True,
                         plot=True,
                         warnings=True,
                         *args,
                         **kwargs):

    setup_test_line_databases()

    try:
        pl = SpectrumFactory(
            wavenum_min=2380,
            wavenum_max=2400,
            #                         wavelength_min=4170,
            #                         wavelength_max=4200,
            mole_fraction=400e-6,
            path_length=100,  # cm
            parallel=False,
            cutoff=1e-30,
            isotope=[1],
            save_memory=True,
            db_use_cached=True,
        )  # 0.2)
        pl.warnings["MissingSelfBroadeningWarning"] = "ignore"
        pl.load_databank("HITRAN-CO2-TEST")
        s = pl.eq_spectrum(Tgas=1500)
        s.apply_slit(0.5)
        if plot:
            s.line_survey(overlay="transmittance", barwidth=0.01)

        if verbose:
            printm("no boolean defined for test_line_survey")
        return True  # test not defined (just testing methods work)

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #2
0
def test_CDSD_calc_vs_tab(verbose=True, warnings=True, *args, **kwargs):
    ''' Test 1: compare calculated PartFunc to the tabulated one '''

    from radis.misc.config import getDatabankEntries

    try:

        iso = 1
        database = 'CDSD-HITEMP-PC'
        
        # Compare tab to hardcoded
        parfunc = getDatabankEntries(database)['parfunc']
        Qf = PartFuncCO2_CDSDtab(iso, parfunc)
        assert np.isclose(Qf.at(300), 291.0447781984652, rtol=0.001)
        assert np.isclose(Qf.at(3000), 114689.88454184022, rtol=0.001)

        if verbose:
            printm('Tested CDSD tabulated is correct: OK')

        # Compare tab to calculated
        energies = getDatabankEntries(database)['levels']
        levelsfmt = getDatabankEntries(database)['levelsfmt']
        Qfc = PartFuncCO2_CDSDcalc(energies[iso], levelsfmt=levelsfmt, isotope=iso, use_cached=True)
        assert np.isclose(Qf.at(300), Qfc.at(300), rtol=0.001)
        assert np.isclose(Qf.at(3000), Qfc.at(3000), rtol=0.001)

        if verbose:
            printm('Tested CDSD Q_calc vs Q_tab give same output: OK')

        return True

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #3
0
def test_CDSD_calc_vs_ref(warnings=True, verbose=True, *args, **kwargs):
    ''' Test partition functions calculated with CDSD energy levels against 
    hardcoded values '''

    from radis.misc.config import getDatabankEntries

    iso = 1

    try:
        energies = getDatabankEntries('CDSD-HITEMP-PC')['levels']
        levelsfmt = getDatabankEntries('CDSD-HITEMP-PC')['levelsfmt']
        Qf = PartFuncCO2_CDSDcalc(energy_levels=energies[iso],
                                  isotope=iso,
                                  use_cached=True,
                                  levelsfmt=levelsfmt)
        assert np.isclose(Qf.at(300), 291.0447781984652, rtol=0.001)
        assert np.isclose(Qf.at(3000), 114689.88454184022, rtol=0.001)
        assert np.isclose(Qf.at_noneq(300, 300), 291.0447781984652, rtol=0.001)
        assert np.isclose(Qf.at_noneq(3000, 3000),
                          114689.88454184022,
                          rtol=0.001)
        assert np.isclose(Qf.at_noneq(3000,
                                      3000,
                                      overpopulation={'(0,1)': 3},
                                      returnQvibQrot=True)[0],
                          120053.34252537244,
                          rtol=0.001)

        if verbose:
            printm('Tested Q_CDSD values are correct : OK')

        return True

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #4
0
def test_media_line_shift(plot=False,
                          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,
                             verbose=verbose)
        sf.warnings['MissingSelfBroadeningWarning'] = 'ignore'
        sf.warnings['GaussianBroadeningWarning'] = 'ignore'
        sf.load_databank('HITRAN-CO-TEST')

        # Calculate a spectrum
        s = sf.eq_spectrum(2000)

        # Compare
        if plot:
            fig = plt.figure(fig_prefix + 'Propagating media line shift')
            s.plot('radiance_noslit',
                   wunit='nm_vac',
                   nfig=fig.number,
                   lw=2,
                   label='Vacuum')
            plt.title('CO spectrum (2000 K)')
            s.plot('radiance_noslit',
                   wunit='nm',
                   nfig=fig.number,
                   lw=2,
                   color='r',
                   label='Air')

        # ... there should be about ~1.25 nm shift at 4.5 µm:
        assert np.isclose(
            s.get('radiance_noslit', wunit='nm_vac')[0][0] -
            s.get('radiance_noslit', wunit='nm')[0][0], 1.2540436086346745)

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #5
0
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)
Exemple #6
0
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)

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)

    finally:  # cleaning
        if exists(temp_file_name):
            os.remove(temp_file_name)

    return True
Exemple #7
0
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)
Exemple #8
0
def test_recompute_Q_from_QvibQrot_CDSD_PC(verbose=True,
                                           warnings=True,
                                           *args,
                                           **kwargs):
    ''' 
    Calculate vibrational and rotational partition functions:
        
    - in CDSD with (p,c) convention for vibrational levels 
    - under nonequilibrium
    
    Recompute total partition function, and compare

    Test if partition function can be recomputed correctly from vibrational
    populations and rotational partition function (note that we are in a coupled
    case so partition function is not simply the product of Qvib, Qrot) 
    '''

    from radis.misc.config import getDatabankEntries

    iso = 1

    try:
        energies = getDatabankEntries('CDSD-HITEMP-PC')['levels']
        levelsfmt = getDatabankEntries('CDSD-HITEMP-PC')['levelsfmt']

        Tvib = 1500
        Trot = 300

        Qf = PartFuncCO2_CDSDcalc(energies[iso],
                                  isotope=iso,
                                  use_cached=True,
                                  levelsfmt=levelsfmt)
        Q = Qf.at_noneq(Tvib, Trot)
        _, Qvib, dfQrot = Qf.at_noneq(Tvib, Trot, returnQvibQrot=True)
        if verbose:
            printm('Q', Q)
        if verbose:
            printm('Qvib', Qvib)

        # 1) Test Q vs Q recomputed from Qrot, Qvib

        # Recompute Qtot
        df = dfQrot
        Q2 = ((df.gvib * exp(-df.Evib * hc_k / Tvib)) * df.Qrot).sum()
        # Todo: non Boltzmann case

        assert np.isclose(Q, Q2)

        if verbose:
            printm('Tested Q vs recomputed from (Qvib, Qrot) are the same: OK')

        return True

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #9
0
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)
Exemple #10
0
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_load_spectrum(plot=False,
                       verbose=True,
                       warnings=True,
                       *args,
                       **kwargs):
    ''' Test load / save 

    Fast version: dont save lines / populations, compare spectra only 
    '''

    setup_test_line_databases()

    temp_file_name = '_test_database_co2_tempfile.spec'
    assert (not exists(temp_file_name))

    try:
        sf = SpectrumFactory(
            wavelength_min=4190,
            wavelength_max=4200,
            mole_fraction=400e-6,
            path_length=0.1,  # cm
            isotope=[1],
            db_use_cached=True,
            cutoff=1e-20,
            verbose=verbose)
        sf.warnings['MissingSelfBroadeningWarning'] = 'ignore'
        sf.load_databank('HITRAN-CO2-TEST')
        s1 = sf.eq_spectrum(Tgas=300)
        s1.apply_slit(2, verbose=False)
        s1.update()
        s2 = load_spec(s1.store(temp_file_name, compress=True))
        s2.update()
        if plot:
            fig = plt.figure(fig_prefix + 'Calculated vs stored+retrieved')
            s1.plot('absorbance', nfig=fig.number, lw=3, label='calculated')
            s2.plot('absorbance',
                    nfig=fig.number,
                    color='r',
                    label='stored (compressed) and retrieved')
            plt.legend()

        assert s1.compare_with(s2, spectra_only=True, plot=False)

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)

    finally:  # cleaning
        if exists(temp_file_name):
            os.remove(temp_file_name)

    return True
Exemple #12
0
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)
Exemple #13
0
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)
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",
            )

            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

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #15
0
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

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)

    finally:
        rmtree(temp_database_name)
Exemple #16
0
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)
Exemple #17
0
def test_calc_spectrum(verbose=True, plot=True, warnings=True, *args, **kwargs):
    """ Basic example, used as a non-regression test

    Notes
    -----
    
    How long it tooks to calculate this Spectrum?

    Performance test on old NeQ package, with the [CDSD-HITEMP-JMIN] databank.
    See the caveats in the E. Pannier "Limits of CO2 NonEquilibrium Models" paper.
    (just used here as a performance monitoring)
    
    - neq 0.9.20: 18.7s

    - neq 0.9.20*: 15.4s   (removed 2nd loop on 1st isotope because of groupby().apply())

    - neq 0.9.20**: 11.7s  (after replacing fill_Evib with map() ) 

    - neq 0.9.21: 9.4s     (improve Qrot / nrot fetching performance) 

    - neq 0.9.22: 8.4s     
    
    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]_
    
    (we also expect the test to be much faster than above, but that's just 
    because the database is smaller!)
    
    - radis 0.9.20 : 2.49 s    on [HITRAN-2016]
                     4.05 s    on [CDSD-HITEMP-JMIN]
    
    """

    if verbose:
        printm("Testing calc_spectrum match reference")

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        import matplotlib.pyplot as plt

        plt.ion()

    try:
        s = calc_spectrum(
            wavelength_min=4165,
            wavelength_max=4200,
            #                          databank='CDSD-HITEMP-JMIN',
            databank="fetch",  # not appropriate for these temperatures, but convenient for automatic testing
            Tgas=300,
            Tvib=1700,
            Trot=1550,
            path_length=0.1,
            mole_fraction=0.5,
            molecule="CO2",
            isotope="1,2",
            wstep=0.01,
            cutoff=1e-25,
            use_cached=True,
            medium="vacuum",
            verbose=verbose,
            warnings={
                "MissingSelfBroadeningWarning": "ignore",
                "NegativeEnergiesWarning": "ignore",
                "HighTemperatureWarning": "ignore",
            },
        )
        s.apply_slit((2, 2.5), "nm", shape="trapezoidal")

        if plot:
            s.plot(wunit="nm")

        w, I = s.get("radiance", wunit="nm")
        w_ref = w[::100]
        # Compare against hardcoded results (neq 0.9.22, 28/06/18)
        #        I_ref = np.array([0.28694463, 0.29141711, 0.32461613, 0.32909566, 0.21939511, 0.18606445,
        #                          0.19740763, 0.16948599, 0.16780345, 0.15572173, 0.16770853, 0.14966064,
        #                          0.13041356, 0.11751016, 0.10818072, 0.11592531, 0.04666677, 0.00177108,
        #                          0.00069339])
        # Harcoded results changed for RADIS  with the change of
        # database (HITEMP-2010 -> HITRAN-2016) and of Tvib model
        # CDSD with (P,C,Jmin,N) in CDSD polyad -> RADIS built-in constants)
        #        I_ref = np.array([ 0.29148768,  0.29646856,  0.32999337,  0.32249701,  0.2078451 ,
        #                          0.18974631,  0.2019285 ,  0.17346687,  0.17211401,  0.15939359,
        #                          0.17240575,  0.15395179,  0.13374185,  0.11997065,  0.10858693,
        #                          0.11114162,  0.04575873,  0.00163863,  0.00062654])
        # Updated again in RADIS 0.9.20 (19/08/19) to account for the use of DLM (difference
        # not significant)
        #        I_ref = np.array([ 0.29060991,  0.29756722,  0.32972058,  0.3206278 ,  0.20696867,
        #                           0.19218358,  0.20155747,  0.17336405,  0.17218653,  0.1589136 ,
        #                           0.17110649,  0.15403513,  0.13376804,  0.11932659,  0.10882006,
        #                           0.11112725,  0.0458288 ,  0.00247956,  0.00144128])
        # Updated again in RADIS 0.9.20 (02/09/19) with switch to tabulated Q(Tref)
        I_ref = np.array(
            [
                0.29048064,
                0.29743104,
                0.32955513,
                0.32047172,
                0.20688813,
                0.19210952,
                0.20148265,
                0.17330909,
                0.17213373,
                0.15887159,
                0.17106096,
                0.15400039,
                0.13374285,
                0.11930822,
                0.10880631,
                0.11111394,
                0.04582291,
                0.00247955,
                0.00144128,
            ]
        )
        if plot:
            plt.plot(w_ref, I_ref, "or", label="ref")
            plt.legend()
        assert np.allclose(I[::100], I_ref, atol=1e-6)

        return True

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #18
0
def DISCARDED_test_parallel_internal(plot=False,
                                     verbose=True,
                                     warnings=True,
                                     *args,
                                     **kwargs):
    ''' Core of the parallel test routine 
    
    Test than parallel is at least faster than sequential mode. Note that 
    this is not necessary: parallelization becomes much faster during the 
    convolution steps, hence for large number of lines
    '''
    # TODO: there is a line missing in the parallel case at 2283nm.
    # I expect the merging of different wave ranges to fail.
    # Test is not run for the moment

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        import matplotlib.pyplot as plt
        plt.ion()

    setup_test_line_databases()

    try:
        # Performance test
        Tvib = 1000  # , 1200, 1400]
        Trot = 900
        path_length = 0.1
        mole_fraction = 0.5

        cutoff = 0
        broadening_max_width = 1
        wstep = 0.0001

        # .. parallel
        sfp = SpectrumFactory(
            wavelength_min=4377.134,
            wavelength_max=4377.9,
            pressure=0.020,  # bar
            cutoff=cutoff,
            db_use_cached=True,
            lvl_use_cached=True,
            parallel=True,
            isotope='1',
            broadening_max_width=broadening_max_width,
            wstep=wstep,
            verbose=verbose)
        sfp.warnings['MissingSelfBroadeningWarning'] = 'ignore'
        sfp.warnings['NegativeEnergiesWarning'] = 'ignore'
        sfp.warnings['EmptyDatabaseWarning'] = 'ignore'
        sfp.load_databank('HITEMP-CO2-TEST')

        s_parallel = sfp.non_eq_spectrum(Tvib,
                                         Trot,
                                         path_length=path_length,
                                         mole_fraction=mole_fraction)
        s_parallel.name = 'Parallel ({0:.1f}s)'.format(
            s_parallel.conditions['calculation_time'])

        # ... non parallel
        sf = SpectrumFactory(
            wavelength_min=4377.134,
            wavelength_max=4377.9,
            pressure=0.020,  # bar
            cutoff=cutoff,
            db_use_cached=True,
            lvl_use_cached=True,
            isotope='1,2',
            broadening_max_width=broadening_max_width,
            wstep=wstep,
            verbose=verbose)
        sf.warnings['MissingSelfBroadeningWarning'] = 'ignore'
        sf.warnings['NegativeEnergiesWarning'] = 'ignore'
        sf.warnings['EmptyDatabaseWarning'] = 'ignore'
        sf.load_databank('HITEMP-CO2-TEST')
        s_sequential = sf.non_eq_spectrum(Tvib,
                                          Trot,
                                          path_length=path_length,
                                          mole_fraction=mole_fraction)
        s_sequential.name = 'Sequential ({0:.1f}s)'.format(
            s_sequential.conditions['calculation_time'])

        t0 = s_parallel.conditions['calculation_time']
        t1 = s_sequential.conditions['calculation_time']

        if verbose:
            printm('\nSpectrumFactory with internal parallel test')
            printm('-------------------')
            printm(('Parallel version: {0:.1f}s'.format(t0)))
            printm(('Normal version: {0:.1f}s'.format(t1)))
            printm('-------------------')

        # Assert that spectra are the same
        assert s_parallel.compare_with(s_sequential,
                                       spectra_only=True,
                                       plot=False)
        if verbose:
            printm('Ensured that spectra are the same: OK')

        if t0 > t1:
            warn(
                'Parallel version ({0:.1f}s) is slower than the Serial version ({1:.1f}s) !'
                .format(t0, t1))

        return True  # no plot implemented

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #19
0
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)
Exemple #20
0
def test_spec_generation(plot=True, verbose=2, warnings=True, *args, **kwargs):
    ''' Test spectrum generation
    Can be used as a base to generate spectra in your codes

    Non-regression test: compare with past version (see conditions below)

    Compare results from a reference case to results calculated on 30/12/2017
    This is not a validation case (30/12/2017 results are not a physically validated
    case), but it makes sure results dont change over time

    Conditions (30/12/2017)::

        Physical Conditions
        ----------------------------------------
           Tgas                 300 K
           Trot                 300 K
           Tvib                 300 K
           pressure             1.01325 bar
           isotope              1,2
           mole_fraction        1
           molecule             CO2
           path_length          1 cm
           wavelength_max       4400.0 nm
           wavelength_min       4150.0 nm
           wavenum_max          2409.6385542168673 cm-1
           wavenum_min          2272.7272727272725 cm-1
        Computation Parameters
        ----------------------------------------
           Tref                 296 K
           broadening_max_width  10 cm-1
           cutoff               1e-25 cm-1/(#.cm-2)
           db_assumed_sorted    True
           db_use_cached        True
           dbformat             cdsd
           dbpath               # USER-DEPENDANT: CDSD-HITEMP
           fillmissinglevelswithzero  False
           levelsfmt            cdsd
           levelspath           # USER-DEPENDANT: CDSD-4000
           medium               vacuum
           parfuncfmt           cdsd
           parfuncpath          # USER-DEPENDANT: CDSD-4000
           rot_distribution     boltzmann
           self_absorption      True
           vib_distribution     boltzmann
           wavenum_max_calc     2414.6385542168673 cm-1
           wavenum_min_calc     2267.7272727272725 cm-1
           waveunit             cm-1
           wstep                0.01 cm-1
        ----------------------------------------

    Notes
    -----

    Performance test. How long it tooks to calculate this Spectrum?
    Test with cutoff 1e-25, broadening_max_width=10 

    - 0.9.15: >>> 33s

    - 0.9.16*: (replaced groupby().apply() with iteration over indexes) >>> 32s  
            [but large impact expected on big files]

    - 0.9.16*: (upgraded cache files to h5) >>> 25s 

    - 0.9.16*: (also added h5 cache file for levels) >>> 21s

    - 0.9.16*: (with Whiting slit voigt function) >>> 5.8s

    Test with cutoff 1e-27, broadening_max_width=50 :  
    ("Spectrum calculated in ... ", including database loading time)

    - 0.9.16*: (same code as last) >>> 12.5s including 7.6s of broadening

    - 0.9.16**: (with pseudo_continuum_threshold=0.01) >>> 7.8s including 2.3s of broadening

    - 0.9.18 (normal code, no pseudo continuum). >>> ?
    
    - 0.9.21 (normal code) >>> 13.7s, including 8.7s of broadening
             (with pseudo_continuum_threshold=0.01) >>> 4.3s, including 2.6s of broadening

    - 0.9.21*              >>> 14.0s  (added the manual lineshape normalization instead of
                                       Whitings's polynomial)
    
    - 0.9.22 (normal code) >>> 11.3s   (without energy level lookup, for eq. calculations)
             (with pseudo_continuum_threshold=0.01) >>> 5.9s

    - 0.9.23 (normal code) >>> 7.2s   (added jit in Voigt broadening)
                           >>> 7.1s   (chunksize = None)  (and much faster for more lines)
             (with pseudo_continuum_threshold=0.01) >>> 4.9s
    
    '''

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        plt.ion()

    try:
        from time import time
        t0 = time()
        if verbose:
            printm('>>> _test_spec_generation')

        # This is how you get a spectrum (see calc.py for front-end functions
        # that do just that)
        sf = SpectrumFactory(
            wavelength_min=4150,
            wavelength_max=4400,
            parallel=False,
            bplot=False,
            cutoff=1e-27,
            isotope='1,2',
            db_use_cached=True,
            broadening_max_width=50,
            #                             pseudo_continuum_threshold=0.01,
            medium='vacuum',
            verbose=verbose)
        sf.warnings['MissingSelfBroadeningWarning'] = 'ignore'
        sf.warnings['NegativeEnergiesWarning'] = 'ignore'
        sf.load_databank(
            'HITEMP-CO2-DUNHAM',
            load_energies=False,  # no need to load energies at equilibrium
        )
        s = sf.eq_spectrum(Tgas=300)
        if verbose:
            printm(
                '>>> _test_spec_generation: Spectrum calculated in {0:.1f}s'.
                format(time() - t0))

        if plot:
            plt.figure(fig_prefix +
                       'Reference spectrum CDSD-HITEMP (radiance)')
            # Iunit is arbitrary. Use whatever makes sense
            s.plot('radiance_noslit', Iunit='µW/cm2/sr/nm', nfig='same')
        s.rescale_path_length(0.01)

        # Here we get some extra informations:
        if plot:
            sf.plot_broadening(i=0)  # show broadening of one line
            plt.xlim((2267.20, 2268.30))

        # Compare with harcoded results
        # ... code previously used to export hardcoded results:
        # ... >>> np.savetxt('output.txt', np.vstack(s.get('abscoeff', wunit='nm', medium='air')).T[::10])
        # ... and header contains all input conditions:
        # ... >>> print(s)
        from radis.test.utils import getTestFile
        wref, Iref = np.loadtxt(
            getTestFile('CO2abscoeff_300K_4150_4400nm.txt')).T
        match_reference = np.allclose(
            s.get('abscoeff', wunit='nm', medium='air')[1][::10], Iref)
        if not match_reference:
            # give some more information before raising error
            printm('Error: {0:.2f}%'.format(
                np.mean(
                    abs(
                        s.get('abscoeff', wunit='nm', medium='air')[1][::10] /
                        Iref - 1)) * 100))
            # Store the faulty spectrum
            s.store('test_factory_failed_{0}.spec'.format(neq.get_version()),
                    if_exists_then='replace')

        # Plot comparison
        if plot:
            plt.figure(fig_prefix + 'Reference spectrum (abscoeff)')
            # , show_points=True)  # show_points to have an
            s.plot('abscoeff',
                   wunit='nm',
                   medium='air',
                   nfig='same',
                   lw=3,
                   label='RADIS, this version')
            # idea of the resolution
            plt.plot(wref,
                     Iref,
                     'or',
                     ms=3,
                     label='version NEQ 0.9.20 (12/05/18)')
            plt.legend()
            plt.title('All close: {0}'.format(match_reference))
            plt.tight_layout()

        # Another example, at higher temperature.
        # Removed because no test is associated with it and it takes time for
        # nothing
#        s2 = sf.non_eq_spectrum(Tvib=1000, Trot=300)
#        if plot: s2.plot('abscoeff', wunit='nm')

        if verbose:
            printm(
                'Spectrum calculation (no database loading) took {0:.1f}s\n'.
                format(s.conditions['calculation_time']))
            printm(
                '_test_spec_generation finished in {0:.1f}s\n'.format(time() -
                                                                      t0))

        assert match_reference

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #21
0
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)
Exemple #22
0
def test_parallel(plot=False, verbose=True, warnings=True, *args, **kwargs):
    ''' Core of the parallel test routine 
    
    Test than parallel is at least faster than sequential mode. Note that 
    this is not necessary: parallelization becomes much faster during the 
    convolution steps, hence for large number of lines
    '''

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        import matplotlib.pyplot as plt
        plt.ion()

    setup_test_line_databases()

    try:
        # Performance test
        Tvib = 1000  # , 1200, 1400]
        Trot = [900, 1200, 1250, 1300, 1400, 1600]
        path_length = 0.1
        mole_fraction = 0.5

        cutoff = 0
        broadening_max_width = 50
        wstep = 0.01

        # .. parallel
        pf = ParallelFactory(wavelength_min=4165,
                             wavelength_max=4200,
                             cutoff=cutoff,
                             db_use_cached=True,
                             lvl_use_cached=True,
                             isotope='1',
                             broadening_max_width=broadening_max_width,
                             wstep=wstep,
                             verbose=verbose)
        pf.warnings['MissingSelfBroadeningWarning'] = 'ignore'
        pf.warnings['NegativeEnergiesWarning'] = 'ignore'
        pf.warnings['EmptyDatabaseWarning'] = 'ignore'
        pf.load_databank('HITRAN-CO2-TEST')

        t0 = time()
        s_parallel = pf.non_eq_spectrum(Tvib,
                                        Trot,
                                        path_length=path_length,
                                        mole_fraction=mole_fraction)
        t0 = time() - t0

        # ... non parallel
        sf = SpectrumFactory(wavelength_min=4165,
                             wavelength_max=4200,
                             cutoff=cutoff,
                             db_use_cached=True,
                             lvl_use_cached=True,
                             isotope='1,2',
                             broadening_max_width=broadening_max_width,
                             wstep=wstep,
                             verbose=verbose)
        sf.warnings['MissingSelfBroadeningWarning'] = 'ignore'
        sf.warnings['NegativeEnergiesWarning'] = 'ignore'
        sf.warnings['EmptyDatabaseWarning'] = 'ignore'
        sf.load_databank('HITRAN-CO2-TEST')
        t1 = time()
        s_sequential = []
        for Troti in Trot:
            s_sequential.append(
                sf.non_eq_spectrum(Tvib,
                                   Troti,
                                   path_length=path_length,
                                   mole_fraction=mole_fraction))
        t1 = time() - t1

        if verbose:
            printm(('\nParallelFactory performance test ({0} cases)'.format(
                len(Trot))))
            printm('-------------------')
            printm(('Parallel version: {0:.1f}s'.format(t0)))
            printm(('Normal version: {0:.1f}s'.format(t1)))
            printm('-------------------')

        # Assert that spectra are the same
        for i in range(len(Trot)):
            assert s_parallel[i].compare_with(s_sequential[i],
                                              spectra_only=True,
                                              plot=False)
        if verbose:
            printm('Ensured that spectra are the same: OK')


#        # parallel version should be at least faster!
#        # note: ...  may not be the case if the calculated ranges are too small
#        # ......... as is the case in the test database. Better use // for spectra
#        # ......... with calculation times > 5s
#        assert t0 > t1
        if t0 > t1:
            warn(
                'Parallel version ({0:.1f}s) is slower than the Serial version ({1:.1f}s) !'
                .format(t0, t1))

        return True  # no plot implemented

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #23
0
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%

    '''

    try:
        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

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #24
0
def test_resampling(rtol=1e-2,
                    verbose=True,
                    plot=True,
                    warnings=True,
                    *args,
                    **kwargs):
    """ Test what happens when a spectrum in nm or cm-1, is convolved
    with a slit function in nm. In particular, slit function is generated
    in the spectrum unit, and spectrum is resampled if not evenly spaced"""

    if verbose:
        printm("Test auto resampling")

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        plt.ion()

    try:

        setup_test_line_databases(
        )  # add HITRAN-CO-TEST in ~/.radis if not there

        plCO = SpectrumFactory(
            wavenum_min=2230,
            wavenum_max=2260,
            mole_fraction=0.02,
            path_length=100,  # cm
            broadening_max_width=20,  # cm^-1
            wstep=0.02,
            isotope=[1, 2, 3],
            verbose=verbose,
        )
        plCO.warnings["MissingSelfBroadeningWarning"] = "ignore"
        plCO.load_databank("HITRAN-CO-TEST")
        sCO = plCO.eq_spectrum(Tgas=300)

        w_nm, T_nm = sCO.get("transmittance_noslit", wunit="nm")
        w_nm, I_nm = sCO.get("radiance_noslit",
                             wunit="nm",
                             Iunit="mW/cm2/sr/nm")
        sCO_nm = transmittance_spectrum(
            w_nm, T_nm, wunit="nm")  # a new spectrum stored in nm
        # sCO_nm = theoretical_spectrum(w_nm, I_nm, wunit='nm', Iunit='mW/cm2/sr/nm') #  a new spectrum stored in nm

        if plot:
            fig = plt.figure(fig_prefix + "auto-resampling")
            sCO.plot(
                "transmittance_noslit",
                wunit="cm-1",
                nfig=fig.number,
                marker="o",
                color="k",
                lw=3,
                ms=10,
                label="(stored in cm-1)",
            )
            plt.title("No slit function")
            sCO_nm.plot(
                "transmittance_noslit",
                wunit="cm-1",
                nfig=fig.number,
                marker="o",
                color="r",
                label="(stored in nm)",
            )
            #            plt.xlim((2246.58, 2247.52))
            #            plt.ylim((0.87, 1.01))
            plt.legend()

        slit_function = 0.8
        slit_unit = "cm-1"
        sCO.apply_slit(slit_function, unit=slit_unit)
        sCO_nm.apply_slit(slit_function, unit=slit_unit)

        if plot:
            fig = plt.figure(fig_prefix +
                             "auto-resampling (after convolution)")
            sCO.plot(
                "transmittance",
                wunit="cm-1",
                nfig=fig.number,
                marker="o",
                color="k",
                lw=3,
                ms=10,
                label="(stored in cm-1)",
            )
            plt.title("Slit function: {0} {1}".format(slit_function,
                                                      slit_unit))
            sCO_nm.plot(
                "transmittance",
                wunit="cm-1",
                nfig=fig.number,
                marker="o",
                color="r",
                label="(stored in nm)",
            )

            #            plt.xlim((2246.58, 2247.52))
            #            plt.ylim((0.87, 1.01))
            plt.legend()

        w_conv, T_conv = sCO.get("transmittance", wunit="cm-1")
        w_nm_conv, T_nm_conv = sCO_nm.get("transmittance", wunit="cm-1")

        error = abs(
            (trapz(1 - T_conv, w_conv) - trapz(1 - T_nm_conv, w_nm_conv)) /
            trapz(1 - T_nm_conv, w_nm_conv))

        if verbose:
            printm("\n>>> _test_resampling\n")
        if verbose:
            printm("Error between 2 spectra ({0:.2f}%) < {1:.2f}%: {2}".format(
                error * 100, rtol * 100, bool(error < rtol)))
        assert bool(error < rtol)

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #25
0
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)
Exemple #26
0
def test_calc_spectrum_overpopulations(verbose=True,
                                       plot=False,
                                       warnings=True,
                                       *args,
                                       **kwargs):
    ''' Non-regression test: 
        
    Example using overpopulation of the 001 asymmetric stretch first level of CO2,
    which is written (p,c,N) = (3,1,4) in [CDSD-4000]_ notation
    
    Notes
    -----
    
    In old Neq package (before RADIS):
    
    the test uses a CDSD-PCN notation for vibrational energy assignation, i.e,
    Evib = minimal energy of a (p,c,N) polyad. See the discussion on the implications
    in the E. Pannier "Limits of CO2 NonEquilibrium models" paper. 
    Better use the assignation scheme suggested in the paper. 
    But it's okay here as a non-regression test.
    
    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]_
    
    '''

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        import matplotlib.pyplot as plt
        plt.ion()

    try:
        s = calc_spectrum(
            wavelength_min=4165,
            wavelength_max=4200,
            #                          databank='CDSD-HITEMP-PCN',
            databank=
            'fetch',  # not appropriate for these temperatures, but convenient for automatic testings
            Tgas=300,
            Tvib=1700,
            Trot=1550,
            #                          overpopulation={'(3,1,4)': 3},  # 00'0'1 in spectroscopic notation
            overpopulation={'(0,0,0,1)':
                            3},  # 00'0'1 in spectroscopic notation
            path_length=0.1,
            mole_fraction=0.5,
            molecule='CO2',
            isotope='1,2',
            wstep=0.01,
            cutoff=1e-25,
            use_cached=True,
            medium='vacuum',
            verbose=verbose,
            warnings={
                'MissingSelfBroadeningWarning': 'ignore',
                'NegativeEnergiesWarning': 'ignore',
                'HighTemperatureWarning': 'ignore'
            })
        s.apply_slit((2, 2.5), 'nm', shape='trapezoidal')

        if plot:
            s.plot()

        w, I = s.get('radiance', wunit='nm')
        w_ref = w[::100]
        # Compare against hardcoded results (neq 0.9.22, 28/06/18)
        I_ref = np.array([
            0.61826008, 0.65598262, 0.79760003, 0.7958013, 0.5792486,
            0.56727691, 0.60361258, 0.51549598, 0.51012651, 0.47133131,
            0.50770568, 0.45093953, 0.39129824, 0.35125324, 0.32238316,
            0.34542781, 0.13908073, 0.00506012, 0.00189535
        ])
        # Harcoded results changed for RADIS v1.0.1  with the change of
        # database (HITEMP-2010 -> HITRAN-2016) and of Tvib model
        # CDSD with (P,C,Jmin,N) in CDSD polyad -> RADIS built-in constants)
        I_ref = np.array([
            0.62299838, 0.66229013, 0.81037059, 0.79899315, 0.57215806,
            0.57626389, 0.61424273, 0.52454807, 0.5200812, 0.47920924,
            0.51843533, 0.46058817, 0.3983277, 0.35582979, 0.32095204,
            0.32821575, 0.13525543, 0.00469489, 0.00174166
        ])
        if plot:
            plt.plot(w_ref, I_ref, 'or', label='ref')
            plt.legend()
            s.plot_populations()

        assert np.allclose(I[::100], I_ref, atol=1e-6)

        if verbose:
            printm('Test overpopulations: OK')

        return True

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #27
0
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)
Exemple #28
0
def test_calc_spectrum(verbose=True,
                       plot=True,
                       warnings=True,
                       *args,
                       **kwargs):
    ''' Basic example, used as a non-regression test

    Note: test case not physically valid as overpopulation is currently calculated
    with a post processing method that is only valid in optically thin cases
    
    
    Notes
    -----
    
    How long it tooks to calculate this Spectrum?

    Performance test on old NeQ package, with the [CDSD-HITEMP-JMIN] databank.
    See the caveats in the E. Pannier "Limits of CO2 NonEquilibrium Models" paper.
    (just used here as a performance monitoring)
    
    - 0.9.20: 18.7s

    - 0.9.20*: 15.4s   (removed 2nd loop on 1st isotope because of groupby().apply())

    - 0.9.20**: 11.7s  (after replacing fill_Evib with map() ) 

    - 0.9.21: 9.4s     (improve Qrot / nrot fetching performance) 

    - 0.9.22: 8.4s     
    
    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]_
    
    (we also expect the test to be much faster than above, but that's just 
    because the database is smaller!)

    '''

    if verbose:
        printm('Testing calc_spectrum match reference')

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        import matplotlib.pyplot as plt
        plt.ion()

    try:
        s = calc_spectrum(
            wavelength_min=4165,
            wavelength_max=4200,
            #                          databank='CDSD-HITEMP-JMIN',
            databank=
            'fetch',  # not appropriate for these temperatures, but convenient for automatic testing
            Tgas=300,
            Tvib=1700,
            Trot=1550,
            path_length=0.1,
            mole_fraction=0.5,
            molecule='CO2',
            isotope='1,2',
            wstep=0.01,
            cutoff=1e-25,
            use_cached=True,
            medium='vacuum',
            verbose=verbose,
            warnings={
                'MissingSelfBroadeningWarning': 'ignore',
                'NegativeEnergiesWarning': 'ignore',
                'HighTemperatureWarning': 'ignore'
            })
        s.apply_slit((2, 2.5), 'nm', shape='trapezoidal')

        if plot:
            s.plot(wunit='nm')

        w, I = s.get('radiance', wunit='nm')
        w_ref = w[::100]
        # Compare against hardcoded results (neq 0.9.22, 28/06/18)
        #        I_ref = np.array([0.28694463, 0.29141711, 0.32461613, 0.32909566, 0.21939511, 0.18606445,
        #                          0.19740763, 0.16948599, 0.16780345, 0.15572173, 0.16770853, 0.14966064,
        #                          0.13041356, 0.11751016, 0.10818072, 0.11592531, 0.04666677, 0.00177108,
        #                          0.00069339])
        # Harcoded results changed for RADIS v1.0.1  with the change of
        # database (HITEMP-2010 -> HITRAN-2016) and of Tvib model
        # CDSD with (P,C,Jmin,N) in CDSD polyad -> RADIS built-in constants)
        I_ref = np.array([
            0.29148768, 0.29646856, 0.32999337, 0.32249701, 0.2078451,
            0.18974631, 0.2019285, 0.17346687, 0.17211401, 0.15939359,
            0.17240575, 0.15395179, 0.13374185, 0.11997065, 0.10858693,
            0.11114162, 0.04575873, 0.00163863, 0.00062654
        ])
        if plot:
            plt.plot(w_ref, I_ref, 'or', label='ref')
            plt.legend()
        assert np.allclose(I[::100], I_ref, atol=1e-6)

        return True

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #29
0
def test_calc_spectrum_overpopulations(
    verbose=True, plot=False, warnings=True, *args, **kwargs
):
    """ Non-regression test: 
        
    Example using overpopulation of the 001 asymmetric stretch first level of CO2,
    which is written (p,c,N) = (3,1,4) in [CDSD-4000]_ notation
    
    Notes
    -----
    
    In old Neq package (before RADIS):
    
    the test uses a CDSD-PCN notation for vibrational energy assignation, i.e,
    Evib = minimal energy of a (p,c,N) polyad. See the discussion on the implications
    in the E. Pannier "Limits of CO2 NonEquilibrium models" paper. 
    Better use the assignation scheme suggested in the paper. 
    But it's okay here as a non-regression test.
    
    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]_
    
    """

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        import matplotlib.pyplot as plt

        plt.ion()

    try:
        s = calc_spectrum(
            wavelength_min=4165,
            wavelength_max=4200,
            #                          databank='CDSD-HITEMP-PCN',
            databank="fetch",  # not appropriate for these temperatures, but convenient for automatic testings
            Tgas=300,
            Tvib=1700,
            Trot=1550,
            #                          overpopulation={'(3,1,4)': 3},  # 00'0'1 in spectroscopic notation
            overpopulation={"(0,0,0,1)": 3},  # 00'0'1 in spectroscopic notation
            path_length=0.1,
            mole_fraction=0.5,
            molecule="CO2",
            isotope="1,2",
            wstep=0.01,
            cutoff=1e-25,
            use_cached=True,
            medium="vacuum",
            verbose=verbose,
            warnings={
                "MissingSelfBroadeningWarning": "ignore",
                "NegativeEnergiesWarning": "ignore",
                "HighTemperatureWarning": "ignore",
            },
        )
        s.apply_slit((2, 2.5), "nm", shape="trapezoidal")

        if plot:
            s.plot()

        w, I = s.get("radiance", wunit="nm")
        w_ref = w[::100]
        # Compare against hardcoded results (neq 0.9.22, 28/06/18)
        #        I_ref = np.array([0.61826008, 0.65598262, 0.79760003, 0.7958013 , 0.5792486 ,
        #                          0.56727691, 0.60361258, 0.51549598, 0.51012651, 0.47133131,
        #                          0.50770568, 0.45093953, 0.39129824, 0.35125324, 0.32238316,
        #                          0.34542781, 0.13908073, 0.00506012, 0.00189535])
        # Harcoded results changed for RADIS v1.0.1  with the change of
        # database (HITEMP-2010 -> HITRAN-2016) and of Tvib model
        # CDSD with (P,C,Jmin,N) in CDSD polyad -> RADIS built-in constants)
        #
        #        I_ref = np.array([ 0.62299838,  0.66229013,  0.81037059,  0.79899315,  0.57215806,
        #                          0.57626389,  0.61424273,  0.52454807,  0.5200812 ,  0.47920924,
        #                          0.51843533,  0.46058817,  0.3983277 ,  0.35582979,  0.32095204,
        #                          0.32821575,  0.13525543,  0.00469489,  0.00174166])
        # Updated again in RADIS 0.9.20 (16/08/19) to account for the use of DLM (difference
        # not significant)
        #        I_ref = np.array([ 0.62134142,  0.66722021,  0.81016539,  0.79387937,  0.56974945,
        #                           0.58280035,  0.6120114 ,  0.52319075,  0.5193041 ,  0.47686282,
        #                           0.51374777,  0.46022548,  0.3979033 ,  0.3534643 ,  0.32129239,
        #                           0.32786479,  0.1351593 ,  0.0068877 ,  0.00387545])
        # Updated again in RADIS 0.9.20 (02/09/19) with switch to tabulated Q(Tref)
        I_ref = np.array(
            [
                0.62109562,
                0.66695661,
                0.80983176,
                0.79356445,
                0.56958189,
                0.58264143,
                0.61185167,
                0.52307454,
                0.51919288,
                0.47677519,
                0.51365307,
                0.46015383,
                0.39785172,
                0.35342697,
                0.32126465,
                0.32783797,
                0.13514737,
                0.00688769,
                0.00387544,
            ]
        )
        if plot:
            plt.plot(w_ref, I_ref, "or", label="ref")
            plt.legend()
            s.plot_populations()

        assert np.allclose(I[::100], I_ref, atol=1e-6)

        if verbose:
            printm("Test overpopulations: OK")

        return True

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)
Exemple #30
0
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 1.0.0 == neq 0.9.24

    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()

    try:

        # %% 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(
            wmin,
            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,
            pseudo_continuum_threshold=0.01,
            Nprocs=cpu_count() - 1,  # warning with memory if too many procs
            broadening_max_width=20,
            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(
            wmin,
            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,
            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

    except DatabankNotFound as err:
        assert IgnoreMissingDatabase(err, __file__, warnings)

    if verbose:
        print(("Finished test_compare_torch_CO2 in {0:.0f}s".format(time() -
                                                                    t0)))