Example #1
0
def calc_emline(stars_list):
    print('[SED_gen/calc_emline]: Calculating Emission Line Fluxes')
    #this function is awful and redundant.  itloops over just the new
    #stars in the box and calculates the SEDs for the ones smaller
    #than cfg.par.HII_max_age.  its a bit wasteful since we already
    #calculate these SEDs, but its difficult to get the file to save
    #in a nice format without incl
    global sp
    if sp is None:
        sp = fsps.StellarPopulation()

    #set up arrays
    #first how many young stars are there?

    newstars_idx = []
    for counter, star in enumerate(stars_list):
        if star.age <= cfg.par.HII_max_age:
            newstars_idx.append(counter)
    num_newstars = len(newstars_idx)

    #set up a dummy sps model just to get number of wavelengths
    sp.params["tage"] = stars_list[0].age
    sp.params["zmet"] = stars_list[0].fsps_zmet
    sp.params["add_neb_emission"] = True
    wav, spec = sp.get_spectrum()
    n_emlines = len(sp.emline_wavelengths)

    #now set up the actual arrays
    master_emline_wavelength = np.zeros([n_emlines])
    master_emline_lum = np.zeros([num_newstars, n_emlines])

    #loop through the newstars now and save the emlines
    for counter, i in enumerate(newstars_idx):
        num_HII_clusters = int(
            np.floor((stars_list[i].mass / constants.M_sun.cgs.value) /
                     (cfg.par.stellar_cluster_mass)))

        #first we calculate the spectrum without lines on to get logU
        sp.params["tage"] = stars_list[i].age
        sp.params["imf_type"] = cfg.par.imf_type
        sp.params["pagb"] = cfg.par.pagb
        sp.params["sfh"] = 0
        sp.params["zmet"] = stars_list[i].fsps_zmet
        sp.params["add_neb_emission"] = False
        sp.params["add_agb_dust_model"] = cfg.par.add_agb_dust_model
        sp.params['gas_logu'] = cfg.par.gas_logu
        if cfg.par.FORCE_gas_logz == False:
            sp.params['gas_logz'] = np.log10(stars_list[i].metals /
                                             cfg.par.solar)
        else:
            sp.params['gas_logz'] = cfg.par.gas_logz

        if cfg.par.CF_on == True:
            sp.params["dust_type"] = 0
            sp.params["dust1"] = 1
            sp.params["dust2"] = 0
            sp.params["dust_tesc"] = tesc_age

        #sp = fsps.StellarPopulation(tage=stars_list[i].age,imf_type=2,sfh=0,zmet=stars_list[i].fsps_zmet)
        spec = sp.get_spectrum(tage=stars_list[i].age,
                               zmet=stars_list[i].fsps_zmet)
        num_HII_clusters = int(
            np.floor((stars_list[i].mass / constants.M_sun.cgs.value) /
                     (cfg.par.stellar_cluster_mass)))
        neb_file_output = False

        sp.params["add_neb_emission"] = False
        spec = sp.get_spectrum(tage=stars_list[i].age,
                               zmet=stars_list[i].fsps_zmet)

        #now we know logU, so recalculate the lines
        if cfg.par.FORCE_gas_logu:
            LogU = cfg.par.gas_logu
        else:
            LogQ, Rin, LogU = calc_LogU(1.e8 * constants.c.cgs.value / spec[0],
                                        spec[1] * constants.L_sun.cgs.value,
                                        cfg.par.HII_nh,
                                        cfg.par.HII_T,
                                        mstar=cfg.par.stellar_cluster_mass)
        sp.params['gas_logu'] = LogU
        sp.params["add_neb_emission"] = True
        spec = sp.get_spectrum(tage=stars_list[i].age,
                               zmet=stars_list[i].fsps_zmet)
        f = spec[1] * num_HII_clusters

        emline_luminosity = sp.emline_luminosity * num_HII_clusters
        emline_wavelength = sp.emline_wavelengths

        #the stellar population returns the calculation in units of Lsun/1 Msun: https://github.com/dfm/python-fsps/issues/117#issuecomment-546513619
        master_emline_lum[counter, :] = emline_luminosity * (
            (stars_list[i].mass * u.g).to(u.Msun).value)
        if counter == 0:
            master_emline_wavelength = emline_wavelength
            #set up the emline output file as new, and insert the wavelengths
            dump_emline(master_emline_wavelength, None, append=False)

    #write the remainder of the emline file
    dump_emline(master_emline_wavelength, master_emline_lum, append=True)
