def _StarformingEvol(self): ''' Evolve the star-forming galaxy population. This involves evolving their stellar mass and star formation rates while quenching some of them to match the quiescent fraction, fQ(M*, z), simultaneously. ''' for nsnap_d in self.descendant_dict.keys(): allwill = self.descendant_dict[str(nsnap_d)].will.copy() allsucc = self.descendant_dict[str(nsnap_d)].succession.copy() anc_sfr_class = self.ancestor.sfr_class.copy() q_ancestors = np.where( anc_sfr_class[allwill] == 'quiescent')[0] # Q ancestors sf_ancestors = np.where( anc_sfr_class[allwill] == 'star-forming')[0] # SF ancestors # star-formation duty cycle parameters (takes a long time ~15 sec) if not self.quiet: dutycycle_time = time.time() self.dutycycle_prop = sfr_evol.dutycycle_param( len(sf_ancestors), dutycycle_prop=self.evol_prop['sfr']['dutycycle']) self.dutycycle_prop['delta_sfr'] = self.ancestor.delta_sfr[ allwill[sf_ancestors]].copy() if not self.quiet: print 'SFR dutycycle properties take ', time.time( ) - dutycycle_time, ' to generate' logsfr, t_quench = self._Evol_MshamSFR(nsnap_d, allwill, sf_ancestors, q_ancestors) self.descendant_dict[str(nsnap_d)].sfr[ allsucc[sf_ancestors]] = logsfr self.descendant_dict[str(nsnap_d)].ssfr[allsucc[sf_ancestors]] = \ self.descendant_dict[str(nsnap_d)].sfr[allsucc[sf_ancestors]] - \ self.descendant_dict[str(nsnap_d)].mass[allsucc[sf_ancestors]] is_qing = np.where( t_quench < self.descendant_dict[str(nsnap_d)].t_cosmic) is_notqing = np.where( t_quench >= self.descendant_dict[str(nsnap_d)].t_cosmic) self.descendant_dict[str(nsnap_d)].sfr_class[allsucc[sf_ancestors[is_qing]]] = \ 'quiescent' self.descendant_dict[str(nsnap_d)].sfr_class[allsucc[sf_ancestors[is_notqing]]] = \ 'star-forming' self.descendant_dict[str(nsnap_d)].t_quench[allsucc[ sf_ancestors[is_qing]]] = t_quench[is_qing] return None
def _StarformingEvol(self): ''' Evolve the star-forming galaxy population. This involves evolving their stellar mass and star formation rates while quenching some of them to match the quiescent fraction, fQ(M*, z), simultaneously. ''' for nsnap_d in self.descendant_dict.keys(): allwill = self.descendant_dict[str(nsnap_d)].will.copy() allsucc = self.descendant_dict[str(nsnap_d)].succession.copy() anc_sfr_class = self.ancestor.sfr_class.copy() q_ancestors = np.where(anc_sfr_class[allwill] == 'quiescent')[0] # Q ancestors sf_ancestors = np.where(anc_sfr_class[allwill] == 'star-forming')[0] # SF ancestors # star-formation duty cycle parameters (takes a long time ~15 sec) if not self.quiet: dutycycle_time = time.time() self.dutycycle_prop = sfr_evol.dutycycle_param( len(sf_ancestors), dutycycle_prop=self.evol_prop['sfr']['dutycycle']) self.dutycycle_prop['delta_sfr'] = self.ancestor.delta_sfr[allwill[sf_ancestors]].copy() if not self.quiet: print 'SFR dutycycle properties take ', time.time() - dutycycle_time, ' to generate' logsfr, t_quench = self._Evol_MshamSFR(nsnap_d, allwill, sf_ancestors, q_ancestors) self.descendant_dict[str(nsnap_d)].sfr[allsucc[sf_ancestors]] = logsfr self.descendant_dict[str(nsnap_d)].ssfr[allsucc[sf_ancestors]] = \ self.descendant_dict[str(nsnap_d)].sfr[allsucc[sf_ancestors]] - \ self.descendant_dict[str(nsnap_d)].mass[allsucc[sf_ancestors]] is_qing = np.where(t_quench < self.descendant_dict[str(nsnap_d)].t_cosmic) is_notqing = np.where(t_quench >= self.descendant_dict[str(nsnap_d)].t_cosmic) self.descendant_dict[str(nsnap_d)].sfr_class[allsucc[sf_ancestors[is_qing]]] = \ 'quiescent' self.descendant_dict[str(nsnap_d)].sfr_class[allsucc[sf_ancestors[is_notqing]]] = \ 'star-forming' self.descendant_dict[str(nsnap_d)].t_quench[allsucc[sf_ancestors[is_qing]]] = t_quench[is_qing] return None
def _StarformingEvol_Pq(ancestor, descendant, succession=None, will=None, sfr_prop=None, evol_prop=None, lineage=None): ''' Evolve the stellar mass and star formation rates simultaneously. The stellar mass evolution is dictated by the SFR. ''' sfms_prop = sfr_prop['sfms'] pq_prop = evol_prop['pq'] tau_prop = evol_prop['tau'] sfrevol_prop = evol_prop['sfr'] dutycycle_prop = sfrevol_prop['dutycycle'] massevol_prop = evol_prop['mass'] # quenching probability pq_time = time.time() P_q = _getPq(ancestor, descendant, succession=succession, will=will, pq_prop=pq_prop, sfr_prop=sfr_prop) print 'Quenching Probabilities takes : ', time.time() - pq_time # quenching time/redshift tq_time = time.time() descendant, t_q, z_q = _tQuench(ancestor, descendant, P_q, succession=succession, will=will) print 'tQuench takes: ', time.time() - tq_time # star forming ancestors sf_ancestors = np.where( ancestor.sfr_class[will] == 'star-forming')[0] # SF ancestors # star-formation duty cycle parameters dutycycle_time = time.time() dutycycle_prop = sfr_evol.dutycycle_param(len(sf_ancestors), dutycycle_prop=dutycycle_prop) dutycycle_prop['delta_sfr'] = ancestor.delta_sfr[will[sf_ancestors]] print 'SFR dutycycle properties take ', time.time( ) - dutycycle_time, ' to generate' M_q = np.repeat(-999., len(sf_ancestors)) # keywords for logSFR(M*,t) kwargs_sfr = { 't_init': descendant.tsnap_genesis[succession[sf_ancestors]], 't_q': t_q, 'z_q': z_q, 'M_q': M_q, 'dutycycle_prop': dutycycle_prop, 'tau_prop': tau_prop, 'sfms_prop': sfms_prop } sham_mass = descendant.mass[ succession[sf_ancestors]].copy() # descendant SHAM masses if massevol_prop['name'] == 'integrated': # integrated stellar mass mass_time = time.time() descendant.mass[succession[sf_ancestors]], descendant.sfr[succession[sf_ancestors]], blah = \ M_integrate( ancestor.mass_genesis[will[sf_ancestors]], ancestor.tsnap_genesis[will[sf_ancestors]], descendant.t_cosmic, massevol_prop=massevol_prop, kwargs_sfr=kwargs_sfr # kwargs for logSFR(M*,t) function ) if np.min(descendant.mass[succession[sf_ancestors]] - ancestor.mass[will[sf_ancestors]]) < 0.0: raise ValueError("Integrated mass can't reduce the mass") print 'Integrated Masses takes ', time.time() - mass_time elif massevol_prop['name'] == 'sham': # SHAM masses # determine the quenching stellar mass (the SHAM stellar mass at t_Q) M_q = _SHAM_Mquenching(kwargs_sfr['t_q'], lineage=lineage, descendant=descendant, descendant_index=succession[sf_ancestors]) kwargs_sfr['M_q'] = M_q descendant.sfr[succession[sf_ancestors]] = \ logSFR_M_t(sham_mass, descendant.t_cosmic, **kwargs_sfr) # calculate SSFR based on evloved SFR and M* descendant.ssfr[succession[sf_ancestors]] = \ descendant.sfr[succession[sf_ancestors]] - descendant.mass[succession[sf_ancestors]] return
def _StarformingEvol_SimulEvo(ancestor, descendants, successions=None, wills=None, sfr_prop=None, evol_prop=None, lineage=None, quiet=True): ''' Evolve the stellar mass, star formation rates, and quench galaxies simultaneously. ''' sfms_prop = sfr_prop['sfms'] # SFMS properties fq_prop = sfr_prop['fq'] # fq_prop tau_prop = evol_prop['tau'] # Quenching timescale properties fudge_prop = evol_prop['fudge'] dutycycle_prop = evol_prop['sfr']['dutycycle'] # SF dutycycle properties massevol_prop = evol_prop['mass'] # mass evolution properties if len(descendants) > 1: allwill = np.array(list(set(list( np.concatenate(wills))))) # combine will of unique elements t_output = [] for des in descendants: t_output.append(des.t_cosmic) else: t_output = [descendants[0].t_cosmic] allwill = wills[0] sf_ancestors = np.where( ancestor.sfr_class[allwill] == 'star-forming')[0] # SF ancestors q_ancestors = np.where( ancestor.sfr_class[allwill] == 'quiescent')[0] # Q ancestors # star-formation duty cycle parameters if not quiet: dutycycle_time = time.time() dutycycle_prop = sfr_evol.dutycycle_param(len(sf_ancestors), dutycycle_prop=dutycycle_prop) dutycycle_prop['delta_sfr'] = ancestor.delta_sfr[allwill[sf_ancestors]] if not quiet: print 'SFR dutycycle properties take ', time.time( ) - dutycycle_time, ' to generate' MshamEvol = ancestor.Msham_evol[0] # keywords for logSFR(M*,t) kwargs_sfr = { 'dutycycle_prop': dutycycle_prop, 'tau_prop': tau_prop, 'fudge_prop': fudge_prop, 'fq_prop': fq_prop, 'sfms_prop': sfms_prop, 'massevol_prop': massevol_prop } if not quiet: mass_time = time.time() # DEFUNCT FOR NOW. needs to be updated #if massevol_prop['name'] == 'integrated': # M_evolved, SFR_evolved, tQ = \ # Evol_IntegMstarSFR( # ancestor.mass_genesis[will[sf_ancestors]], # ancestor.tsnap_genesis[will[sf_ancestors]], # descendant.t_cosmic, # tQ0=ancestor.tQ[will[sf_ancestors]], # MQ0=ancestor.MQ[will[sf_ancestors]], # ancestor_Mq=MshamEvol[will[q_ancestors],:], # **kwargs_sfr # ) #elif massevol_prop['name'] == 'sham': bef_tsnap = ancestor.tsnap_genesis[allwill[sf_ancestors]] bef_tQ = ancestor.tQ[allwill[sf_ancestors]] bef_MQ = ancestor.MQ[allwill[sf_ancestors]] bef_sfr = ancestor.sfr[allwill[sf_ancestors]] bef_MshamEvol = MshamEvol[allwill] SFRs_evolved, tQ = \ Evol_shamMstarSFR( ancestor.tsnap_genesis[allwill[sf_ancestors]], t_output, tQ0=ancestor.tQ[allwill[sf_ancestors]], MQ0=ancestor.MQ[allwill[sf_ancestors]], SFR0=ancestor.sfr[allwill[sf_ancestors]], q_Mshams=MshamEvol[allwill[q_ancestors],:], sf_Mshams=MshamEvol[allwill[sf_ancestors],:], **kwargs_sfr ) print 'tsnap stays the same', np.array_equal( bef_tsnap, ancestor.tsnap_genesis[allwill[sf_ancestors]]) print 'tQ stays the same', np.array_equal( bef_tQ, ancestor.tQ[allwill[sf_ancestors]]) print 'MQ stays the same', np.array_equal( bef_MQ, ancestor.MQ[allwill[sf_ancestors]]) print 'SFR stays the same', np.array_equal( bef_sfr, ancestor.sfr[allwill[sf_ancestors]]) print 'MshamEvol stays the same', np.array_equal(bef_MshamEvol, MshamEvol[allwill]) print 'recalculating for just t=', t_output[0] SFRs_evolved1, tQ1 = \ Evol_shamMstarSFR( ancestor.tsnap_genesis[allwill[sf_ancestors]], [t_output[0]], tQ0=ancestor.tQ[allwill[sf_ancestors]], MQ0=ancestor.MQ[allwill[sf_ancestors]], SFR0=ancestor.sfr[allwill[sf_ancestors]], q_Mshams=MshamEvol[allwill[q_ancestors],:], sf_Mshams=MshamEvol[allwill[sf_ancestors],:], **kwargs_sfr ) print 'tsnap stays the same', np.array_equal( bef_tsnap, ancestor.tsnap_genesis[allwill[sf_ancestors]]) print 'tQ stays the same', np.array_equal( bef_tQ, ancestor.tQ[allwill[sf_ancestors]]) print 'MQ stays the same', np.array_equal( bef_MQ, ancestor.MQ[allwill[sf_ancestors]]) print 'SFR stays the same', np.array_equal( bef_sfr, ancestor.sfr[allwill[sf_ancestors]]) print 'MshamEvol stays the same', np.array_equal(bef_MshamEvol, MshamEvol[allwill]) print np.array_equal(SFRs_evolved[0], SFRs_evolved1) dist, bins = np.histogram(SFRs_evolved[0], range=[-5, 2]) plt.plot(0.5 * (bins[:-1] + bins[1:]), dist) dist, bins = np.histogram(SFRs_evolved1, range=[-5, 2]) plt.plot(0.5 * (bins[:-1] + bins[1:]), dist) plt.show() for i_d in range(len(t_output)): sf_anc = np.where(ancestor.sfr_class[wills[i_d]] == 'star-forming')[0] sf_succession = (successions[i_d])[sf_anc] sf_will = (wills[i_d])[sf_anc] sf_allwill = allwill[sf_ancestors] ss, ww = intersection_index(sf_allwill, sf_will) if len(ww) != len(sf_will): raise ValueError #descendants[i_d].mass[sf_succession[ww]] = (Ms_evolved[i_d])[ss] descendants[i_d].sfr[sf_succession[ww]] = (SFRs_evolved[i_d])[ss] is_qing = np.where(tQ[ss] < t_output[i_d]) is_notqing = np.where(tQ[ss] >= t_output[i_d]) descendants[i_d].sfr_class[sf_succession[is_qing]] = 'quiescent' descendants[i_d].sfr_class[sf_succession[is_notqing]] = 'star-forming' # calculate SSFR based on evloved SFR and M* descendants[i_d].ssfr[sf_succession[ww]] = \ descendants[i_d].sfr[sf_succession[ww]] - descendants[i_d].mass[sf_succession[ww]] #if massevol_prop['name'] == 'integrated': # if np.min(descendant.mass[succession[sf_ancestors]] - ancestor.mass[will[sf_ancestors]]) < 0.0: # raise ValueError("Integrated mass can't reduce the mass") return descendants
def _StarformingEvol_Pq(ancestor, descendant, succession=None, will=None, sfr_prop=None, evol_prop=None, lineage=None): ''' Evolve the stellar mass and star formation rates simultaneously. The stellar mass evolution is dictated by the SFR. ''' sfms_prop = sfr_prop['sfms'] pq_prop = evol_prop['pq'] tau_prop = evol_prop['tau'] sfrevol_prop = evol_prop['sfr'] dutycycle_prop = sfrevol_prop['dutycycle'] massevol_prop = evol_prop['mass'] # quenching probability pq_time = time.time() P_q = _getPq(ancestor, descendant, succession=succession, will=will, pq_prop=pq_prop, sfr_prop=sfr_prop) print 'Quenching Probabilities takes : ', time.time() - pq_time # quenching time/redshift tq_time = time.time() descendant, t_q, z_q = _tQuench(ancestor, descendant, P_q, succession=succession, will=will) print 'tQuench takes: ', time.time() - tq_time # star forming ancestors sf_ancestors = np.where(ancestor.sfr_class[will] == 'star-forming')[0] # SF ancestors # star-formation duty cycle parameters dutycycle_time = time.time() dutycycle_prop = sfr_evol.dutycycle_param(len(sf_ancestors), dutycycle_prop=dutycycle_prop) dutycycle_prop['delta_sfr'] = ancestor.delta_sfr[will[sf_ancestors]] print 'SFR dutycycle properties take ', time.time() - dutycycle_time, ' to generate' M_q = np.repeat(-999., len(sf_ancestors)) # keywords for logSFR(M*,t) kwargs_sfr = { 't_init': descendant.tsnap_genesis[succession[sf_ancestors]], 't_q': t_q, 'z_q': z_q, 'M_q': M_q, 'dutycycle_prop': dutycycle_prop, 'tau_prop': tau_prop, 'sfms_prop': sfms_prop } sham_mass = descendant.mass[succession[sf_ancestors]].copy() # descendant SHAM masses if massevol_prop['name'] == 'integrated': # integrated stellar mass mass_time = time.time() descendant.mass[succession[sf_ancestors]], descendant.sfr[succession[sf_ancestors]], blah = \ M_integrate( ancestor.mass_genesis[will[sf_ancestors]], ancestor.tsnap_genesis[will[sf_ancestors]], descendant.t_cosmic, massevol_prop=massevol_prop, kwargs_sfr=kwargs_sfr # kwargs for logSFR(M*,t) function ) if np.min(descendant.mass[succession[sf_ancestors]] - ancestor.mass[will[sf_ancestors]]) < 0.0: raise ValueError("Integrated mass can't reduce the mass") print 'Integrated Masses takes ', time.time() - mass_time elif massevol_prop['name'] == 'sham': # SHAM masses # determine the quenching stellar mass (the SHAM stellar mass at t_Q) M_q = _SHAM_Mquenching(kwargs_sfr['t_q'], lineage=lineage, descendant=descendant, descendant_index=succession[sf_ancestors]) kwargs_sfr['M_q'] = M_q descendant.sfr[succession[sf_ancestors]] = \ logSFR_M_t(sham_mass, descendant.t_cosmic, **kwargs_sfr) # calculate SSFR based on evloved SFR and M* descendant.ssfr[succession[sf_ancestors]] = \ descendant.sfr[succession[sf_ancestors]] - descendant.mass[succession[sf_ancestors]] return
def _StarformingEvol_SimulEvo(ancestor, descendants, successions=None, wills=None, sfr_prop=None, evol_prop=None, lineage=None, quiet=True): ''' Evolve the stellar mass, star formation rates, and quench galaxies simultaneously. ''' sfms_prop = sfr_prop['sfms'] # SFMS properties fq_prop = sfr_prop['fq'] # fq_prop tau_prop = evol_prop['tau'] # Quenching timescale properties fudge_prop = evol_prop['fudge'] dutycycle_prop = evol_prop['sfr']['dutycycle'] # SF dutycycle properties massevol_prop = evol_prop['mass'] # mass evolution properties if len(descendants) > 1: allwill = np.array(list(set(list(np.concatenate(wills))))) # combine will of unique elements t_output = [] for des in descendants: t_output.append(des.t_cosmic) else: t_output = [descendants[0].t_cosmic] allwill = wills[0] sf_ancestors = np.where(ancestor.sfr_class[allwill] == 'star-forming')[0] # SF ancestors q_ancestors = np.where(ancestor.sfr_class[allwill] == 'quiescent')[0] # Q ancestors # star-formation duty cycle parameters if not quiet: dutycycle_time = time.time() dutycycle_prop = sfr_evol.dutycycle_param(len(sf_ancestors), dutycycle_prop=dutycycle_prop) dutycycle_prop['delta_sfr'] = ancestor.delta_sfr[allwill[sf_ancestors]] if not quiet: print 'SFR dutycycle properties take ', time.time() - dutycycle_time, ' to generate' MshamEvol = ancestor.Msham_evol[0] # keywords for logSFR(M*,t) kwargs_sfr = {'dutycycle_prop': dutycycle_prop, 'tau_prop': tau_prop, 'fudge_prop': fudge_prop, 'fq_prop': fq_prop, 'sfms_prop': sfms_prop, 'massevol_prop': massevol_prop} if not quiet: mass_time = time.time() # DEFUNCT FOR NOW. needs to be updated #if massevol_prop['name'] == 'integrated': # M_evolved, SFR_evolved, tQ = \ # Evol_IntegMstarSFR( # ancestor.mass_genesis[will[sf_ancestors]], # ancestor.tsnap_genesis[will[sf_ancestors]], # descendant.t_cosmic, # tQ0=ancestor.tQ[will[sf_ancestors]], # MQ0=ancestor.MQ[will[sf_ancestors]], # ancestor_Mq=MshamEvol[will[q_ancestors],:], # **kwargs_sfr # ) #elif massevol_prop['name'] == 'sham': bef_tsnap = ancestor.tsnap_genesis[allwill[sf_ancestors]] bef_tQ = ancestor.tQ[allwill[sf_ancestors]] bef_MQ = ancestor.MQ[allwill[sf_ancestors]] bef_sfr = ancestor.sfr[allwill[sf_ancestors]] bef_MshamEvol = MshamEvol[allwill] SFRs_evolved, tQ = \ Evol_shamMstarSFR( ancestor.tsnap_genesis[allwill[sf_ancestors]], t_output, tQ0=ancestor.tQ[allwill[sf_ancestors]], MQ0=ancestor.MQ[allwill[sf_ancestors]], SFR0=ancestor.sfr[allwill[sf_ancestors]], q_Mshams=MshamEvol[allwill[q_ancestors],:], sf_Mshams=MshamEvol[allwill[sf_ancestors],:], **kwargs_sfr ) print 'tsnap stays the same', np.array_equal(bef_tsnap, ancestor.tsnap_genesis[allwill[sf_ancestors]]) print 'tQ stays the same', np.array_equal(bef_tQ, ancestor.tQ[allwill[sf_ancestors]]) print 'MQ stays the same', np.array_equal(bef_MQ, ancestor.MQ[allwill[sf_ancestors]]) print 'SFR stays the same', np.array_equal(bef_sfr, ancestor.sfr[allwill[sf_ancestors]]) print 'MshamEvol stays the same', np.array_equal(bef_MshamEvol, MshamEvol[allwill]) print 'recalculating for just t=', t_output[0] SFRs_evolved1, tQ1 = \ Evol_shamMstarSFR( ancestor.tsnap_genesis[allwill[sf_ancestors]], [t_output[0]], tQ0=ancestor.tQ[allwill[sf_ancestors]], MQ0=ancestor.MQ[allwill[sf_ancestors]], SFR0=ancestor.sfr[allwill[sf_ancestors]], q_Mshams=MshamEvol[allwill[q_ancestors],:], sf_Mshams=MshamEvol[allwill[sf_ancestors],:], **kwargs_sfr ) print 'tsnap stays the same', np.array_equal(bef_tsnap, ancestor.tsnap_genesis[allwill[sf_ancestors]]) print 'tQ stays the same', np.array_equal(bef_tQ, ancestor.tQ[allwill[sf_ancestors]]) print 'MQ stays the same', np.array_equal(bef_MQ, ancestor.MQ[allwill[sf_ancestors]]) print 'SFR stays the same', np.array_equal(bef_sfr, ancestor.sfr[allwill[sf_ancestors]]) print 'MshamEvol stays the same', np.array_equal(bef_MshamEvol, MshamEvol[allwill]) print np.array_equal(SFRs_evolved[0], SFRs_evolved1) dist, bins = np.histogram(SFRs_evolved[0], range=[-5, 2]) plt.plot(0.5 * (bins[:-1] + bins[1:]), dist) dist, bins = np.histogram(SFRs_evolved1, range=[-5, 2]) plt.plot(0.5 * (bins[:-1] + bins[1:]), dist) plt.show() for i_d in range(len(t_output)): sf_anc = np.where(ancestor.sfr_class[wills[i_d]] == 'star-forming')[0] sf_succession = (successions[i_d])[sf_anc] sf_will = (wills[i_d])[sf_anc] sf_allwill = allwill[sf_ancestors] ss, ww = intersection_index(sf_allwill, sf_will) if len(ww) != len(sf_will): raise ValueError #descendants[i_d].mass[sf_succession[ww]] = (Ms_evolved[i_d])[ss] descendants[i_d].sfr[sf_succession[ww]] = (SFRs_evolved[i_d])[ss] is_qing = np.where(tQ[ss] < t_output[i_d]) is_notqing = np.where(tQ[ss] >= t_output[i_d]) descendants[i_d].sfr_class[sf_succession[is_qing]] = 'quiescent' descendants[i_d].sfr_class[sf_succession[is_notqing]] = 'star-forming' # calculate SSFR based on evloved SFR and M* descendants[i_d].ssfr[sf_succession[ww]] = \ descendants[i_d].sfr[sf_succession[ww]] - descendants[i_d].mass[sf_succession[ww]] #if massevol_prop['name'] == 'integrated': # if np.min(descendant.mass[succession[sf_ancestors]] - ancestor.mass[will[sf_ancestors]]) < 0.0: # raise ValueError("Integrated mass can't reduce the mass") return descendants
def _StarformingEvol(ancestor, descendant, succession=None, will=None, sfr_prop=None, evol_prop=None, lineage=None): ''' Evolve the stellar mass, star formation rates, and quench galaxies simultaneously. ''' # SFMS properties sfms_prop = sfr_prop['sfms'] # fq_prop fq_prop = sfr_prop['fq'] # Quenching timescale properties tau_prop = evol_prop['tau'] # SFR evolution properties sfrevol_prop = evol_prop['sfr'] # SF dutycycle properties dutycycle_prop = sfrevol_prop['dutycycle'] # mass evolution properties massevol_prop = evol_prop['mass'] # star forming ancestors sf_ancestors = np.where(ancestor.sfr_class[will] == 'star-forming')[0] # SF ancestors # star-formation duty cycle parameters dutycycle_time = time.time() dutycycle_prop = sfr_evol.dutycycle_param(len(sf_ancestors), dutycycle_prop=dutycycle_prop) dutycycle_prop['delta_sfr'] = ancestor.delta_sfr[will[sf_ancestors]] print 'SFR dutycycle properties take ', time.time() - dutycycle_time, ' to generate' # keywords for logSFR(M*,t) kwargs_sfr = { 'dutycycle_prop': dutycycle_prop, 'tau_prop': tau_prop, 'fq_prop': fq_prop, 'sfms_prop': sfms_prop, 'massevol_prop': massevol_prop } sham_mass = descendant.mass[succession[sf_ancestors]].copy() # descendant SHAM masses mass_time = time.time() descendant.mass[succession[sf_ancestors]], descendant.sfr[succession[sf_ancestors]] = \ MstarSFR_simul_evol( ancestor.mass_genesis[will[sf_ancestors]], ancestor.tsnap_genesis[will[sf_ancestors]], descendant.t_cosmic, **kwargs_sfr ) if np.min(descendant.mass[succession[sf_ancestors]] - ancestor.mass[will[sf_ancestors]]) < 0.0: raise ValueError("Integrated mass can't reduce the mass") ''' elif massevol_prop['name'] == 'sham': # SHAM masses # determine the quenching stellar mass (the SHAM stellar mass at t_Q) M_q = _SHAM_Mquenching(kwargs_sfr['t_q'], lineage=lineage, descendant=descendant, descendant_index=succession[sf_ancestors]) kwargs_sfr['M_q'] = M_q descendant.sfr[succession[sf_ancestors]] = \ logSFR_M_t(sham_mass, descendant.t_cosmic, **kwargs_sfr) ''' # calculate SSFR based on evloved SFR and M* descendant.ssfr[succession[sf_ancestors]] = \ descendant.sfr[succession[sf_ancestors]] - descendant.mass[succession[sf_ancestors]] return
def _StarformingEvol(ancestor, descendant, succession=None, will=None, sfr_prop=None, evol_prop=None, lineage=None): ''' Evolve the stellar mass, star formation rates, and quench galaxies simultaneously. ''' # SFMS properties sfms_prop = sfr_prop['sfms'] # fq_prop fq_prop = sfr_prop['fq'] # Quenching timescale properties tau_prop = evol_prop['tau'] # SFR evolution properties sfrevol_prop = evol_prop['sfr'] # SF dutycycle properties dutycycle_prop = sfrevol_prop['dutycycle'] # mass evolution properties massevol_prop = evol_prop['mass'] # star forming ancestors sf_ancestors = np.where( ancestor.sfr_class[will] == 'star-forming')[0] # SF ancestors # star-formation duty cycle parameters dutycycle_time = time.time() dutycycle_prop = sfr_evol.dutycycle_param(len(sf_ancestors), dutycycle_prop=dutycycle_prop) dutycycle_prop['delta_sfr'] = ancestor.delta_sfr[will[sf_ancestors]] print 'SFR dutycycle properties take ', time.time( ) - dutycycle_time, ' to generate' # keywords for logSFR(M*,t) kwargs_sfr = { 'dutycycle_prop': dutycycle_prop, 'tau_prop': tau_prop, 'fq_prop': fq_prop, 'sfms_prop': sfms_prop, 'massevol_prop': massevol_prop } sham_mass = descendant.mass[ succession[sf_ancestors]].copy() # descendant SHAM masses mass_time = time.time() descendant.mass[succession[sf_ancestors]], descendant.sfr[succession[sf_ancestors]] = \ MstarSFR_simul_evol( ancestor.mass_genesis[will[sf_ancestors]], ancestor.tsnap_genesis[will[sf_ancestors]], descendant.t_cosmic, **kwargs_sfr ) if np.min(descendant.mass[succession[sf_ancestors]] - ancestor.mass[will[sf_ancestors]]) < 0.0: raise ValueError("Integrated mass can't reduce the mass") ''' elif massevol_prop['name'] == 'sham': # SHAM masses # determine the quenching stellar mass (the SHAM stellar mass at t_Q) M_q = _SHAM_Mquenching(kwargs_sfr['t_q'], lineage=lineage, descendant=descendant, descendant_index=succession[sf_ancestors]) kwargs_sfr['M_q'] = M_q descendant.sfr[succession[sf_ancestors]] = \ logSFR_M_t(sham_mass, descendant.t_cosmic, **kwargs_sfr) ''' # calculate SSFR based on evloved SFR and M* descendant.ssfr[succession[sf_ancestors]] = \ descendant.sfr[succession[sf_ancestors]] - descendant.mass[succession[sf_ancestors]] return