double collisional_starburst_recipe(double mass_ratio, int merger_centralgal, int centralgal, double time, double deltaT, int nstep) //ROB: New variable 'nstep' added, for use in update_yields() { /** @brief If StarBurstRecipe = 1 (since Croton2006), the Somerville 2001 * model of bursts is used. The burst can happen for both major * and minor mergers, with a fraction of the added cold gas from * the satellite and central being consumed. SN Feedback from * starformation is computed and the sizes of bulge and disk * followed (not done for the other burst mode).*/ double mstars, reheated_mass, ejected_mass, fac, metallicitySF; double CentralVvir, eburst, MergeCentralVvir, Ggas, EjectVmax, EjectVvir; double SN_Energy, Reheat_Energy; /* This is the major and minor merger starburst recipe of Somerville 2001. * The coefficients in eburst are taken from TJ Cox's PhD thesis and should * be more accurate then previous. */ Ggas=Gal[merger_centralgal].ColdGas; /* the bursting fraction given the mass ratio */ /* m_dot = 0.56*(m_sat/m_central)^0.7*m_gas */ eburst = SfrBurstEfficiency * pow(mass_ratio, SfrBurstSlope); //eburst = 0.56 * pow(mass_ratio, 0.7); mstars = eburst * Gal[merger_centralgal].ColdGas; if(mstars < 0.0) mstars = 0.0; /* this bursting results in SN feedback on the cold/hot gas * TODO this is the same code used in star_formation_and_feedback.c * and should be merged if possible. */ if(FeedbackRecipe == 0 || FeedbackRecipe == 1) { if (Gal[merger_centralgal].Type == 0) reheated_mass = FeedbackReheatingEpsilon * mstars*(.5+1./pow(Gal[merger_centralgal].Vmax/ReheatPreVelocity,ReheatSlope)); else reheated_mass = FeedbackReheatingEpsilon * mstars*(.5+1./pow(Gal[merger_centralgal].InfallVmax/ReheatPreVelocity,ReheatSlope)); } //Make sure that the energy used does not exceed the SN energy (central subhalo Vvir used) if(FeedbackRecipe == 0 || FeedbackRecipe == 1) { if (reheated_mass * Gal[merger_centralgal].Vvir * Gal[merger_centralgal].Vvir > mstars * EtaSNcode * EnergySNcode) reheated_mass = mstars * EtaSNcode * EnergySNcode / Gal[merger_centralgal].Vvir / Gal[merger_centralgal].Vvir; } /* cant use more cold gas than is available! so balance SF and feedback */ if((mstars + reheated_mass) > Gal[merger_centralgal].ColdGas) { fac = Gal[merger_centralgal].ColdGas / (mstars + reheated_mass); mstars *= fac; reheated_mass *= fac; } if (merger_centralgal == centralgal) { EjectVmax=Gal[centralgal].Vmax; EjectVvir=Gal[centralgal].Vvir;// main halo Vvir } else { EjectVmax=Gal[merger_centralgal].InfallVmax; EjectVvir=Gal[merger_centralgal].Vvir; //central subhalo Vvir } /* determine ejection*/ if(FeedbackRecipe == 0) { ejected_mass = (FeedbackEjectionEfficiency* (EtaSNcode * EnergySNcode) *mstars * min(1./FeedbackEjectionEfficiency,.5+1/pow(EjectVmax/EjectPreVelocity,EjectSlope)) - reheated_mass*EjectVvir*EjectVvir) /(EjectVvir*EjectVvir); } else if(FeedbackRecipe == 1) { SN_Energy = .5 * mstars * (EtaSNcode * EnergySNcode); Reheat_Energy = .5 * reheated_mass * EjectVvir * EjectVvir; ejected_mass = (SN_Energy - Reheat_Energy)/(0.5 * FeedbackEjectionEfficiency*(EtaSNcode * EnergySNcode)); if(FeedbackEjectionEfficiency*(EtaSNcode * EnergySNcode)<EjectVvir*EjectVvir) ejected_mass =0.0; } // Finished calculating mass exchanges, so just check that none are negative if (reheated_mass < 0.0) reheated_mass = 0.0; if (ejected_mass < 0.0) ejected_mass = 0.0; /* update the star formation rate */ #ifdef SAVE_MEMORY Gal[merger_centralgal].Sfr += mstars / deltaT; #else for(outputbin = 0; outputbin < NOUT; outputbin++) { if(Halo[halonr].SnapNum == ListOutputSnaps[outputbin]) { Gal[merger_centralgal].Sfr[outputbin] += mstars / deltaT; break; } } #endif /* Store the value of the metallicity of the cold phase when SF occurs. * Used to update luminosities below */ #ifdef METALS //metallicitySF = Gal[merger_centralgal].MetalsColdGas.type2/Gal[merger_centralgal].ColdGas; metallicitySF = metals_total(Gal[merger_centralgal].MetalsColdGas)/Gal[merger_centralgal].ColdGas; #else metallicitySF = Gal[merger_centralgal].MetalsColdGas/Gal[merger_centralgal].ColdGas; #endif mass_checks("collisional_starburst_recipe #1",merger_centralgal); if (mstars > 0.) update_from_star_formation(merger_centralgal, mstars, deltaT/STEPS, nstep); mass_checks("collisional_starburst_recipe #2",merger_centralgal); // Do not call if Gal[merger_centralgal].ColdGas < 1e-8? if (reheated_mass + ejected_mass > 0.) update_from_feedback(merger_centralgal, centralgal, reheated_mass, ejected_mass); #ifndef POST_PROCESS_MAGS /* update the luminosities due to the stars formed */ if (mstars > 0.0) add_to_luminosities(merger_centralgal, mstars, time, metallicitySF); #endif if (Ggas > 0.) return mstars/Ggas; else return 0.0; }
/** @brief Main recipe, calculates the fraction of cold gas turned into stars due * to star formation; the fraction of mass instantaneously recycled and * returned to the cold gas; the fraction of gas reheated from cold to hot, * ejected from hot to external and returned from ejected to hot due to * SN feedback. */ void starformation(int p, int centralgal, double time, double dt, int nstep) { /*! Variables: reff-Rdisk, tdyn=Rdisk/Vmax, strdot=Mstar_dot, stars=strdot*dt*/ double tdyn, strdot=0., stars, cold_crit, metallicitySF; if(Gal[p].Type == 0) { tdyn = Gal[p].GasDiskRadius / Gal[p].Vmax; cold_crit = SfrColdCrit * Gal[p].Vmax/200. * Gal[p].GasDiskRadius*100.; } else { tdyn = Gal[p].GasDiskRadius / Gal[p].InfallVmax; cold_crit = SfrColdCrit * Gal[p].InfallVmax/200. * Gal[p].GasDiskRadius*100.; } //standard star formation law (Croton2006, Delucia2007, Guo2010) if(StarFormationModel == 0) { if(Gal[p].ColdGas > cold_crit) strdot = SfrEfficiency * (Gal[p].ColdGas - cold_crit) / tdyn; else strdot = 0.0; } /*if(StarFormationModel == 1) { strdot = ALTERNATIVE STAR FORMATION LAW }*/ /* Note that Units of dynamical time are Mpc/Km/s - no conversion on dt needed */ stars = strdot * dt; if(stars < 0.0) terminate("***error stars<0.0***\n"); //otherwise cold gas and stars share material in update_stars_due_to_reheat #ifdef FEEDBACK_COUPLED_WITH_MASS_RETURN if(stars > Gal[p].ColdGas) stars = Gal[p].ColdGas; #endif mass_checks("recipe_starform #1",p); mass_checks("recipe_starform #1.1",centralgal); /* update for star formation * updates Mcold, StellarMass, MetalsMcold and MetalsStellarMass * in Guo2010 case updates the stellar spin -> hardwired, not an option */ /* Store the value of the metallicity of the cold phase when SF occurs */ if (Gal[p].ColdGas > 0.) metallicitySF= metals_total(Gal[p].MetalsColdGas)/Gal[p].ColdGas; else metallicitySF=0.; if (stars > 0.) update_stars_due_to_reheat(p, centralgal, &stars); mass_checks("recipe_starform #2",p); mass_checks("recipe_starform #2.1",centralgal); /* update the star formation rate */ /*Sfr=stars/(dt*steps)=strdot*dt/(dt*steps)=strdot/steps -> average over the STEPS*/ Gal[p].Sfr += stars / (dt * STEPS); // update_from_star_formation can only be called // after SD_feeedback recipe since stars need to be re_set once the reheated mass is known // (star formation and feedback share the same fraction of cold gas) if (stars > 0.) update_from_star_formation(p, stars, false, nstep); // false indicates not a burst update_massweightage(p, stars, time); #ifndef FEEDBACK_COUPLED_WITH_MASS_RETURN /* ifdef FEEDBACK_COUPLED_WITH_MASS_RETURN feedback is only called * when stars die, inside DETAILED_METALS_AND_MASS_RETURN */ if (stars > 0.) SN_feedback(p, centralgal, stars, "ColdGas"); #endif #ifdef COMPUTE_SPECPHOT_PROPERTIES #ifndef POST_PROCESS_MAGS /* Update the luminosities due to the stars formed */ if (stars > 0.0) add_to_luminosities(p, stars, time, dt, metallicitySF); #endif //NDEF POST_PROCESS_MAGS #endif //COMPUTE_SPECPHOT_PROPERTIES if(Gal[p].DiskMass > 0.0) check_disk_instability(p); if (DiskRadiusModel== 0) get_stellar_disk_radius(p); }