/**@brief join_galaxies_of_progenitors() updates the properties of the
 *        galaxy from the dark matter halo properties and deals with
 *        merging clocks. This routine is called by construct_galaxies
 *        for every halo in the FOF being constructed. When there is no
 *        galaxy in the Halo of FirstProgenitor, the first_occupied
 *        pointer is changed to a subhalo which have the maximum mass.
 *
 *        For a central galaxy it just updates its properties. For
 *        satellites it needs to know its most massive (or only progenitor)
 *        to keep track of the merging clock. It also finds the central
 *        galaxies into which galaxies should merge. Type 1's
 *        can merge if their baryonic mass is bigger than the dark matter
 *        mass and type 2's can merge into them. Once the type 1's merge
 *        into a type 0 all its satellites will have the merging clock
 *        into the type 0 reset .
 * */
int join_galaxies_of_progenitors(int halonr, int ngalstart, int *cenngal)
{
  int ngal, prog, i, j, first_occupied, lenmax, centralgal, mostmassive;


  lenmax = 0;
  first_occupied = Halo[halonr].FirstProgenitor;
  prog = Halo[halonr].FirstProgenitor;


  /* When there is no galaxy in the Halo of FirstProgenitor, the first_occupied
   * pointer is changed to a subhalo which have the maximum mass (This should
   * only happen in the case that the leaf on the firstprogenitor branch occurs
   * as a subhalo, in that case no galaxy would be assigned to it). */
  if(prog >= 0)			//If halo has progenitors
    {
      if(HaloAux[prog].NGalaxies == 0)	//if progenitor has no galaxies
	while(prog >= 0)
	  {
	    int currentgal;

	    for(i = 0, currentgal = HaloAux[prog].FirstGalaxy; i < HaloAux[prog].NGalaxies; i++)
	      {
		if(HaloGal[currentgal].Type == 0 || HaloGal[currentgal].Type == 1)
		  {
		    if(Halo[prog].Len > lenmax)
		      {
			lenmax = Halo[prog].Len;
			first_occupied = prog;	//define the new first_occupied
		      }
		  }
		currentgal = HaloGal[currentgal].NextGalaxy;
	      }
	    prog = Halo[prog].NextProgenitor;
	  }
    }
   
  lenmax = 0;
  prog = Halo[halonr].FirstProgenitor;
  mostmassive = Halo[halonr].FirstProgenitor;

  /* loop through all the progenitors and get the halo mass and ID
   * of the most massive*/
  while(prog >= 0)
    {
      if(Halo[prog].Len > lenmax)
	{
	  lenmax = Halo[prog].Len;
	  mostmassive = prog;
	}
      prog = Halo[prog].NextProgenitor;
    }

  ngal = ngalstart;
  prog = Halo[halonr].FirstProgenitor;

  while(prog >= 0)
    {
      int currentgal;
      for(i = 0, currentgal = HaloAux[prog].FirstGalaxy; i < HaloAux[prog].NGalaxies; i++)
	{
	  if(ngal >= MaxGal)
	    {
	      AllocValue_MaxGal *= ALLOC_INCREASE_FACTOR;
	      MaxGal = AllocValue_MaxGal;
	      if(MaxGal<ngal+1) MaxGal=ngal+1;
	      Gal = myrealloc_movable(Gal, sizeof(struct GALAXY) * MaxGal);
	    }
	  if(*cenngal==currentgal)
	    *cenngal=ngal;

	  /* Copy galaxy properties from progenitor,
	   * except for those that need initialising */
	  Gal[ngal] = HaloGal[currentgal];

	  Gal[ngal].HaloNr = halonr;
	  Gal[ngal].CoolingRadius = 0.0;
	  Gal[ngal].CoolingGas = 0.0;

	  Gal[ngal].PrimordialAccretionRate = 0.0;
	  Gal[ngal].CoolingRate = 0.0;
	  Gal[ngal].CoolingRate_beforeAGN = 0.0;
	  Gal[ngal].Sfr = 0.0;
	  Gal[ngal].SfrBulge = 0.0;
	  Gal[ngal].QuasarAccretionRate=0.0;
	  Gal[ngal].RadioAccretionRate=0.0;
#ifdef GALAXYTREE
	  Gal[ngal].FirstProgGal = HaloGal[currentgal].GalTreeIndex;	/* CHECK */
#endif
	  // To fail this check means that we copy in a failed galaxy
	  mass_checks("Middle of join_galaxies_of_progenitors",ngal);

	  /* Update Properties of this galaxy with physical properties of halo */
	  /* this deals with the central galaxies of subhalos */
	  if(Gal[ngal].Type == 0 || Gal[ngal].Type == 1)
	    {
	      if(prog == first_occupied)
		{
#ifdef HALOPROPERTIES
		  Gal[ngal].HaloM_Mean200 = Halo[halonr].M_Mean200;
		  Gal[ngal].HaloM_Crit200 = Halo[halonr].M_Crit200;
		  Gal[ngal].HaloM_TopHat = Halo[halonr].M_TopHat;
		  Gal[ngal].HaloVelDisp = Halo[halonr].VelDisp;
		  Gal[ngal].HaloVmax = Halo[halonr].Vmax;
#endif
		  Gal[ngal].MostBoundID = Halo[halonr].MostBoundID;
		  for(j = 0; j < 3; j++)
		    {
		      Gal[ngal].Pos[j] = Halo[halonr].Pos[j];
		      Gal[ngal].Vel[j] = Halo[halonr].Vel[j];
#ifdef HALOPROPERTIES
		      Gal[ngal].HaloPos[j] = Halo[halonr].Pos[j];
		      Gal[ngal].HaloVel[j] = Halo[halonr].Vel[j];
#endif
		    }

		  Gal[ngal].Len = Halo[halonr].Len;

		  // FOFCentralGal property in case that is different from FirstGalaxy
		  if(halonr == Halo[halonr].FirstHaloInFOFgroup)
		    update_centralgal(ngal, halonr);
		  else
		    update_type_1(ngal, halonr, prog);

		  if(DiskRadiusModel == 1 || DiskRadiusModel == 2)
		    {
		      Gal[ngal].GasDiskRadius = get_disk_radius(halonr, ngal);
		      Gal[ngal].StellarDiskRadius = Gal[ngal].GasDiskRadius;
		    }
		  Gal[ngal].Vmax = Halo[halonr].Vmax;
		}
	      else //type 2 galaxies
		{
		  update_type_2(ngal, halonr, prog, mostmassive);
		}
	    }

	  /* Note: Galaxies that are already type=2 do not need a special treatment at this point */
	  if(Gal[ngal].Type < 0 || Gal[ngal].Type > 2)
	    terminate("Unknown galaxy type\n");

	  ngal++;

	  currentgal = HaloGal[currentgal].NextGalaxy;
	}

      prog = Halo[prog].NextProgenitor;
    }


  /* If there are no progenitors with galaxies, a new galaxy is created.
   * However, if it's a subhalo, no galaxy is placed, since it would stay
   * at zero luminosity. */
  if(ngal == 0)
    {
      *cenngal=0;

      if(Halo[halonr].FirstHaloInFOFgroup == halonr)
	{
	  init_galaxy(ngal, halonr);
	  ngal++;
	}
    }

  /* satelites (type 2's) will preferably merge onto this type 1 rather than the type 0 */
  for(i = ngalstart, centralgal = -1; i < ngal; i++)
    if(Gal[i].Type == 0 || Gal[i].Type == 1)
      {
	if(centralgal != -1)
	  terminate("Subhalo hosts more than one Type 0/1\n");

	centralgal = i;
      }

  for(i = ngalstart; i < ngal; i++)
    {
      Gal[i].CentralGal = centralgal;
      if(centralgal != -1)
	for(j = 0; j < 3; j++)
	  Gal[i].MergCentralPos[j] = Gal[centralgal].Pos[j];
    }

  /* Satellites whose type 1 has merged into type 0, will be reset to merge
   * into the type 0. */
  if(centralgal == -1 && ngal != ngalstart)
    {
      for(i = ngalstart; i < ngal; i++)
  	{
	  Gal[i].CentralGal = *cenngal;
	  for(j = 0; j < 3; j++)
	    Gal[i].MergCentralPos[j] = Gal[*cenngal].Pos[j];
  	}
    }
  
  for (i = ngalstart; i<ngal; i++)
    mass_checks("Bottom of join_galaxies_of_progenitors",i);
  
  report_memory_usage(&HighMark, "join_galaxies");

  return ngal;
}
Ejemplo n.º 2
0
int join_galaxies_of_progenitors(int halonr, int ngalstart)
{
  int ngal, prog, mother_halo=-1, i, j, first_occupied, lenmax, lenoccmax, centralgal;
  double previousMvir, previousVvir, previousVmax;
  int step;

  lenmax = 0;
  lenoccmax = 0;
  first_occupied = Halo[halonr].FirstProgenitor;
  prog = Halo[halonr].FirstProgenitor;

  if(prog >=0)
    if(HaloAux[prog].NGalaxies > 0)
    lenoccmax = -1;

  // Find most massive progenitor that contains an actual galaxy
  // Maybe FirstProgenitor never was FirstHaloInFOFGroup and thus has no galaxy

  while(prog >= 0)
  {
    if(Halo[prog].Len > lenmax)
    {
      lenmax = Halo[prog].Len;
      mother_halo = prog;
    }
    if(lenoccmax != -1 && Halo[prog].Len > lenoccmax && HaloAux[prog].NGalaxies > 0)
    {
      lenoccmax = Halo[prog].Len;
      first_occupied = prog;
    }
    prog = Halo[prog].NextProgenitor;
  }

  ngal = ngalstart;
  prog = Halo[halonr].FirstProgenitor;

  while(prog >= 0)
  {
    for(i = 0; i < HaloAux[prog].NGalaxies; i++)
    {
			assert(ngal < FoF_MaxGals);

      // This is the cruical line in which the properties of the progenitor galaxies 
      // are copied over (as a whole) to the (temporary) galaxies Gal[xxx] in the current snapshot 
      // After updating their properties and evolving them 
      // they are copied to the end of the list of permanent galaxies HaloGal[xxx] 

      Gal[ngal] = HaloGal[HaloAux[prog].FirstGalaxy + i];
      Gal[ngal].HaloNr = halonr;

      Gal[ngal].dT = -1.0;

      // this deals with the central galaxies of (sub)halos 
      if(Gal[ngal].Type == 0 || Gal[ngal].Type == 1)
      {
        // this halo shouldn't hold a galaxy that has already merged; remove it from future processing
        if(Gal[ngal].mergeType != 0)
        {
          Gal[ngal].Type = 3;
          continue;
        }

        // remember properties from the last snapshot
        previousMvir = Gal[ngal].Mvir;
        previousVvir = Gal[ngal].Vvir;
        previousVmax = Gal[ngal].Vmax;

        if(prog == first_occupied)
        {
          // update properties of this galaxy with physical properties of halo 
          Gal[ngal].MostBoundID = Halo[halonr].MostBoundID;

          for(j = 0; j < 3; j++)
          {
            Gal[ngal].Pos[j] = Halo[halonr].Pos[j];
            Gal[ngal].Vel[j] = Halo[halonr].Vel[j];
          }
					
          Gal[ngal].Len = Halo[halonr].Len;
          Gal[ngal].Vmax = Halo[halonr].Vmax;

					Gal[ngal].deltaMvir = get_virial_mass(halonr) - Gal[ngal].Mvir;

          if(get_virial_mass(halonr) > Gal[ngal].Mvir)
          {
            Gal[ngal].Rvir = get_virial_radius(halonr);  // use the maximum Rvir in model
            Gal[ngal].Vvir = get_virial_velocity(halonr);  // use the maximum Vvir in model
          }
          Gal[ngal].Mvir = get_virial_mass(halonr);

          Gal[ngal].Cooling = 0.0;
          Gal[ngal].Heating = 0.0;
          Gal[ngal].QuasarModeBHaccretionMass = 0.0;
          Gal[ngal].OutflowRate = 0.0;
          Gal[ngal].Lx_bol = 0.0;

          for(step = 0; step < STEPS; step++)
          {
            Gal[ngal].SfrDisk[step] = Gal[ngal].SfrBulge[step] = 0.0;
            Gal[ngal].SfrDiskColdGas[step] = Gal[ngal].SfrDiskColdGasMetals[step] = 0.0;
            Gal[ngal].SfrBulgeColdGas[step] = Gal[ngal].SfrBulgeColdGasMetals[step] = 0.0;
          }

          if(halonr == Halo[halonr].FirstHaloInFOFgroup)
          {
            // a central galaxy
            Gal[ngal].mergeType = 0;
            Gal[ngal].mergeIntoID = -1;
            Gal[ngal].MergTime = 999.9;            

            Gal[ngal].DiskScaleRadius = get_disk_radius(halonr, ngal);

            Gal[ngal].Type = 0;
          }
          else
          {
            // a satellite with subhalo
            Gal[ngal].mergeType = 0;
            Gal[ngal].mergeIntoID = -1;

            if(Gal[ngal].Type == 0)  // remember the infall properties before becoming a subhalo
            {
              Gal[ngal].infallMvir = previousMvir;
              Gal[ngal].infallVvir = previousVvir;
              Gal[ngal].infallVmax = previousVmax;
            }

            if(Gal[ngal].Type == 0 || Gal[ngal].MergTime > 999.0)
              // here the galaxy has gone from type 1 to type 2 or otherwise doesn't have a merging time.
              Gal[ngal].MergTime = estimate_merging_time(halonr, Halo[halonr].FirstHaloInFOFgroup, ngal);
            
            Gal[ngal].Type = 1;
          }
        }
        else
        {
          // an orhpan satellite galaxy - these will merge or disrupt within the current timestep
          Gal[ngal].deltaMvir = -1.0*Gal[ngal].Mvir;
          Gal[ngal].Mvir = 0.0;

          if(Gal[ngal].MergTime > 999.0 || Gal[ngal].Type == 0)
          {
            // here the galaxy has gone from type 0 to type 2 - merge it!
            Gal[ngal].MergTime = 0.0;
          
            Gal[ngal].infallMvir = previousMvir;
            Gal[ngal].infallVvir = previousVvir;
            Gal[ngal].infallVmax = previousVmax;
          }

          Gal[ngal].Type = 2;
        }
      }

      ngal++;

    }

    prog = Halo[prog].NextProgenitor;
  }

  if(ngal == 0)
  {
    // We have no progenitors with galaxies. This means we create a new galaxy. 
    init_galaxy(ngal, halonr);
    ngal++;
  }

  // Per Halo there can be only one Type 0 or 1 galaxy, all others are Type 2  (orphan)
  // In fact, this galaxy is very likely to be the first galaxy in the halo if 
	// first_occupied==FirstProgenitor and the Type0/1 galaxy in FirstProgenitor was also the first one 
  // This cannot be guaranteed though for the pathological first_occupied!=FirstProgenitor case 

  for(i = ngalstart, centralgal = -1; i < ngal; i++)
  {
    if(Gal[i].Type == 0 || Gal[i].Type == 1)
    {
			assert(centralgal == -1);
      centralgal = i;
    }
  }

  for(i = ngalstart; i < ngal; i++)
    Gal[i].CentralGal = centralgal;

  return ngal;

}