/** @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 deal_with_galaxy_merger(int p, int merger_centralgal, int centralgal, double time, double deltaT, int nstep)
{

/** @brief Deals with the physics triggered by mergers, according to the mass
 *         fraction of the merger \f$(M_{\rm{sat}}/M_{\rm{central}}><0.3)\f$.
 *         Add the cold and stellar phase of the satellite galaxy to the central
 *         one, form a bulge at the central galaxy with the stars from the
 *         satellite in a minor merger if BulgeFormationInMinorMergersOn=1.
 *         Grows black hole through accretion from cold gas "quasar mode". 
 *         If StarBurstRecipe = 0, the Somerville 2001 model
 *         of bursts is used, SN Feedback from starformation is computed and
 *         the sizes of bulge and disk followed. When a major merger occurs,
 *         the disk of both merging galaxies is completely destroyed to form
 *         a bulge. */

  double mi, ma, mass_ratio, Mcstar, Mcgas, Mcbulge, Mpstar, Mpgas,Mpbulge;
  double frac;
#ifdef GALAXYTREE
  int q;

  mass_checks("deal_with_galaxy_merger #0",p);
  mass_checks("deal_with_galaxy_merger #0",merger_centralgal);
  mass_checks("deal_with_galaxy_merger #0",centralgal);

  q = Gal[merger_centralgal].FirstProgGal;
  if(q >= 0)
    {
      while(GalTree[q].NextProgGal >= 0)
        q = GalTree[q].NextProgGal;
        
      GalTree[q].NextProgGal = Gal[p].FirstProgGal;
      
      if(GalTree[q].NextProgGal >= NGalTree)
	{
	  printf("q=%d p=%d GalTree[q].NextProgGal=%d NGalTree=%d\n",
		 q, p, GalTree[q].NextProgGal, NGalTree);
	  terminate("problem");
	}
    }

  if(q < 0)
    terminate("may not happen");

  q = GalTree[q].NextProgGal;

  if(HaloGal[GalTree[q].HaloGalIndex].GalTreeIndex != q)
    terminate("inconsistency");

  HaloGal[GalTree[q].HaloGalIndex].MergeOn = 2;

  if(Gal[p].Type == 1)
    HaloGal[GalTree[q].HaloGalIndex].MergeOn = 3;
#endif


  /* flag galaxy as finished */
  Gal[p].Type = 3;

  /*  calculate mass ratio of merging galaxies */
  mi = Gal[p].DiskMass+Gal[p].BulgeMass+Gal[p].ColdGas;
  ma = Gal[merger_centralgal].DiskMass+Gal[merger_centralgal].BulgeMass+Gal[merger_centralgal].ColdGas;
  if(max(mi,ma) > 0.)
    mass_ratio = min(mi,ma) / max(mi,ma);
  else
    mass_ratio = 1.0;

  /* record the gas and stellar component  mass of merger central and satellite
   * galaxies before the before merger */
  Mcstar=(Gal[merger_centralgal].DiskMass+Gal[merger_centralgal].BulgeMass);
  Mcbulge=Gal[merger_centralgal].BulgeMass;
  Mcgas=Gal[merger_centralgal].ColdGas;
  Mpstar=(Gal[p].DiskMass+Gal[p].BulgeMass);
  Mpbulge=Gal[p].BulgeMass;
  Mpgas=Gal[p].ColdGas;
  
  mass_checks("deal_with_galaxy_merger #1",p);
  mass_checks("deal_with_galaxy_merger #1",merger_centralgal);
  mass_checks("deal_with_galaxy_merger #1",centralgal);

  /* Add the cold and stellar phase of the merged galaxy to the central one.
     Also form a bulge if BulgeFormationInMinorMergersOn is set on, but only
     with the stars from the satellite. In a major merger (dealt at the burst
     make_bulge_from_burst) all the stars in the central and satellite end up
     in the central bulge. */
  add_galaxies_together(merger_centralgal, p);

  mass_checks("deal_with_galaxy_merger #2",p);
  mass_checks("deal_with_galaxy_merger #2",merger_centralgal);
  mass_checks("deal_with_galaxy_merger #2",centralgal);

  /* grow black hole through accretion from cold disk during mergers, as in
   * Kauffmann & Haehnelt (2000) + minor mergers - Quasar Mode */
  if(AGNrecipeOn > 0)
    grow_black_hole(merger_centralgal, mass_ratio, deltaT);

  mass_checks("deal_with_galaxy_merger #3",p);
  mass_checks("deal_with_galaxy_merger #3",merger_centralgal);
  mass_checks("deal_with_galaxy_merger #3",centralgal);

  if (StarBurstRecipe == 0) {
    /* Starburst as in Somerville 2001, with feedback computed inside. */
    frac=collisional_starburst_recipe(mass_ratio, merger_centralgal, centralgal, time, deltaT, nstep);
    bulgesize_from_merger(mass_ratio,merger_centralgal,p,Mcstar,Mcbulge,Mcgas,
			  Mpstar,Mpbulge,Mpgas,frac);

    mass_checks("deal_with_galaxy_merger #3.5",p);
    mass_checks("deal_with_galaxy_merger #3.5",merger_centralgal);
    mass_checks("deal_with_galaxy_merger #3.5",centralgal);

    if(mass_ratio > ThreshMajorMerger)
      make_bulge_from_burst(merger_centralgal);    
  }

  mass_checks("deal_with_galaxy_merger #4",p);
  mass_checks("deal_with_galaxy_merger #4",merger_centralgal);
  mass_checks("deal_with_galaxy_merger #4",centralgal);

  /* If we are in the presence of a minor merger, check disk stability (the disk
   * is completely destroyed in major mergers)*/
  if(TrackDiskInstability)
    if(mass_ratio < ThreshMajorMerger &&
       (Gal[merger_centralgal].DiskMass+Gal[merger_centralgal].BulgeMass) > 0.0)
      check_disk_instability(merger_centralgal);

  /* Not supported option to shrink bulge sizes in gas rich mergers */
