Ejemplo n.º 1
0
def test_vs_RADEX():
    for filename,coll_ID,Tex_values,tau_nu_values in\
                          zip(filenames,collider_names,RADEX_Tex,RADEX_tau_nu):
        lamda_filepath = os.path.join(here,filename)
        params = zip(Ntot_values,width_v_values,Tkin_values,
                     coll_partner_densities_values,test_trans,Tex_values,tau_nu_values)
        for Ntot,width_v,Tkin,collp_dens,trans_num,Tex,tau_nu in params:
            coll_partner_densities = {coll_ID:collp_dens}
            test_nebula = nebula.Nebula(
                        data_filepath=lamda_filepath,geometry=geometry,
                        ext_background=ext_background,Tkin=Tkin,
                        coll_partner_densities=coll_partner_densities,
                        Ntot=Ntot,line_profile=line_profile,width_v=width_v)
            test_nebula.solve_radiative_transfer()
            fluxes = test_nebula.observed_fluxes(
                                  source_surface=surface,d_observer=distance)
            #see radex_output_readme.txt or RADEX manual for explanation of the follwing formula
            trans = test_nebula.emitting_molecule.rad_transitions[trans_num]
            RADEX_intensity = (helpers.B_nu(nu=trans.nu0,T=Tex)- ext_background(trans.nu0))\
                              * (1-np.exp(-tau_nu))
            RADEX_flux = np.pi*RADEX_intensity*trans.line_profile.width_nu
            pyradex_flux = fluxes[trans_num]
            print('RADEX flux: {:g}; pyradex flux: {:g}'.format(RADEX_flux,pyradex_flux))
            pyradex_tau = test_nebula.tau_nu0[trans_num]
            print('RADEX tau: {:g}; pyradex tau: {:g}'.format(tau_nu,pyradex_tau))
            print('RADEX Tex: {:g} K; pyradex Tex: {:g} K'.format(Tex,test_nebula.Tex[trans_num]))
            assert np.isclose(RADEX_flux,pyradex_flux,atol=0,rtol=0.7)
            assert np.isclose(pyradex_tau,tau_nu,atol=0.01,rtol=0.1)
        print('\n')
Ejemplo n.º 2
0
    def compute_line_fluxes(self, solid_angle):
        '''Compute the observed spectra and total fluxes for each line. This
        requires that the radiative transfer has been solved. This method
        computes the attributes obs_line_fluxes (total observed line fluxes in W/m2)
        and obs_line_spectra (observed line spectra in W/m2/Hz).
        
        Parameters:
        ---------------
        solid_angle: float
            the solid angle of the source in [rad2]
        '''

        self.obs_line_fluxes = []
        self.obs_line_spectra = []
        for i, line in enumerate(self.emitting_molecule.rad_transitions):
            nu_array = line.line_profile.nu_array
            x1 = self.level_pop[line.low.number]
            x2 = self.level_pop[line.up.number]
            source_function = helpers.B_nu(T=self.Tex[i], nu=nu_array)
            tau_nu = line.tau_nu_array(N1=x1 * self.Ntot, N2=x2 * self.Ntot)
            line_flux_nu = self.geometry.compute_flux_nu(
                tau_nu=tau_nu,
                source_function=source_function,
                solid_angle=solid_angle)
            self.obs_line_spectra.append(line_flux_nu)  #W/m2/Hz
            line_flux = np.trapz(line_flux_nu,
                                 line.line_profile.nu_array)  #[W/m2]
            self.obs_line_fluxes.append(line_flux)