Example #2
0
def newstars_gen(stars_list):
    global sp
    if sp is None:
        sp = fsps.StellarPopulation()

    #the newstars (particle type 4; so, for cosmological runs, this is all
    #stars) are calculated in a separate function with just one argument so that it is can be fed
    #into pool.map for multithreading.
    #sp = fsps.StellarPopulation()
    sp.params["tage"] = stars_list[0].age
    sp.params["imf_type"] = cfg.par.imf_type
    sp.params["pagb"] = cfg.par.pagb
    sp.params["sfh"] = 0
    sp.params["zmet"] = stars_list[0].fsps_zmet
    sp.params["add_neb_emission"] = False
    sp.params["add_agb_dust_model"] = cfg.par.add_agb_dust_model
    sp.params['gas_logu'] = cfg.par.gas_logu

    if cfg.par.FORCE_gas_logz == False:
        sp.params['gas_logz'] = np.log10(stars_list[0].metals / cfg.par.solar)
    else:
        sp.params['gas_logz'] = cfg.par.gas_logz

    #first figure out how many wavelengths there are

    spec = sp.get_spectrum(tage=stars_list[0].age,
                           zmet=stars_list[0].fsps_zmet)
    nu = 1.e8 * constants.c.cgs.value / spec[0]

    nlam = len(nu)

    stellar_nu = np.zeros([nlam])
    stellar_fnu = np.zeros([len(stars_list), nlam])

    minage = 13  #Gyr
    for i in range(len(stars_list)):
        if stars_list[i].age < minage:
            minage = stars_list[i].age

    tesc_age = np.log10((minage + cfg.par.birth_cloud_clearing_age) * 1.e9)

    # Get the number of ionizing photons from SED

    #calculate the SEDs for new stars
    for i in range(len(stars_list)):

        sp.params["tage"] = stars_list[i].age
        sp.params["imf_type"] = cfg.par.imf_type
        sp.params["pagb"] = cfg.par.pagb
        sp.params["sfh"] = 0
        sp.params["zmet"] = stars_list[i].fsps_zmet
        sp.params["add_neb_emission"] = False
        sp.params["add_agb_dust_model"] = cfg.par.add_agb_dust_model

        if cfg.par.FORCE_gas_logz == False:
            LogZ = np.log10(stars_list[i].metals / cfg.par.solar)
        else:
            LogZ = cfg.par.gas_logz

        if cfg.par.CF_on == True:
            sp.params["dust_type"] = 0
            sp.params["dust1"] = 1
            sp.params["dust2"] = 0
            sp.params["dust_tesc"] = tesc_age

        #sp = fsps.StellarPopulation(tage=stars_list[i].age,imf_type=2,sfh=0,zmet=stars_list[i].fsps_zmet)
        spec = sp.get_spectrum(tage=stars_list[i].age,
                               zmet=stars_list[i].fsps_zmet)
        f = spec[1]

        #Only including particles below the maximum age limit for calulating nebular emission
        if cfg.par.add_neb_emission and stars_list[
                i].age <= cfg.par.HII_max_age:

            num_HII_clusters = int(
                np.floor((stars_list[i].mass / constants.M_sun.cgs.value) /
                         (cfg.par.stellar_cluster_mass)))
            f = np.zeros(nlam)
            neb_file_output = cfg.par.neb_file_output

            sp.params["add_neb_emission"] = False
            spec = sp.get_spectrum(tage=stars_list[i].age,
                                   zmet=stars_list[i].fsps_zmet)

            if cfg.par.FORCE_gas_logu:
                alpha = 2.5e-13 * ((cfg.par.HII_T / (10**4))**(-0.85))
                LogU = cfg.par.gas_logu
                LogQ = np.log10((10**(3 * LogU)) *
                                (36 * np.pi * (constants.c.cgs.value**3)) /
                                ((alpha**2) * cfg.par.HII_nh))
                Rin = ((3 * (10**LogQ)) /
                       (4 * np.pi * (cfg.par.HII_nh**2) * alpha))**(1. / 3.)
            else:
                LogQ, Rin, LogU = calc_LogU(
                    1.e8 * constants.c.cgs.value / spec[0],
                    spec[1] * constants.L_sun.cgs.value,
                    cfg.par.HII_nh,
                    cfg.par.HII_T,
                    mstar=cfg.par.stellar_cluster_mass)

            if cfg.par.FORCE_logq:
                LogQ = cfg.par.source_logq

            if cfg.par.FORCE_inner_radius:
                Rin = cfg.par.inner_radius

            if neb_file_output:
                logu_diagnostic(LogQ,
                                Rin,
                                LogU,
                                cfg.par.stellar_cluster_mass,
                                stars_list[i].age,
                                stars_list[i].fsps_zmet,
                                append=True)
                neb_file_output = False

            sp.params['gas_logu'] = LogU
            sp.params['gas_logz'] = LogZ
            sp.params["add_neb_emission"] = True
            if cfg.par.use_cloudy_tables:
                lam_neb, spec_neb = sp.get_spectrum(
                    tage=stars_list[i].age, zmet=stars_list[i].fsps_zmet)
            else:
                try:
                    # Calculating ionizing photons again but for 1 Msun in order to scale the output for FSPS
                    LogQ_1, Rin_1, LogU_1 = calc_LogU(
                        1.e8 * constants.c.cgs.value / spec[0],
                        spec[1] * constants.L_sun.cgs.value, cfg.par.HII_nh,
                        cfg.par.HII_T)
                    spec_neb = get_nebular(spec[0],
                                           spec[1],
                                           cfg.par.HII_nh,
                                           LogQ,
                                           Rin,
                                           LogU,
                                           LogZ,
                                           LogQ_1,
                                           abund=cfg.par.neb_abund,
                                           useq=cfg.par.use_Q,
                                           clean_up=cfg.par.cloudy_cleanup)
                except ValueError as err:
                    lam_neb, spec_neb = sp.get_spectrum(
                        tage=stars_list[i].age, zmet=stars_list[i].fsps_zmet)

            f = spec_neb * num_HII_clusters

        stellar_nu[:] = 1.e8 * constants.c.cgs.value / spec[0]
        stellar_fnu[i, :] = f

    return stellar_fnu