예제 #1
0
def DIG_source_add(m,reg,df_nu):

    print("--------------------------------\n")
    print("Adding DIG to Source List in source_creation\n")
    print("--------------------------------\n")

    print ("Getting specific energy dumped in each grid cell")

    try:
        rtout = cfg.model.outputfile + '.sed'
        try: 
            grid_properties = np.load(cfg.model.PD_output_dir+"/grid_physical_properties."+cfg.model.snapnum_str+'_galaxy'+cfg.model.galaxy_num_str+".npz")
        except:
            grid_properties = np.load(cfg.model.PD_output_dir+"/grid_physical_properties."+cfg.model.snapnum_str+".npz")

        cell_info = np.load(cfg.model.PD_output_dir+"/cell_info."+cfg.model.snapnum_str+"_"+cfg.model.galaxy_num_str+".npz")
    except:
        print ("ERROR: Can't proceed with DIG nebular emission calculation. Code is unable to find the required files.") 
        print ("Make sure you have the rtout.sed, grid_physical_properties.npz and cell_info.npz for the corresponding galaxy.")

        return 

    m_out = ModelOutput(rtout)
    oct = m_out.get_quantities()
    grid = oct
    order = find_order(grid.refined)
    refined = grid.refined[order]
    quantities = {}
    for field in grid.quantities:
        quantities[('gas', field)] = grid.quantities[field][0][order][~refined]

    cell_width = cell_info["fw1"][:,0]
    mass = (quantities['gas','density']*units.g/units.cm**3).value * (cell_width**3)
    met = grid_properties["grid_gas_metallicity"]
    specific_energy = (quantities['gas','specific_energy']*units.erg/units.s/units.g).value
    specific_energy = (specific_energy * mass) # in ergs/s

    # Black 1987 curve has a integrated ergs/s/cm2 of 0.0278 so the factor we need to multiply it by is given by this value
    factor = specific_energy/(cell_width**2)/(0.0278) 

    mask1 = np.where(mass != 0 )[0]
    mask = np.where((mass != 0 ) & (factor >= cfg.par.DIG_min_factor))[0] # Masking out all grid cells that have no gas mass and where the specific emergy is too low
    print (len(factor), len(mask1), len(mask))
    
    factor = factor[mask]
    cell_width = cell_width[mask]
    cell_x = (cell_info["xmax"] - cell_info["xmin"])[mask]
    cell_y = (cell_info["ymax"] - cell_info["ymin"])[mask]
    cell_z = (cell_info["zmax"] - cell_info["zmin"])[mask]
    pos = np.vstack([cell_x, cell_y, cell_z]).transpose()

    met = grid_properties["grid_gas_metallicity"][:, mask]
    met = np.transpose(met)
    
    fnu_arr = sg.get_dig_seds(factor, cell_width, met)
    
    dat = np.load(cfg.par.pd_source_dir + "/powderday/nebular_emission/data/black_1987.npz")
    spec_lam = dat["lam"]
    nu = 1.e8 * constants.c.cgs.value / spec_lam 

    for i in range(len(factor)):
        fnu = fnu_arr[i,:]
        nu, fnu = wavelength_compress(nu,fnu,df_nu)
        
        nu = nu[::-1]
        fnu = fnu[::-1]
        
        lum = np.absolute(np.trapz(fnu,x=nu))*constants.L_sun.cgs.value
        
        source = m.add_point_source()
        source.luminosity = lum # [ergs/s]
        source.spectrum = (nu,fnu)
        source.position = pos[i] # [cm]