Ejemplo n.º 3
0
def test_compute_line_fluxes():
    n = thin_LTE_test_nebula.Ntot / (2 * r)
    tot_particles = n * 4 / 3 * r**3 * np.pi
    up_level_particles = np.array([
        tot_particles * expected_LTE_level_pop[trans.up.number]
        for trans in thin_LTE_test_nebula.emitting_molecule.rad_transitions
    ])
    A21 = [
        trans.A21
        for trans in thin_LTE_test_nebula.emitting_molecule.rad_transitions
    ]
    Delta_E = [
        trans.Delta_E
        for trans in thin_LTE_test_nebula.emitting_molecule.rad_transitions
    ]
    expected_LTE_fluxes_thin = up_level_particles * A21 * Delta_E / (
        4 * np.pi * r**2)
    assert np.allclose(thin_LTE_test_nebula.line_fluxes,
                       expected_LTE_fluxes_thin,
                       atol=0,
                       rtol=1e-2)
    thick_LTE_test_nebula.solve_radiative_transfer()
    #the higher transitions might not be optically thick, so just test the lowest transition:
    lowest_trans = thick_LTE_test_nebula.emitting_molecule.rad_transitions[0]
    expected_thick_LTE_flux_lowest_trans = np.pi*helpers.B_nu(nu=lowest_trans.nu0,T=Tkin)\
                                           * lowest_trans.line_profile.width_nu
    assert np.isclose(thick_LTE_test_nebula.line_fluxes[0],
                      expected_thick_LTE_flux_lowest_trans,
                      atol=0,
                      rtol=1e-2)
Ejemplo n.º 4
0
def test_CMB_background():
    test_nu = np.logspace(np.log10(1), np.log10(1000), 20) * constants.giga
    test_z = (0, 2)
    for z in test_z:
        CMB = helpers.generate_CMB_background(z=z)
        assert np.all(
            CMB(test_nu) == helpers.B_nu(nu=test_nu, T=2.73 * (1 + z)))
Ejemplo n.º 5
0
 def compute_line_fluxes(self):
     '''Compute the flux for each line. This requires that the radiative transfer
     has been solved'''
     self.line_fluxes = []
     for i, line in enumerate(self.emitting_molecule.rad_transitions):
         nu_array = line.line_profile.nu_array
         x1 = self.level_pop[line.low.number]
         x2 = self.level_pop[line.up.number]
         source_function = helpers.B_nu(T=self.Tex[i], nu=nu_array)
         tau_nu = line.tau_nu_array(N1=x1 * self.Ntot, N2=x2 * self.Ntot)
         line_flux_nu = self.geometry.compute_flux_nu(
             tau_nu=tau_nu, source_function=source_function)
         line_flux = np.trapz(line_flux_nu,
                              line.line_profile.nu_array)  #[W/m2]
         self.line_fluxes.append(line_flux)
Ejemplo n.º 6
0
def test_compute_line_fluxes():
    for geo,neb in nebulae.items():
        if 'RADEX' in geo or 'slab' in geo:
            continue
        Ntot = neb['thin_LTE'].Ntot
        if 'sphere' in geo:
            volume = 4/3*r**3*np.pi
            n = Ntot/(2*r)
        elif 'slab' in geo:
            volume = slab_surface*slab_depth
            n = Ntot/slab_depth
        tot_particles = n*volume
        thin_LTE_rad_transitions = neb['thin_LTE'].emitting_molecule.rad_transitions
        up_level_particles = np.array(
                              [tot_particles*expected_LTE_level_pop[trans.up.number]
                              for trans in thin_LTE_rad_transitions])
        A21 = np.array([trans.A21 for trans in thin_LTE_rad_transitions])
        Delta_E = np.array([trans.Delta_E for trans in thin_LTE_rad_transitions])
        energy_flux = up_level_particles*A21*Delta_E #W
        if 'sphere' in geo:
            expected_LTE_fluxes_thin = energy_flux/(4*np.pi*d**2)
        elif 'slab' in geo:
            #not isotropic, so I can't do the same thing as for sphere
            expected_LTE_fluxes_thin = energy_flux/(4*np.pi*slab_surface)\
                                        *get_solid_angle(geo)
        line_profile_nu0 = np.array([trans.line_profile.phi_nu(trans.nu0) for
                                     trans in thin_LTE_rad_transitions])
        expected_LTE_fluxes_nu_thin = expected_LTE_fluxes_thin*line_profile_nu0
        assert np.allclose(neb['thin_LTE'].obs_line_fluxes,expected_LTE_fluxes_thin,
                           atol=0,rtol=1e-2)
        line_fluxes_nu_thin = [np.max(fluxes_nu) for fluxes_nu in
                               neb['thin_LTE'].obs_line_spectra]
        assert np.allclose(line_fluxes_nu_thin,expected_LTE_fluxes_nu_thin,
                           atol=0,rtol=1e-2)
        #the higher transitions might not be optically thick, so just test the
        #lowest transition:
        lowest_trans = neb['thick_LTE'].emitting_molecule.rad_transitions[0]
        expected_thick_LTE_flux_nu = helpers.B_nu(nu=lowest_trans.nu0,T=Tkin)\
                                      *get_solid_angle(geo)
        expected_thick_LTE_flux = expected_thick_LTE_flux_nu\
                                       * lowest_trans.line_profile.width_nu
        assert np.isclose(neb['thick_LTE'].obs_line_fluxes[0],
                           expected_thick_LTE_flux,atol=0,rtol=1e-2)
