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);

}
void do_AGN_heating(double dt, int ngal)
{
  double AGNrate, AGNheating, AGNaccreted, AGNcoeff, fraction, EDDrate, FreeFallRadius;
  double dist, HotGas, HotRadius, Rvir, Vvir, Mvir;
  double LeftOverEnergy, CoolingGas, AGNAccretedFromCentral;
  int p, FoFCentralGal;

  if(AGNRadioModeModel == 0)
    {
      for (p = 0; p < ngal; p++)
	if(Gal[p].Type == 0)
	  FoFCentralGal=p;
    }

  for (p = 0; p < ngal; p++)
    {
      Gal[p].CoolingRate_beforeAGN += Gal[p].CoolingGas / (dt*STEPS);

      AGNrate=0.;
      LeftOverEnergy = 0.;

      HotGas = Gal[p].HotGas;
      HotRadius = Gal[p].HotRadius;
      CoolingGas = Gal[p].CoolingGas;
      Mvir = Gal[p].Mvir;
      Rvir = Gal[p].Rvir;
      Vvir = Gal[p].Vvir;

      if(HotGas > 0.0)
	{
	  if(AGNRadioModeModel == 0)
	    AGNrate = AgnEfficiency * (UnitTime_in_s*SOLAR_MASS)/(UNITMASS_IN_G*SEC_PER_YEAR)
	              * Gal[p].BlackHoleMass/Hubble_h * (HotGas/Hubble_h) * 10.;
	  else if(AGNRadioModeModel == 2)
	    {
	      //empirical (standard) accretion recipe - Eq. 10 in Croton 2006
	      AGNrate = AgnEfficiency / (UNITMASS_IN_G / UnitTime_in_s * SEC_PER_YEAR / SOLAR_MASS)
  	  		* (Gal[p].BlackHoleMass / 0.01) * pow3(Vvir / 200.0)
			* ((HotGas / HotRadius * Rvir / Mvir) / 0.1);
	    }
	  else if(AGNRadioModeModel == 3 || AGNRadioModeModel == 4)
	    {
	      double x, lambda, temp, logZ, tot_metals;

	      tot_metals = metals_total(Gal[p].MetalsHotGas);

	      /* temp -> Temperature of the Gas in Kelvin, obtained from
	       * hidrostatic equilibrium KT=0.5*mu_p*(Vc)^2 assuming Vvir~Vc */
	      temp = 35.9 * Vvir * Vvir;
	      if(tot_metals > 0)
		logZ = log10(tot_metals / HotGas);
	      else
		logZ = -10.0;
	      lambda = get_metaldependent_cooling_rate(log10(temp), logZ);
	      x = PROTONMASS * BOLTZMANN * temp / lambda; // now this has units sec g/cm^3
	      x /= (UnitDensity_in_cgs * UnitTime_in_s);  // now in internal units

	      /* Bondi-Hoyle accretion recipe -- efficiency = 0.15
	       * Eq. 29 in Croton 2006 */
	      if(AGNRadioModeModel == 3)
		AGNrate = (2.5 * M_PI * G) * (0.75 * 0.6 * x) * Gal[p].BlackHoleMass * 0.15;
	      else if(AGNRadioModeModel == 4)
		{
		  /* Cold cloud accretion recipe -- trigger: Rff = 50 Rdisk,
		   * and accretion rate = 0.01% cooling rate
		   * Eq. 25 in Croton 2006 */
		  FreeFallRadius = HotGas / (6.0 * 0.6 * x * Rvir * Vvir) /	HotRadius * Rvir;
		  if(Gal[p].BlackHoleMass > 0.0 && FreeFallRadius < Gal[p].GasDiskRadius * 50.0)
		    AGNrate = 0.0001 * CoolingGas / dt;
		  else
		    AGNrate = 0.0;
		}
	    }

	  /* Eddington rate */
	  /* Note that this assumes an efficiency of 50%
	   * - it ignores the e/(1-e) factor in L = e/(1-e) Mdot c^2 */
	  EDDrate = 1.3e48 * Gal[p].BlackHoleMass / (UnitEnergy_in_cgs / UnitTime_in_s) / 9e10;

	  /* accretion onto BH is always limited by the Eddington rate */
	  if(AGNrate > EDDrate)
	    AGNrate = EDDrate;

	  /*  accreted mass onto black hole the value of dt puts an h factor into AGNaccreted as required for code units */
	  AGNaccreted = AGNrate * dt;

	  /* cannot accrete more mass than is available! */
	  if(AGNaccreted > HotGas)
	    AGNaccreted = HotGas;

	  /*  coefficient to heat the cooling gas back to the virial temperature of the halo */
	  /*  1.34e5 = sqrt(2*eta*c^2), eta=0.1 (standard efficiency) and c in km/s
	   *  Eqs. 11 & 12 in Croton 2006 */
	  AGNcoeff = (1.34e5 / Vvir) * (1.34e5 / Vvir);

	  /*  cooling mass that can be suppressed from AGN heating */
	  AGNheating = AGNcoeff * AGNaccreted;


	  if(AGNRadioModeModel == 0 && Gal[p].Type==1)
	    {
	      if(dist < Gal[FoFCentralGal].Rvir)
		{
		  if(AGNheating > (Gal[p].CoolingGas + Gal[FoFCentralGal].CoolingGas))
		    {
		      AGNheating = (Gal[p].CoolingGas + Gal[FoFCentralGal].CoolingGas);
		      AGNaccreted = (Gal[p].CoolingGas + Gal[FoFCentralGal].CoolingGas) / AGNcoeff;
		    }
		  if(AGNheating > Gal[p].CoolingGas)
		    LeftOverEnergy = AGNheating - Gal[p].CoolingGas;
		}
	    }
	  else
	    if(AGNheating > Gal[p].CoolingGas)
	      AGNaccreted = Gal[p].CoolingGas / AGNcoeff;

	  /* limit heating to cooling rate */
	  if(AGNheating > Gal[p].CoolingGas)
	    AGNheating = Gal[p].CoolingGas;




	  /*  accreted mass onto black hole */
	  Gal[p].BlackHoleMass += AGNaccreted; //ROB: transfer_mass functions should be used here
	  Gal[p].RadioAccretionRate += AGNaccreted / (dt*STEPS);
	  fraction=AGNaccreted/Gal[p].HotGas;
	  Gal[p].HotGas -= AGNaccreted;
	  Gal[p].MetalsHotGas = metals_add(Gal[p].MetalsHotGas,Gal[p].MetalsHotGas, -fraction);

#ifdef INDIVIDUAL_ELEMENTS
	  Gal[p].HotGas_elements = elements_add(Gal[p].HotGas_elements,Gal[p].HotGas_elements,-fraction);
#endif
#ifdef METALS_SELF
	  Gal[p].MetalsHotGasSelf = 	metals_add(Gal[p].MetalsHotGasSelf,Gal[p].MetalsHotGasSelf,-fraction);
#endif	

	}
      else
	AGNheating = 0.0;


      Gal[p].CoolingGas -= AGNheating;

      if(Gal[p].CoolingGas < 0.0)
	Gal[p].CoolingGas = 0.0;

      Gal[p].CoolingRate += Gal[p].CoolingGas / (dt*STEPS);

      if(AGNRadioModeModel == 0 && LeftOverEnergy>0.)
  	{
	  Gal[FoFCentralGal].CoolingGas -= LeftOverEnergy;

	  if(Gal[FoFCentralGal].CoolingGas < 0.0)
	    Gal[FoFCentralGal].CoolingGas = 0.0;
	  else
	    Gal[FoFCentralGal].CoolingRate -= LeftOverEnergy / (dt*STEPS);
  	}


      mass_checks("cooling_recipe #2.",p);

  }
}
void compute_cooling(int p, double dt, int ngal)
{
  double Vvir, Rvir, x, lambda, tcool, rcool, temp, tot_hotMass, tot_metals, HotRadius;
  double coolingGas, logZ, rho_rcool, rho0;

  mass_checks("cooling_recipe #1",p);

  tot_hotMass = Gal[p].HotGas;
  tot_metals = metals_total(Gal[p].MetalsHotGas);

  if(tot_hotMass > 1.0e-6)
  {

    Vvir = Gal[p].Vvir;
    Rvir = Gal[p].Rvir;

    tcool = Rvir / Vvir; // tcool = t_dynamical = Rvir/Vvir

    /* temp -> Temperature of the Gas in Kelvin, obtained from
     * hidrostatic equilibrium KT=0.5*mu_p*(Vc)^2 assuming Vvir~Vc */
    temp = 35.9 * Vvir * Vvir;
      
    if (Gal[p].Type == 0)
      HotRadius = Gal[p].Rvir;
    else 
      HotRadius = Gal[p].HotRadius;
    
    if(tot_metals > 0)
      logZ = log10(tot_metals / tot_hotMass);
    else
      logZ = -10.0;

    //eq. 3 and 4 Guo2010
    lambda = get_metaldependent_cooling_rate(log10(temp), logZ);
    x = PROTONMASS * BOLTZMANN * temp / lambda; // now this has units sec g/cm^3
    x /= (UnitDensity_in_cgs * UnitTime_in_s);  // now in internal units
    rho_rcool = x / (0.28086 * tcool);
    /* an isothermal density profile for the hot gas is assumed here */
    rho0 = tot_hotMass / (4 * M_PI * HotRadius);
    rcool = sqrt(rho0 / rho_rcool);
    
    if (Gal[p].CoolingRadius < rcool)
      Gal[p].CoolingRadius = rcool;
      
    //if Hotradius is used, when galaxies become type 1's there will be a discontinuity in the cooling
    if(rcool > Rvir) // INFALL DOMINATED REGIME
      //coolingGas = tot_hotMass; - Delucia 2007
      /*comes in to keep the continuity (Delucia2004) */
      coolingGas = tot_hotMass / (HotRadius / Vvir) * dt;
    else // HOT PHASE REGIME
      /*coolingGas = (tot_hotMass / Rvir) * (rcool / tcool) * dt */
      coolingGas = (tot_hotMass / HotRadius) * (rcool / tcool) * dt ;
        
    //Photoionizing background
    if (log10(temp) < 4.0)
      coolingGas = 0.;
    
    if(coolingGas > tot_hotMass)
      coolingGas = tot_hotMass;
    else if(coolingGas < 0.0)
      coolingGas = 0.0;      
    

  }
  else
  {
    coolingGas = 0.0;
  }

  Gal[p].CoolingGas = coolingGas;

  mass_checks("cooling_recipe #1.5",p);

}   
/** @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_and_feedback(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, stars, reheated_mass, ejected_mass, fac, cold_crit,
         metallicitySF, CentralVvir, MergeCentralVvir, EjectVmax, EjectVvir,
         SN_Energy, Reheat_Energy;

  
  //standard star formation law (Croton2006, Delucia2007, Guo2010)
  if(StarFormationRecipe == 0)
  {
  	if(Gal[p].Type == 0)
  		tdyn = Gal[p].GasDiskRadius / Gal[p].Vmax;
  	else
  		tdyn = Gal[p].GasDiskRadius / Gal[p].InfallVmax;

  	if(Gal[p].Type == 0)
  		cold_crit = 0.19 * Gal[p].Vmax * Gal[p].GasDiskRadius;
	  else
	  	cold_crit = 0.19 * Gal[p].InfallVmax * Gal[p].GasDiskRadius;

  	if(Gal[p].ColdGas > cold_crit)
  		strdot = SfrEfficiency * (Gal[p].ColdGas - cold_crit) / tdyn * pow(Gal[p].Vvir / SfrLawPivotVelocity, SfrLawSlope);
  	else
  		strdot = 0.0;
  }

  //No dependce on Tdyn
  if(StarFormationRecipe == 1)
    {

	  if(Gal[p].ColdGas > 1.e-7)
		strdot = SfrEfficiency * (Gal[p].ColdGas) / (2.e-5) * pow(Gal[p].Vvir / SfrLawPivotVelocity, SfrLawSlope);
	  else
		strdot = 0.0;
    }

#ifdef H2FORMATION
  /* use H2 formation model from Krumholz */
  Not yet implemented
  H2Mass=cal_H2(p);
  strdot = SfrEfficiency * H2Mass / tdyn;
