def supernova_rate(self): """ Calculates the SN rate at time t by integrating over mass m """ # initialize sn_rate_list = [] dm = 0.01 prev_t = 1e-3 # define time array time = self.sfh[:, 0] time = time[time < self.tend] for t in time: # need to clear the sn_rates as we don't want them adding up sn_rate = 0.0 dsn_rate = 0.0 if t < 0.049: m = lookup_fn(t_lifetime, "lifetime_high_metals", t)[0] else: m = 9.0 while m < 40.0: if m > 10.0: dm = 0.5 sn_rate += f.initial_mass_function(m, self.imf_type) * dm m += dm r_sn = self.sfr(t) * sn_rate # units in N per Gyr dt = t - prev_t prev_t = t sn_rate_list.append(r_sn) return np.array(sn_rate_list)
def test_minimum_mass_lookup_highZ(self): t_lifetime = Table(rows=lifetime, names=('mass', 'lifetime_low_metals', 'lifetime_high_metals'), meta={'name': 'Lifetime'}) minimum_mass = lookup_fn(t_lifetime, 'lifetime_high_metals', 1.75)['mass'] assert minimum_mass == 2.0
def mass_integral(choice, reduce_sn, t, metallicity, sfr_lookup, z_lookup, imf): ''' This function does the mass integral for: - e(t): ejected gas mass em - ez(t): ejected metal mass ezm - ed(t): ejected dust mass edm - Zdiff and SFR diff are also calculated ie at t-taum In: -- choice: array of dust source choices -- t: time in Gyrs -- metallicity: metal mass fraction Mz/Mg -- sfr_lookup: SFR array (time, SFR) based on previous time steps -- z_lookup: metallicity array (time, Z) based on previous time steps -- imf: choice of IMF ''' mu = t_lifetime[-1]['mass'] dm = 0.01 t_0 = 1e-3 ezm = 0. edm = 0. em = 0. # we pull out mass corresponding to age of system # to get lower limit of integral # to make taum lookup faster m = lookup_fn(t_lifetime,'lifetime_low_metals',t)['mass'] lifetime_cols = {'low_metals':1, 'high_metals':2} if metallicity < 0.019: col_choice = lifetime_cols['low_metals'] else: col_choice = lifetime_cols['high_metals'] while m <= mu: if m > 10.: dm = 0.5 # pull out lifetime of star of mass m so we can # calculate SFR when star was born which is t-lifetime taum = lookup_taum(m,col_choice) tdiff = t - taum # only release material after stars die if tdiff <= 0: ezm = 0 edm = 0 em = 0 else: # get nearest Z which corresponds to Z at time=t-taum zdiff = find_nearest(z_lookup,tdiff)[1] sfrdiff = find_nearest(sfr_lookup,tdiff)[1] ezm += ejected_metal_mass(m, sfrdiff, zdiff, metallicity, imf) * dm em += ejected_gas_mass(m, sfrdiff, imf) * dm edm += ejected_dust_mass(choice, reduce_sn, m, sfrdiff, zdiff, metallicity, imf) * dm m += dm return em, ezm, edm
def mass_integral(choice, delta_lims, reduce_sn, t, metallicity, sfr_lookup, z_lookup, oxy_lookup, imf): ''' This function does the mass integral for: - e(t): ejected gas mass em - ez(t): ejected metal mass ezm - ed(t): ejected dust mass edm - Zdiff and SFR diff are also calculated ie at t-taum (when stars that are dying now were born) In: -- choice: array of dust source choices -- delta_lims: efficiency of fresh metals condensing into dust, set by user -- t: time in Gyrs -- metallicity: metal mass fraction Mz/Mg -- sfr_lookup: SFR array (time, SFR) based on previous time steps -- z_lookup: metallicity array (time, Z) based on previous time steps -- imf: choice of IMF ''' mu = t_lifetime[-1]['mass'] t_0 = 1e-3 ezm = 0. eom = 0. edm = 0. em = 0. lifetime_cols = {'low_metals': 1, 'high_metals': 2} if metallicity <= 0.008: # in between Z=0.001 and Z=0.02 files from Schaller et al 1992 # get the correct lower mass of integral based on age of system m_min = lookup_fn(t_lifetime, 'lifetime_low_metals', t)['mass'] # define column choice to speed up taum fn below col_choice = lifetime_cols['low_metals'] else: m_min = lookup_fn(t_lifetime, 'lifetime_high_metals', t)['mass'] # define column choice to speed up taum fn below col_choice = lifetime_cols['high_metals'] # checks that m_min does not exceed mu if (m_min >= mu): m_min = mu # increasing the number of steps increases the # resolution in the mass integral steps = 500 m = m_min dlogm = 0 logmnew = np.log10(m) + dlogm dm = 10**(logmnew) - m dlogm = (np.log10(mu) - np.log10(m_min)) / steps count = 0 z_near = lambda td: z_lookup[(abs(z_lookup[:, 0] - td)).argmin()] oxy_near = lambda td: oxy_lookup[(abs(oxy_lookup[:, 0] - td)).argmin()] sfr_near = lambda td: sfr_lookup[(abs(sfr_lookup[:, 0] - td)).argmin()] # loop over the full mass range while count < steps: count += 1 logmnew = np.log10(m) + dlogm dm = 10.0**(logmnew) - m mmid = 10.0**((logmnew + np.log10(m)) / 2.0) # pull out lifetime of star of mass m so we can # calculate SFR when star was born which is t-lifetime taum = lookup_taum(mmid, col_choice) tdiff = t - taum # only release material after stars die if tdiff <= 0: ezm = 0 eom = 0 edm = 0 em = 0 else: # get nearest Z and SFR which corresponds to Z and SFR at time=t-taum zdiff = z_near(tdiff)[1] # find_nearest(z_lookup,tdiff)[1] oxydiff = oxy_near(tdiff)[1] # find_nearest(oxy_lookup,tdiff)[1] sfrdiff = sfr_near(tdiff)[1] # find_nearest(sfr_lookup,tdiff)[1] ezm += ejected_metal_mass(mmid, sfrdiff, zdiff, metallicity, imf) * dm eom += ejected_oxygen_mass(mmid, sfrdiff, oxydiff, metallicity, imf) * dm em += ejected_gas_mass(mmid, sfrdiff, imf) * dm edm += ejected_dust_mass(choice, delta_lims, reduce_sn, mmid, sfrdiff, zdiff, metallicity, imf) * dm #Calculate the next mass value mnew = 10**(logmnew) m = mnew return em, ezm, eom, edm
def mass_integral(choice, reduce_sn, t, metallicity, sfr_lookup, z_lookup, imf): ''' This function does the mass integral for: - e(t): ejected gas mass em - ez(t): ejected metal mass ezm - ed(t): ejected dust mass edm - Zdiff and SFR diff are also calculated ie at t-taum (when stars that are dying now were born) In: -- choice: array of dust source choices -- t: time in Gyrs -- metallicity: metal mass fraction Mz/Mg -- sfr_lookup: SFR array (time, SFR) based on previous time steps -- z_lookup: metallicity array (time, Z) based on previous time steps -- imf: choice of IMF ''' mu = t_lifetime[-1]['mass'] t_0 = 1e-3 ezm = 0. edm = 0. em = 0. lifetime_cols = {'low_metals':1, 'high_metals':2} if metallicity <= 0.008: # in between Z=0.001 and Z=0.02 files from Schaller et al 1992 # get the correct lower mass of integral based on age of system m_min = lookup_fn(t_lifetime,'lifetime_low_metals',t)['mass'] # define column choice to speed up taum fn below col_choice = lifetime_cols['low_metals'] else: m_min = lookup_fn(t_lifetime,'lifetime_high_metals',t)['mass'] # define column choice to speed up taum fn below col_choice = lifetime_cols['high_metals'] # checks that m_min does not exceed mu if(m_min >= mu): m_min = mu # increasing the number of steps increases the # resolution in the mass integral steps = 500 m = m_min dlogm = 0 logmnew = np.log10(m) + dlogm dm = 10**(logmnew)- m dlogm = (np.log10(mu)-np.log10(m_min))/steps count = 0 z_near = lambda td : z_lookup[(abs(z_lookup[:,0]-td)).argmin()] sfr_near = lambda td : sfr_lookup[(abs(sfr_lookup[:,0]-td)).argmin()] # loop over the full mass range while count < steps: count += 1 logmnew = np.log10(m) + dlogm dm = 10.0**(logmnew) - m mmid = 10.0**((logmnew+np.log10(m))/2.0) # pull out lifetime of star of mass m so we can # calculate SFR when star was born which is t-lifetime taum = lookup_taum(mmid,col_choice) tdiff = t - taum # only release material after stars die if tdiff <= 0: ezm = 0 edm = 0 em = 0 else: # get nearest Z and SFR which corresponds to Z and SFR at time=t-taum zdiff = z_near(tdiff)[1] # find_nearest(z_lookup,tdiff)[1] sfrdiff = sfr_near(tdiff)[1] # find_nearest(sfr_lookup,tdiff)[1] ezm += ejected_metal_mass(mmid, sfrdiff, zdiff, metallicity, imf) * dm em += ejected_gas_mass(mmid, sfrdiff, imf) * dm edm += ejected_dust_mass(choice, reduce_sn, mmid, sfrdiff, zdiff, metallicity, imf) * dm #Calculate the next mass value mnew = 10**(logmnew) m = mnew return em, ezm, edm
def test_minimum_mass_lookup_highZ(self): t_lifetime = Table(rows=lifetime, names=('mass','lifetime_low_metals','lifetime_high_metals'),meta={'name': 'Lifetime'}) minimum_mass = lookup_fn(t_lifetime,'lifetime_high_metals',1.75)['mass'] assert minimum_mass == 2.0