Ejemplo n.º 7
0
def test_vs_RADEX():
    for filename, coll_ID in zip(filenames, collider_names):
        specie = filename[:-4]
        lamda_filepath = os.path.join(here, filename)
        params = zip(Ntot_values, width_v_values, Tkin_values,
                     coll_partner_densities_values, test_trans)
        for i, (Ntot, width_v, Tkin, collp_dens,
                trans_num) in enumerate(params):
            coll_partner_densities = {coll_ID: collp_dens}
            for geo in geometries:
                Omega = get_solid_angle(geo)
                print('looking at {:s}, {:s} (case {:d})'.format(
                    specie, geo, i))
                test_nebula = nebula.Nebula(
                    datafilepath=lamda_filepath,
                    geometry=geo,
                    ext_background=ext_background,
                    Tkin=Tkin,
                    coll_partner_densities=coll_partner_densities,
                    Ntot=Ntot,
                    line_profile=line_profile,
                    width_v=width_v)
                test_nebula.solve_radiative_transfer()
                test_nebula.compute_line_fluxes(solid_angle=Omega)
                trans = test_nebula.emitting_molecule.rad_transitions[
                    trans_num]
                if 'sphere' in geo:
                    radex = RADEX['sphere']
                elif 'slab' in geo:
                    radex = RADEX['slab']
                Tex = radex[specie]['Tex'][i]
                tau_nu = radex[specie]['tau'][i]
                #see radex_output_readme.txt or RADEX manual for explanation of the
                #follwing formula
                RADEX_intensity = (helpers.B_nu(nu=trans.nu0,T=Tex)
                                                   -ext_background(trans.nu0))\
                                  * (1-np.exp(-tau_nu))
                RADEX_flux = RADEX_intensity * trans.line_profile.width_nu * Omega
                pyradex_flux = test_nebula.obs_line_fluxes[trans_num]
                print('RADEX flux: {:g}; pyradex flux: {:g}'.format(
                    RADEX_flux, pyradex_flux))
                pyradex_tau = test_nebula.tau_nu0[trans_num]
                pyradex_Tex = test_nebula.Tex[trans_num]
                print('RADEX tau: {:g}; pyradex tau: {:g}'.format(
                    tau_nu, pyradex_tau))
                print('RADEX Tex: {:g} K; pyradex Tex: {:g} K'.format(
                    Tex, pyradex_Tex))
                if 'RADEX' in geo:
                    atol_flux = 0
                    rtol_flux = 0.3
                    atol_tau = 0.1
                    rtol_tau = 0.1
                    atol_Tex = 1
                    rtol_Tex = 0.2
                else:
                    atol_flux = 0
                    rtol_flux = 0.7
                    atol_tau = 0.1
                    rtol_tau = 0.5
                    atol_Tex = 1
                    rtol_Tex = 0.5
                if pyradex_tau < 0:
                    assert tau_nu < 0
                    assert Tex < 0
                    assert pyradex_Tex < 0
                else:
                    assert np.isclose(pyradex_tau,
                                      tau_nu,
                                      atol=atol_tau,
                                      rtol=rtol_tau)
                    assert np.isclose(RADEX_flux,
                                      pyradex_flux,
                                      atol=atol_flux,
                                      rtol=rtol_flux)
                    assert np.isclose(Tex,
                                      pyradex_Tex,
                                      atol=atol_Tex,
                                      rtol=rtol_Tex)
            print('\n')
        print('\n')