#ifdef SHRINKINRICHMERGER  
  if (Mcgas+Mcstar+Mpgas+Mpstar > 1.e-8 ) {
    Gal[merger_centralgal].BulgeSize /= 1+pow((Mcgas+Mpgas)/(Mcgas+Mcstar+Mpgas+Mpstar)/0.15,1.);
    if (Gal[merger_centralgal].BulgeSize < 1.e-8)
      Gal[merger_centralgal].BulgeSize = 1.e-8;
  }
#endif

  if ((Gal[merger_centralgal].BulgeMass > 1.e-6 && Gal[merger_centralgal].BulgeSize == 0.0) ||
      (Gal[merger_centralgal].BulgeMass == 0.0 && Gal[merger_centralgal].BulgeSize >1.e-6)) {
    printf("central: stellarmass %f, bulgemass %f, bulgesize %f, coldgas %f,gasdisk %f,stellardisk %f \n",
    		(Gal[merger_centralgal].DiskMass+Gal[merger_centralgal].BulgeMass),Gal[merger_centralgal].BulgeMass,
    		Gal[merger_centralgal].BulgeSize,Gal[merger_centralgal].ColdGas,Gal[merger_centralgal].GasDiskRadius,
    		Gal[merger_centralgal].StellarDiskRadius);
    exit(0);
  }

  if (DiskRadiusMethod == 2) {
    get_gas_disk_radius(merger_centralgal);
    get_stellar_disk_radius(merger_centralgal);
  }

  mass_checks("deal_with_galaxy_merger #5",p);
  mass_checks("deal_with_galaxy_merger #5",merger_centralgal);
  mass_checks("deal_with_galaxy_merger #5",centralgal);

}
//void update_from_star_formation(int p, double time, double stars, double metallicity)
void update_from_star_formation(int p, double stars, bool flag_burst, int nstep)
{
  int i;
  double fraction;
  double stars_to_add=0.;

  if(Gal[p].ColdGas <= 0. || stars <= 0.) {
    printf("update_from_star_formation: Gal[p].ColdGas <= 0. || stars <= 0.\n");
    exit(0);
  }

  /* If DETAILED_METALS_AND_MASS_RETURN, no longer an assumed instantaneous
   * recycled fraction. Mass is returned over time via SNe and AGB winds.
   * Update the Stellar Spin when forming stars */
#ifndef DETAILED_METALS_AND_MASS_RETURN
  stars_to_add=(1 - RecycleFraction) * stars;
#else
  stars_to_add=stars;
#endif

  if (Gal[p].DiskMass+stars_to_add > 1.e-8)
    for (i = 0; i < 3; i++)
      Gal[p].StellarSpin[i]=((Gal[p].StellarSpin[i])*(Gal[p].DiskMass) + stars_to_add*Gal[p].GasSpin[i])/(Gal[p].DiskMass+stars_to_add);

    /*  Update Gas and Metals from star formation */
  mass_checks("update_from_star_formation #0",p);

  fraction=stars_to_add/Gal[p].ColdGas;


#ifdef STAR_FORMATION_HISTORY
  Gal[p].sfh_DiskMass[Gal[p].sfh_ibin]+=stars_to_add; //ROB: Now, all SF gas is put in SFH array ("recycled' mass will return to gas phase over time)
  Gal[p].sfh_MetalsDiskMass[Gal[p].sfh_ibin] = metals_add(Gal[p].sfh_MetalsDiskMass[Gal[p].sfh_ibin],Gal[p].MetalsColdGas,fraction);
#ifdef INDIVIDUAL_ELEMENTS
  Gal[p].sfh_ElementsDiskMass[Gal[p].sfh_ibin] = elements_add(Gal[p].sfh_ElementsDiskMass[Gal[p].sfh_ibin],Gal[p].ColdGas_elements,fraction);
#endif
#ifdef TRACK_BURST
  if (flag_burst) Gal[p].sfh_BurstMass[Gal[p].sfh_ibin]+=stars_to_add;
#endif
#endif


  Gal[p].MetalsDiskMass=metals_add(Gal[p].MetalsDiskMass,Gal[p].MetalsColdGas,fraction);
  Gal[p].MetalsColdGas=metals_add(Gal[p].MetalsColdGas,Gal[p].MetalsColdGas,-fraction);

  //GLOBAL PROPERTIES
  Gal[p].DiskMass += stars_to_add;
  Gal[p].ColdGas -= stars_to_add;
#ifdef INDIVIDUAL_ELEMENTS
  Gal[p].DiskMass_elements=elements_add(Gal[p].DiskMass_elements,Gal[p].ColdGas_elements,fraction);
  Gal[p].ColdGas_elements=elements_add(Gal[p].ColdGas_elements,Gal[p].ColdGas_elements,-fraction);
#endif
#ifdef TRACK_BURST
  if (flag_burst) Gal[p].BurstMass+=stars_to_add;
#endif

  mass_checks("update_from_star_formation #1",p);

  /* Formation of new metals - instantaneous recycling approximation - only SNII
   * Also recompute the metallicity of the cold phase.*/
#ifndef DETAILED_METALS_AND_MASS_RETURN
  /* stars used because the Yield is defined as a fraction of
   * all stars formed, not just long lived */
  Gal[p].MetalsColdGas += Yield * stars;
#endif

  if (DiskRadiusModel == 0)
    get_stellar_disk_radius(p);

}