#endif    

  /*TODO - Note that Units of dynamical time are Mpc/Km/s - no conversion on dt needed
   *       be mentioned 3.06e19 to 3.15e19 */
  stars = strdot * dt;
  if(stars < 0.0)
    terminate("***error stars<0.0***\n");

/* SN FEEDBACK RECIPES */

  /* In Guo2010 type 1s can eject, reincorporate gas and get gas from their
   * own satellites (is not sent to the type 0 galaxy as in Delucia2007),
   * for gas flow computations:
   * If satellite is inside Rvir of main halo, Vvir of main halo used
   * If it is outside, the Vvir of its central subhalo is used. */

  CentralVvir = Gal[centralgal].Vvir; // main halo Vvir
  MergeCentralVvir = Gal[Gal[p].CentralGal].Vvir; //central subhalo Vvir
   
  mass_checks("recipe_starform #0",p);
  mass_checks("recipe_starform #0.1",centralgal);

  /* Feedback depends on the circular velocity of the host halo
   * Guo2010 - eq 18 & 19*/
  if(FeedbackRecipe == 0) {
    if (Gal[Gal[p].CentralGal].Type == 0)
      reheated_mass = FeedbackReheatingEpsilon * stars*
	(.5+1./pow(Gal[Gal[p].CentralGal].Vmax/ReheatPreVelocity,ReheatSlope));
    else
      reheated_mass = FeedbackReheatingEpsilon * stars*
	(.5+1./pow(Gal[Gal[p].CentralGal].InfallVmax/ReheatPreVelocity,ReheatSlope));
  }

  //Make sure that the energy used in reheat does not exceed the SN energy (central subhalo Vvir used)
  if (FeedbackRecipe == 0 || FeedbackRecipe == 1) {
    if (reheated_mass * Gal[Gal[p].CentralGal].Vvir * Gal[Gal[p].CentralGal].Vvir > stars * (EtaSNcode * EnergySNcode))
      reheated_mass = stars * (EtaSNcode * EnergySNcode) / (Gal[Gal[p].CentralGal].Vvir * Gal[Gal[p].CentralGal].Vvir);
  }

  /*  cant use more cold gas than is available! so balance SF and feedback */
  if((stars + reheated_mass) > Gal[p].ColdGas) {
    fac = Gal[p].ColdGas / (stars + reheated_mass);
    stars *= fac;
    reheated_mass *= fac;
  }  

  /* Determine ejection (for FeedbackRecipe 2 we have the dependence on Vmax)
   * Guo2010 - eq 22
   * Note that satellites can now retain gas and have their own gas cycle*/

  if (Gal[Gal[p].CentralGal].Type == 0)
    {
	  EjectVmax=Gal[centralgal].Vmax;
	  EjectVvir=Gal[centralgal].Vvir;// main halo Vvir
    }
  else
    {
	  EjectVmax=Gal[Gal[p].CentralGal].InfallVmax;
	  EjectVvir=Gal[Gal[p].CentralGal].Vvir; //central subhalo Vvir
    }

  if(FeedbackRecipe == 0)
    {
      ejected_mass =
    	(FeedbackEjectionEfficiency* (EtaSNcode * EnergySNcode) * stars *
	     min(1./FeedbackEjectionEfficiency, .5+1/pow(EjectVmax/EjectPreVelocity,EjectSlope)) -
	     reheated_mass*EjectVvir*EjectVvir) /(EjectVvir*EjectVvir);
    }
  else if(FeedbackRecipe == 1)//the ejected material is assumed to have V_SN
    {
	 
	  SN_Energy = .5 * stars * (EtaSNcode * EnergySNcode);
	  Reheat_Energy = .5 * reheated_mass * EjectVvir * EjectVvir;
	  
	  ejected_mass = (SN_Energy - Reheat_Energy)/(0.5 * FeedbackEjectionEfficiency*(EtaSNcode * EnergySNcode));

	  //if VSN^2<Vvir^2 nothing is ejected
	  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
  /*Sfr=stars/(dt*steps)=strdot*dt/(dt*steps)=strdot/steps -> average over the STEPS*/
  Gal[p].Sfr += stars / (dt * STEPS);
#else
  for(outputbin = 0; outputbin < NOUT; outputbin++) {
    if(Halo[halonr].SnapNum == ListOutputSnaps[outputbin]) {
      Gal[p].Sfr[outputbin] += stars / (dt * STEPS);
      break;
    }
  }
#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.)
#ifdef METALS
    //metallicitySF=Gal[p].MetalsColdGas.type2/Gal[p].ColdGas;
	metallicitySF= metals_total(Gal[p].MetalsColdGas)/Gal[p].ColdGas;
#else
    metallicitySF=Gal[p].MetalsColdGas/Gal[p].ColdGas;
#endif
  else