Ejemplo n.º 8
0
test_molecule = molecule.Molecule.from_LAMDA_datafile(
    data_filepath=lamda_filepath)
Tkin = 100
expected_LTE_level_pop = test_molecule.LTE_level_pop(Tkin)
coll_partner_densities_default = {
    'para-H2': 1e1 / constants.centi**3,
    'ortho-H2': 1e1 / constants.centi**3
}
coll_partner_densities_large = {
    'para-H2': 1e10 / constants.centi**3,
    'ortho-H2': 1e10 / constants.centi**3
}
coll_partner_densities_0 = {'para-H2': 0, 'ortho-H2': 0}
Jbar_lines_0 = np.zeros(test_molecule.n_rad_transitions)
Jbar_lines_B_nu = [
    helpers.B_nu(nu=trans.nu0, T=Tkin)
    for trans in test_molecule.rad_transitions
]
beta_lines_thin = np.ones(test_molecule.n_rad_transitions)
I_ext_lines_0 = np.zeros(test_molecule.n_rad_transitions)


def get_level_pops(coll_partner_densities, Jbar_lines, beta_lines,
                   I_ext_lines):
    kwargs = {
        'molecule': test_molecule,
        'coll_partner_densities': coll_partner_densities,
        'Tkin': Tkin
    }
    rate_equations_std = nebula.RateEquations(mode='std', **kwargs)
    level_pop_std = rate_equations_std.solve(Jbar_lines=Jbar_lines)
Ejemplo n.º 9
0
from scipy import constants
import numpy as np

here = os.path.dirname(os.path.abspath(__file__))
lamda_filepath = os.path.join(here,'co.dat')

test_molecule = molecule.Molecule.from_LAMDA_datafile(datafilepath=lamda_filepath)
Tkin = 100
expected_LTE_level_pop = test_molecule.LTE_level_pop(Tkin)
coll_partner_densities_default = {'para-H2':1e1/constants.centi**3,
                                  'ortho-H2':1e1/constants.centi**3}
coll_partner_densities_large = {'para-H2':1e10/constants.centi**3,
                                'ortho-H2':1e10/constants.centi**3}                                  
coll_partner_densities_0 = {'para-H2':0,'ortho-H2':0}
Jbar_lines_0 = np.zeros(test_molecule.n_rad_transitions)
Jbar_lines_B_nu = [helpers.B_nu(nu=trans.nu0,T=Tkin) for trans in
                   test_molecule.rad_transitions]
beta_lines_thin = np.ones(test_molecule.n_rad_transitions)
I_ext_lines_0 = np.zeros(test_molecule.n_rad_transitions)

def get_level_pops(coll_partner_densities,Jbar_lines,beta_lines,I_ext_lines):
    kwargs = {'molecule':test_molecule,
              'coll_partner_densities':coll_partner_densities,'Tkin':Tkin}
    rate_equations_std = nebula.RateEquations(mode='std',**kwargs)
    level_pop_std = rate_equations_std.solve(Jbar_lines=Jbar_lines)
    rate_equations_ALI = nebula.RateEquations(mode='ALI',**kwargs)
    level_pop_ALI = rate_equations_ALI.solve(
                          beta_lines=beta_lines,I_ext_lines=I_ext_lines)
    return level_pop_std,level_pop_ALI

def test_compute_level_populations_no_excitation():