예제 #2
0
def DIG_source_add(m, reg, df_nu, boost):

    print("--------------------------------")
    print("Adding DIG to Source List in source_creation")
    print("--------------------------------")

    print("Getting the specific energy dumped in each grid cell")

    try:
        rtout = cfg.model.outputfile + '_DIG_energy_dumped.sed'
        try:
            grid_properties = np.load(cfg.model.PD_output_dir +
                                      "/grid_physical_properties." +
                                      cfg.model.snapnum_str + '_galaxy' +
                                      cfg.model.galaxy_num_str + ".npz")
        except:
            grid_properties = np.load(cfg.model.PD_output_dir +
                                      "/grid_physical_properties." +
                                      cfg.model.snapnum_str + ".npz")

        cell_info = np.load(cfg.model.PD_output_dir + "/cell_info." +
                            cfg.model.snapnum_str + "_" +
                            cfg.model.galaxy_num_str + ".npz")
    except:
        print(
            "ERROR: Can't proceed with DIG nebular emission calculation. Code is unable to find the required files."
        )
        print(
            "Make sure you have the rtout.sed, grid_physical_properties.npz and cell_info.npz for the corresponding galaxy."
        )

        return

    m_out = ModelOutput(rtout)
    oct = m_out.get_quantities()
    grid = oct
    order = find_order(grid.refined)
    refined = grid.refined[order]
    quantities = {}
    for field in grid.quantities:
        quantities[('gas', field)] = grid.quantities[field][0][order][~refined]

    cell_width = cell_info["fw1"][:, 0]
    mass = (quantities['gas', 'density'] * units.g /
            units.cm**3).value * (cell_width**3)
    specific_energy = (quantities['gas', 'specific_energy'] * units.erg /
                       units.s / units.g).value
    specific_energy = (specific_energy * mass)  # in ergs/s

    mask = np.where(
        mass != 0)[0]  # Masking out all grid cells that have no gas mass
    pos = cell_info["fc1"][mask] - boost
    cell_width = cell_width[mask]
    met = grid_properties["grid_gas_metallicity"][:, mask]
    met = np.transpose(met)
    specific_energy = specific_energy[mask]

    mask = []
    logU_arr = []
    lam_arr = []
    fnu_arr = []

    for i in range(len(cell_width)):

        # Getting shape of the incident spectrum by taking a distance weighted average of the CLOUDY output spectrum of nearby young stars.
        sed_file_name = cfg.model.PD_output_dir + "neb_seds_galaxy_" + cfg.model.galaxy_num_str + ".npz"
        lam, fnu = get_DIG_sed_shape(
            pos[i], cell_width[i], sed_file=sed_file_name
        )  # Returns input SED shape, lam in Angstrom, fnu in Lsun/Hz

        # If the gas cell has no young stars within a specified distance (stars_max_dist) then skip it.
        if len(np.atleast_1d(fnu)) == 1:
            continue

        # Calulating the ionization parameter by extrapolating the specfic energy beyind the lyman limit
        # using the SED shape calculated above.
        logU = get_DIG_logU(lam, fnu, specific_energy[i], cell_width[i])

        lam_arr.append(lam)
        fnu_arr.append(fnu)

        # Only cells with ionization parameter greater than the parameter DIG_min_logU are considered
        # for nebular emission calculation. This is done so as to speed up the calculation by ignoring
        # the cells that do not have enough energy to prduce any substantial emission
        if logU > cfg.par.DIG_min_logU:
            mask.append(i)
            lam_arr.append(lam)
            fnu_arr.append(fnu)
            logU_arr.append(logU)

    cell_width = cell_width[mask]
    met = met[mask]
    lam_arr = np.array(lam_arr)
    fnu_arr = np.array(fnu_arr)
    logU = np.array(logU_arr)
    pos = pos[mask]

    if (len(mask)) == 0:
        print(
            "No gas particles fit the criteria for calculating DIG. Skipping DIG calculation"
        )
        return

    print(
        "----------------------------------------------------------------------------------"
    )
    print("Calculating nebular emission from Diffused Ionized Gas for " +
          str(len(mask)) + " gas cells")
    print(
        "----------------------------------------------------------------------------------"
    )

    fnu_arr_neb = sg.get_dig_seds(lam_arr, fnu_arr, logU, cell_width, met)

    nu = 1.e8 * constants.c.cgs.value / lam

    for i in range(len(logU)):
        fnu = fnu_arr_neb[i, :]
        nu, fnu = wavelength_compress(nu, fnu, df_nu)

        nu = nu[::-1]
        fnu = fnu[::-1]

        lum = np.absolute(np.trapz(fnu, x=nu)) * constants.L_sun.cgs.value

        source = m.add_point_source()
        source.luminosity = lum  # [ergs/s]
        source.spectrum = (nu[::-1], fnu[::-1])
        source.position = pos[i]  # [cm]