Exemple #1
0
Cell* ReadCells(MPI_Comm comm, const char* cellfile, int &Ncells) {
    int nprocs, myid, root;
    Cell* cells;

    MPI_Comm_size(comm, &nprocs);
    MPI_Comm_rank(comm, &myid);
    root = 0;

    /* Have root process read in cells */
    if(myid == root) {
        size_t n, size;
        char endian;
        char fmt[ABN_MAX_FORMAT_LENGTH];
        Config cellopts = cfg_new();

        /* Read basis cells from file */
        FILE* fcells = fopen(cellfile, "r");
        if(fcells == NULL) {
            fprintf(stderr, "ReadCells: could not read cells from '%s'\n", cellfile);
            MPI_Abort(comm, 1);
        }
        if(abn_read(fcells, (void**) &cells, &n, &size, &endian, fmt, cellopts) != 0) {
            report_memory_usage();
            fprintf(stderr, "ReadCells: error reading cells from '%s'\n", cellfile);
            MPI_Abort(comm, 1);
        }
        fclose(fcells);

        Ncells = cfg_get_int(cellopts, "Ncells");
        if((int)n != Ncells)
            fprintf(stderr, "Warning: consistency check fail for Ncells: %d != %d\n", Ncells, (int)n);
        if(size != sizeof(Cell))
            fprintf(stderr, "Warning: consistency check fail for sizeof(Cell): %d != %d\n", (int)sizeof(Cell), (int)size);

        /* Debugging... */
        printf("Read %d basis cells from '%s'\n", Ncells, cellfile);
    }
    MPI_Bcast(&Ncells, 1, MPI_INT, root, comm);

    /* Define MPI datatype for cells (this must be updated if struct Cell changes!) */
    MPI_Datatype cell_datatype;
    int blocklengths[2] = { 2, 8 };
    MPI_Aint displacements[2] = { 0, 8 };
    MPI_Datatype types[2] = { MPI_INT, MPI_DOUBLE };
    MPI_Type_create_struct(2, blocklengths, displacements, types, &cell_datatype);
    MPI_Type_commit(&cell_datatype);

    /* Broadcast cell data to all other processes */
    if(myid != root) {
        cells = (Cell*) malloc(Ncells*sizeof(Cell));
        if(cells == NULL) {
            fprintf(stderr, "ReadCells: could not allocate memory for cells on process %d\n", myid);
            MPI_Abort(comm, 1);
        }
    }
    MPI_Bcast(cells, Ncells, cell_datatype, root, comm);
    return cells;
}
static sfsistat
mlfi_close (SMFICTX *context)
{
    if (report_request) {
        g_print("close\n");
    }

    if (report_memory_profile) {
        report_memory_usage();
    }

    return SMFIS_ACCEPT;
}
/* Note: halonr is here the FOF-background subhalo (i.e. main halo) */
void evolve_galaxies(int halonr, int ngal, int treenr, int cenngal)
{
  int p, q, nstep, centralgal, merger_centralgal, currenthalo, prevgal, start, i;
  double infallingGas, deltaT, Zcurr;
  double time, previoustime, newtime;
  double AGNaccreted, t_Edd;
#ifdef STAR_FORMATION_HISTORY
  double age_in_years;
#endif

  // Eddington time in code units
  // code units are UnitTime_in_s/Hubble_h
  t_Edd=1.42e16*Hubble_h/UnitTime_in_s;

  //previoustime = NumToTime(Gal[0].SnapNum);
  previoustime = NumToTime(Halo[halonr].SnapNum-1);
  newtime = NumToTime(Halo[halonr].SnapNum);

  /* Time between snapshots */
  deltaT = previoustime - newtime;
  /* Redshift of current Snapnum */
  Zcurr = ZZ[Halo[halonr].SnapNum];

  centralgal = Gal[0].CentralGal;
	
  for (p =0;p<ngal;p++)
	  mass_checks("Evolve_galaxies #0",p);

  //print_galaxy("\n\ncheck1", centralgal, halonr);

 if(Gal[centralgal].Type != 0 || Gal[centralgal].HaloNr != halonr)
    terminate("Something wrong here ..... \n");

  /* Update all galaxies to same star-formation history time-bins.
   * Needed in case some galaxy has skipped a snapshot. */
#ifdef STAR_FORMATION_HISTORY
  age_in_years=(Age[0]-previoustime)*UnitTime_in_years/Hubble_h; //ROB: age_in_years is in units of "real years"!
  nstep=0;
  for (p=0; p<ngal; p++)
    sfh_update_bins(p,Halo[halonr].SnapNum-1,nstep,age_in_years);
#endif

  /* Handle the transfer of mass between satellites and central galaxies */
  deal_with_satellites(centralgal, ngal);

  /* Delete inconsequential galaxies */
  for (p =0;p<ngal;p++)
    if (Gal[p].Type ==2 && Gal[p].ColdGas+Gal[p].DiskMass+Gal[p].BulgeMass <1.e-8)
      Gal[p].Type = 3;
    else
      mass_checks("Evolve_galaxies #0.1",p);
   
  /* Calculate how much hot gas needs to be accreted to give the correct baryon fraction
   * in the main halo. This is the universal fraction, less any reduction due to reionization. */
  infallingGas = infall_recipe(centralgal, ngal, Zcurr);
  Gal[centralgal].PrimordialAccretionRate=infallingGas/deltaT;
  
  /* All the physics are computed in a number of intervals between snapshots
   * equal to STEPS */
  for (nstep = 0; nstep < STEPS; nstep++)
    {
      /* time to present of the current step */
      time = previoustime - (nstep + 0.5) * (deltaT / STEPS);

      /* Update all galaxies to the star-formation history time-bins of current step*/
#ifdef STAR_FORMATION_HISTORY
      age_in_years=(Age[0]-time)*UnitTime_in_years/Hubble_h;
      for (p=0; p<ngal; p++)
	sfh_update_bins(p,Halo[halonr].SnapNum-1,nstep,age_in_years);

#endif

      /* Infall onto central galaxy only, if required to make up a baryon deficit */
#ifndef GUO10
#ifndef GUO13
      if (infallingGas > 0.)
#endif
#endif
	add_infall_to_hot(centralgal, infallingGas / STEPS);

      mass_checks("Evolve_galaxies #0.5",centralgal);

      for (p = 0; p < ngal; p++)
	{
	  /* don't treat galaxies that have already merged */
	  if(Gal[p].Type == 3)
	    continue;
	  mass_checks("Evolve_galaxies #1",p);

	  if (Gal[p].Type == 0 || Gal[p].Type == 1)
	    {
	      reincorporate_gas(p, deltaT / STEPS);
	      /* determine cooling gas given halo properties and add it to the cold phase*/
	      mass_checks("Evolve_galaxies #1.5",p);
	      compute_cooling(p, deltaT / STEPS, ngal);
	    }
	}

      //this must be separated as now satellite AGN can heat central galaxies
      //therefore the AGN from all satellites must be computed, in a loop inside this function,
      //before gas is cooled into central galaxies (only suppress cooling, the gas is not actually heated)
      if(AGNRadioModeModel != 5)
	do_AGN_heating(deltaT / STEPS, ngal);

      for (p = 0; p < ngal; p++)
	{
	  cool_gas_onto_galaxy(p, deltaT / STEPS);
	  mass_checks("Evolve_galaxies #2",p);
	  starformation(p, centralgal, time, deltaT / STEPS, nstep);
	  mass_checks("Evolve_galaxies #3",p);
	  //print_galaxy("check3", centralgal, halonr);
	}

      /* Check for merger events */
      for(p = 0; p < ngal; p++)
	{
	  if(Gal[p].Type == 2 || (Gal[p].Type == 1 && Gal[p].MergeOn == 1))	/* satellite galaxy */
	    {
	      Gal[p].MergTime -= deltaT / STEPS;
	      if(Gal[p].MergTime < 0.0)
		{
		  NumMergers++;

		  if(Gal[p].Type == 1)
		    for(q = 0; q < ngal; q++)
		      if(Gal[q].Type == 2 && Gal[p].CentralGal == p)
			Gal[q].CentralGal = cenngal;

		  if(Gal[p].Type == 2)
		    merger_centralgal = Gal[p].CentralGal;
		  else
		    merger_centralgal = cenngal;

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

		  deal_with_galaxy_merger(p, merger_centralgal, centralgal, time, deltaT, nstep);

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

		}
	    }
	}//loop on all galaxies to detect mergers

#ifdef DETAILED_METALS_AND_MASS_RETURN
      //DELAYED ENRICHMENT AND MASS RETURN + FEEDBACK: No fixed yield or recycling fraction anymore. FB synced with enrichment
      for (p = 0; p < ngal; p++)
	update_yields_and_return_mass(p, centralgal, deltaT/STEPS, nstep);
#endif

    }/* end move forward in interval STEPS */

  for(p = 0; p < ngal; p++)
    {
      if(Gal[p].Type == 2)
	{
#ifndef UPDATETYPETWO
	  int jj;
	  float tmppos;
	  for(jj = 0; jj < 3; jj++)
	    {
	      tmppos = wrap(Gal[p].DistanceToCentralGal[jj],BoxSize);
	      tmppos *=  2.*sqrt(Gal[p].MergTime/Gal[p].OriMergTime);
	      Gal[p].Pos[jj] = Gal[p].MergCentralPos[jj] + tmppos;

	      if(Gal[p].Pos[jj] < 0)
		Gal[p].Pos[jj] = BoxSize + Gal[p].Pos[jj];
	      if(Gal[p].Pos[jj] > BoxSize)
		Gal[p].Pos[jj] = Gal[p].Pos[jj] - BoxSize;
	    }
#endif
	  /* Disruption of type 2 galaxies. Type 1 galaxies are not disrupted since usually
	   * bayonic component is more compact than dark matter.*/

	  if(DisruptionModel==0)
	    disrupt(p);
	}
    }

  for (p =0;p<ngal;p++)
    mass_checks("Evolve_galaxies #6",p);
  
#ifdef COMPUTE_SPECPHOT_PROPERTIES
#ifndef  POST_PROCESS_MAGS
  int n;
  /* If this is an output snapshot apply the dust model to each galaxy */
  for(n = 0; n < NOUT; n++)
    {
      if(Halo[halonr].SnapNum == ListOutputSnaps[n])
        {
    	  for(p = 0; p < ngal; p++)
    		  dust_model(p, n, halonr);
    	  break;
        }
    }
#endif  //POST_PROCESS_MAGS
#endif //COMPUTE_SPECPHOT_PROPERTIES

  /* now save the galaxies of all the progenitors (and free the associated storage) */
  int prog = Halo[halonr].FirstProgenitor;

  while(prog >= 0)
    {
      int currentgal;
      for(i = 0, currentgal = HaloAux[prog].FirstGalaxy; i < HaloAux[prog].NGalaxies; i++)
        {
    	  int nextgal = HaloGal[currentgal].NextGalaxy;
    	  /* this will write this galaxy to an output file and free the storage associate with it */
    	  output_galaxy(treenr, HaloGal[currentgal].HeapIndex);
    	  currentgal = nextgal;
        }
      prog = Halo[prog].NextProgenitor;
    }

  for(p = 0, prevgal = -1, currenthalo = -1, centralgal = -1, start = NGalTree; p < ngal; p++)
    {
      if(Gal[p].HaloNr != currenthalo)
	{
	  currenthalo = Gal[p].HaloNr;
	  HaloAux[currenthalo].FirstGalaxy = -1;
	  HaloAux[currenthalo].NGalaxies = 0;
	}

      mass_checks("Evolve_galaxies #7",p);

      if(Gal[p].Type != 3)
	{
	  if(NHaloGal >= MaxHaloGal)
	    {
	      int oldmax = MaxHaloGal;
	      AllocValue_MaxHaloGal *= ALLOC_INCREASE_FACTOR;
	      MaxHaloGal = AllocValue_MaxHaloGal;
	      if(MaxHaloGal<NHaloGal+1)
		MaxHaloGal=NHaloGal+1;
	      HaloGal = myrealloc_movable(HaloGal, sizeof(struct GALAXY) * MaxHaloGal);
	      HaloGalHeap = myrealloc_movable(HaloGalHeap, sizeof(int) * MaxHaloGal);
	      for(i = oldmax; i < MaxHaloGal; i++)
		HaloGalHeap[i] = i;
	    }

	  Gal[p].SnapNum = Halo[currenthalo].SnapNum;

#ifndef GUO10
#ifdef UPDATETYPETWO
	  update_type_two_coordinate_and_velocity(treenr, p, Gal[0].CentralGal);
#endif
#endif

	  /* when galaxies are outputed, the slot is filled with the
	   * last galaxy in the heap. New galaxies always take the last spot */
	  int nextgal = HaloGalHeap[NHaloGal];
	  HaloGal[nextgal] = Gal[p];
	  HaloGal[nextgal].HeapIndex = NHaloGal;

	  if(HaloAux[currenthalo].FirstGalaxy < 0)
	    HaloAux[currenthalo].FirstGalaxy = nextgal;

	  if(prevgal >= 0)
	    HaloGal[prevgal].NextGalaxy = nextgal;
	  prevgal = nextgal;

	  HaloAux[currenthalo].NGalaxies++;
	  NHaloGal++;


#ifdef GALAXYTREE
	  if(NGalTree >= MaxGalTree)
	    {
	      AllocValue_MaxGalTree *= ALLOC_INCREASE_FACTOR;
	      MaxGalTree = AllocValue_MaxGalTree;
	      if(MaxGalTree<NGalTree+1) MaxGalTree=NGalTree+1;
	      GalTree = myrealloc_movable(GalTree, sizeof(struct galaxy_tree_data) * MaxGalTree);
	    }
	  HaloGal[nextgal].GalTreeIndex = NGalTree;

	  memset(&GalTree[NGalTree], 0, sizeof(struct galaxy_tree_data));
	  GalTree[NGalTree].HaloGalIndex = nextgal;
	  GalTree[NGalTree].SnapNum = Halo[currenthalo].SnapNum;
	  GalTree[NGalTree].NextProgGal = -1;
	  GalTree[NGalTree].DescendantGal = -1;

	  GalTree[NGalTree].FirstProgGal = Gal[p].FirstProgGal;
	  if(Gal[p].Type == 0)
	    centralgal = NGalTree;
	  NGalTree++;
#endif
	}
    }

#ifdef GALAXYTREE
  for(p = start; p < NGalTree; p++)
    {
      if(centralgal < 0)
	terminate("centralgal < 0");
      GalTree[p].FOFCentralGal = centralgal;
    }
#endif

  report_memory_usage(&HighMark, "evolve_galaxies");
}
/**@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;
}
Exemple #5
0
/* Note: halonr is here the FOF-background subhalo (i.e. main halo) */
void evolve_galaxies(int halonr, int ngal, int treenr, int cenngal)
{
  int jj, p, q, nstep, centralgal, merger_centralgal, currenthalo, prevgal, start, i;
  double infallingGas, coolingGas, deltaT, Zcurr;  
  double time, previoustime, newtime;
  double AGNaccreted, t_Edd;
#ifdef STAR_FORMATION_HISTORY
  double age_in_years;
#endif
#ifdef HT09_DISRUPTION
  double CentralRadius, CentralMass, SatelliteRadius, SatelliteMass;
#endif

  // Eddington time in code units
  // Bizarrely, code units are UnitTime_in_s/Hubble_h
  t_Edd=1.42e16*Hubble_h/UnitTime_in_s;

  //previoustime = NumToTime(Gal[0].SnapNum);
  previoustime = NumToTime(Halo[halonr].SnapNum-1);
  newtime = NumToTime(Halo[halonr].SnapNum);

  /* Time between snapshots */
  deltaT = previoustime - newtime;
  /* Redshift of current Snapnum */
  Zcurr = ZZ[Halo[halonr].SnapNum];

  //if(halonr == 83)
  //	for(p=0;p<ngal;p++)
  //		printf("check halonr=%d id=%d type=%d\n", halonr, p,Gal[p].Type);


  centralgal = Gal[0].CentralGal;
	
  for (p =0;p<ngal;p++)
	  mass_checks("Evolve_galaxies #0",p);

 if(Gal[centralgal].Type != 0 || Gal[centralgal].HaloNr != halonr)
    terminate("Something wrong here ..... \n");


  /* Update all galaxies to same star-formation history time-bins.
   * Needed in case some galaxy has skipped a snapshot. */
#ifdef STAR_FORMATION_HISTORY
  age_in_years=(Age[0]-previoustime)*UnitTime_in_years/Hubble_h; //ROB: age_in_years is in units of "real years"!
  nstep=0;
  for (p=0; p<ngal; p++)
    sfh_update_bins(p,Halo[halonr].SnapNum-1,nstep,age_in_years);
#endif

  //if(halonr == 84)
   // 	print_galaxy("check00", centralgal, halonr);

    //for(p=0;p<ngal;p++)
    //	printf("prog=%d\n",Halo[halonr].FirstProgenitor);

  /* Handle the transfer of mass between satellites and central galaxies */
  deal_with_satellites(centralgal, ngal);


  /* Delete inconsequential galaxies */
  for (p =0;p<ngal;p++)
    if (Gal[p].Type ==2 && Gal[p].ColdGas+Gal[p].DiskMass+Gal[p].BulgeMass <1.e-8)
      Gal[p].Type = 3;
    else
      mass_checks("Evolve_galaxies #0.1",p);
   
  
  /* Calculate how much hot gas needs to be accreted to give the correct baryon fraction
   * in the main halo. This is the universal fraction, less any reduction due to reionization. */
  infallingGas = infall_recipe(centralgal, ngal, Zcurr);
  Gal[centralgal].PrimordialAccretionRate=infallingGas/deltaT;
  
  //if(halonr > 35 && halonr < 40)
  //	print_galaxy("check02", centralgal, halonr);


  /* All the physics are computed in a number of intervals between snapshots
   * equal to STEPS */
  for (nstep = 0; nstep < STEPS; nstep++)
    {
  	//printf("step=%d\n",nstep);
  	/* time to present of the current step */
	  time = previoustime - (nstep + 0.5) * (deltaT / STEPS);
     

	  /* Update all galaxies to the star-formation history time-bins of current step*/
#ifdef STAR_FORMATION_HISTORY
	  age_in_years=(Age[0]-time)*UnitTime_in_years/Hubble_h;
	  for (p=0; p<ngal; p++)
	  	sfh_update_bins(p,Halo[halonr].SnapNum-1,nstep,age_in_years);

#endif
	  //if(halonr > 35 && halonr < 40)
	 	// 		    	print_galaxy("check02.1", centralgal, halonr);

	  /* Infall onto central galaxy only, if required to make up a baryon deficit */
#ifndef GUO13
#ifndef GUO10
	  if (infallingGas > 0.)
#endif
#endif
	  	add_infall_to_hot(centralgal, infallingGas / STEPS);

	  //if(halonr == 84)
	 	//	    	print_galaxy("check02.5", centralgal, halonr);



	  mass_checks("Evolve_galaxies #0.5",centralgal);
      
	  for (p = 0; p < ngal; p++)
	    {
	  	//if((halonr > 28 && halonr < 32) || Gal[p].HaloNr==52)
	  		//if(Gal[p].SnapNum==31 || (halonr > 28 && halonr < 31))
	  		//	if(halonr ==140)
	  		// print_galaxy("check03", p, halonr);
	  	/* don't treat galaxies that have already merged */
		  if(Gal[p].Type == 3)
			  continue;

		  mass_checks("Evolve_galaxies #1",p);


		  if (Gal[p].Type == 0 || Gal[p].Type == 1)
		  {
		  	if((ReIncorporationRecipe == 0 && Gal[p].Type==0) || ReIncorporationRecipe > 0)
				  reincorporate_gas(p, deltaT / STEPS);
		  	 //if(halonr > 28 && halonr < 31)
		  	//			  print_galaxy("check04", p, halonr);
			  /* determine cooling gas given halo properties and add it to the cold phase*/
			  mass_checks("Evolve_galaxies #1.5",p);
			  coolingGas = cooling_recipe(p, deltaT / STEPS);
			  cool_gas_onto_galaxy(p, coolingGas);
			  //if(halonr > 28 && halonr < 31)
				//if(halonr ==140)
			  //print_galaxy("check05", p, halonr);

		  }


		  mass_checks("Evolve_galaxies #2",p);

#ifdef H2_AND_RINGS
      gas_inflow(p, deltaT / STEPS);
      //if(halonr > 38 && halonr < 40)
      //print_galaxy("check06", p, halonr);
#endif
		  /* stars form*/
		  starformation(p, centralgal, time, deltaT / STEPS, nstep);
		  //int ii;
		  //for (ii = 0; ii < ngal; ii++)
		  //	if(halonr > 28 && halonr < 31)
			//if(halonr ==140)
		  //	print_galaxy("check07", ii, halonr);
		  mass_checks("Evolve_galaxies #3",p);

	    } //for (p = 0; p < ngal; p++)
      
	  /* Check for merger events */
	  //if(Gal[p].Type == 1)
	  //for(p = 0; p < -1; p++)


	  for(p = 0; p < ngal; p++)
	    {
	    //if(halonr == 84)
	  	//	  print_galaxy("check07.01", p, halonr);
	  	#ifdef MERGE01
    	  if(Gal[p].Type == 2 || (Gal[p].Type == 1 && Gal[p].MergeOn == 1))	/* satellite galaxy */
#else
    	  if(Gal[p].Type == 2)
#endif
    	    {    		  
    		  Gal[p].MergTime -= deltaT / STEPS;

#ifdef HT09_DISRUPTION
    		  Gal[p].MergRadius -= get_deltar(p, deltaT/STEPS );
    		  if(Gal[p].MergRadius<0.)
    		  	Gal[p].MergRadius=0.;
    		  //printf("merge radius=%f detlar=%f\n",Gal[p].MergRadius, 100.*get_deltar(p, deltaT/STEPS ));
    		  disruption_code (p, time);

    		  /* a merger has occured! */
    		  //MergRadius is tracked for type 2's subject to disruption while MergTime is tracked for type 1's
    		 // if( ( Gal[p].Type == 2 && (Gal[p].MergRadius < Gal[centralgal].StellarDiskRadius+Gal[centralgal].BulgeSize || Gal[p].BulgeMass+Gal[p].DiskMass == 0) )
    			//	  || (Gal[p].Type == 1 && Gal[p].MergTime < 0.0))
    		 if( Gal[p].MergRadius < Gal[centralgal].StellarDiskRadius+Gal[centralgal].BulgeSize || Gal[p].BulgeMass+Gal[p].DiskMass == 0 )


    		  //if(Gal[p].MergTime < 0.0 || Gal[p].BulgeMass+Gal[p].DiskMass == 0)
#else
    		  if(Gal[p].MergTime < 0.0)
#endif
    		    {
    			  NumMergers++;

#ifdef MERGE01
    			  if(Gal[p].Type == 1)
    			  	for(q = 0; q < ngal; q++)
    			  		if(Gal[q].Type == 2 && Gal[p].CentralGal == p)
    			  			Gal[q].CentralGal = cenngal;

    			  if(Gal[p].Type == 2)
    				merger_centralgal = Gal[p].CentralGal;
    			  else
    				merger_centralgal = cenngal;
#else
    			  merger_centralgal = Gal[p].CentralGal;
#endif
    			 
    			  mass_checks("Evolve_galaxies #4",p);
    			  mass_checks("Evolve_galaxies #4",merger_centralgal);
    			  mass_checks("Evolve_galaxies #4",centralgal);
    			  //if(halonr == 140)
    			  //print_galaxy("check08", p, halonr);
    			  //if(halonr == 140)
    			  //print_galaxy("check09", merger_centralgal, halonr);
    			  deal_with_galaxy_merger(p, merger_centralgal, centralgal, time, deltaT, nstep);
    			  //if(halonr == 140)
    			  //print_galaxy("check10", p, halonr);
    			  //if(halonr == 140)
    			  //print_galaxy("check11", merger_centralgal, halonr);
    			  mass_checks("Evolve_galaxies #5",p);
    			  mass_checks("Evolve_galaxies #5",merger_centralgal);
    			  mass_checks("Evolve_galaxies #5",centralgal);

    		    }

    	    }// if(Gal[p].Type == 2)
	    }//loop on all galaxies to detect mergers

	  /* Cool gas onto AGN */
	  if (BlackHoleGrowth == 1)
	  {
		  for (p = 0; p < ngal; p++)
		  {
		  	AGNaccreted=min(Gal[p].BlackHoleGas, Gal[p].BlackHoleMass*BlackHoleAccretionRate*deltaT/(STEPS*t_Edd));
			  if (AGNaccreted > 0.)
			  {
				  Gal[p].BlackHoleMass += AGNaccreted;
				  Gal[p].BlackHoleGas -= AGNaccreted;
				  // Instantaneous accretion rate.  This will get overwritten on each mini-step but that's OK
				  Gal[p].QuasarAccretionRate = AGNaccreted*STEPS/deltaT;
			  }
		  }
	  }
	  
	  //DELAYED ENRICHMENT AND MASS RETURN + FEEDBACK: No fixed yield or recycling fraction anymore. FB synced with enrichment
	  for (p = 0; p < ngal; p++)
	  {
#ifdef DETAILED_METALS_AND_MASS_RETURN
	  update_yields_and_return_mass(p, centralgal, deltaT/STEPS, nstep);
#endif
	  }	  

#ifdef ALL_SKY_LIGHTCONE
	  int nr, istep, ix, iy, iz;
	  istep = Halo[halonr].SnapNum*STEPS + nstep;
	  Gal[p].SnapNum = Halo[halonr].SnapNum;
	  for (p = 0; p < ngal; p++)
	  	for (nr = 0; nr < NCONES; nr++)
	  		for (ix = 0; ix < NREPLICA; ix++)
	  			for (iy = 0; iy < NREPLICA; iy++)
	  				for (iz = 0; iz < NREPLICA; iz++)
	  					inside_lightcone(p, istep, nr, ix, iy, iz);
#endif


    }/* end move forward in interval STEPS */
  


  /* check the bulge size*/
  //checkbulgesize_main(ngal);
    

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

	  	//if(halonr == 140)
	  	//print_galaxy("check12", p, halonr);
/*#ifdef UPDATETYPETWO
		  update_type_two_coordinate_and_velocity(treenr, p, centralgal);
#else*/
#ifndef UPDATETYPETWO
	  	int jj;
	  	float tmppos;
	  	for(jj = 0; jj < 3; jj++)
	  	{
	  		tmppos = wrap(Gal[p].DistanceToCentralGal[jj],BoxSize);
	  		tmppos *=  (Gal[p].MergTime/Gal[p].OriMergTime);
	  		Gal[p].Pos[jj] = Gal[p].MergCentralPos[jj] + tmppos;

	  		if(Gal[p].Pos[jj] < 0)
	  			Gal[p].Pos[jj] = BoxSize + Gal[p].Pos[jj];
	  		if(Gal[p].Pos[jj] > BoxSize)
	  			Gal[p].Pos[jj] = Gal[p].Pos[jj] - BoxSize;
	  	}
#endif
      /* Disruption of type 2 galaxies. Type 1 galaxies are not disrupted since usually
       * bayonic component is more compact than dark matter.*/

#ifdef DISRUPTION
	    //if(halonr == 84)
	  	//print_galaxy("check13", p, halonr);
		  disrupt(p, Gal[p].CentralGal);
		  //if(halonr == 84)
		  //print_galaxy("check014", p, halonr);


#endif
        }
	  //if(halonr > 20 && halonr < 31)
	  	//if(halonr ==140)
	 		 // print_galaxy("check015", p, halonr);
    }




  for (p =0;p<ngal;p++) mass_checks("Evolve_galaxies #6",p);
  
#ifdef COMPUTE_SPECPHOT_PROPERTIES
#ifndef  POST_PROCESS_MAGS
  int n;
  /* If this is an output snapshot apply the dust model to each galaxy */
  for(n = 0; n < NOUT; n++)
    {
      if(Halo[halonr].SnapNum == ListOutputSnaps[n])
        {
    	  for(p = 0; p < ngal; p++)
    		  dust_model(p, n, halonr);
    	  break;
        }
    }
#endif  //POST_PROCESS_MAGS
#endif //COMPUTE_SPECPHOT_PROPERTIES

  /* now save the galaxies of all the progenitors (and free the associated storage) */
  int prog = Halo[halonr].FirstProgenitor;

  while(prog >= 0)
  	{
      int currentgal;
      for(i = 0, currentgal = HaloAux[prog].FirstGalaxy; i < HaloAux[prog].NGalaxies; i++)
        {
    	  int nextgal = HaloGal[currentgal].NextGalaxy;
    	  /* this will write this galaxy to an output file and free the storage associate with it */
    	  output_galaxy(treenr, HaloGal[currentgal].HeapIndex);
    	  currentgal = nextgal;
        }
      prog = Halo[prog].NextProgenitor;
    }


  for(p = 0, prevgal = -1, currenthalo = -1, centralgal = -1, start = NGalTree; p < ngal; p++)
    {
	  if(Gal[p].HaloNr != currenthalo)
	    {
		  currenthalo = Gal[p].HaloNr;
		  HaloAux[currenthalo].FirstGalaxy = -1;
		  HaloAux[currenthalo].NGalaxies = 0;
	    }

	  mass_checks("Evolve_galaxies #7",p);

      /* may be wrong (what/why?) */
	  if(Gal[p].Type != 3)
	    {
		  if(NHaloGal >= MaxHaloGal)
		    {
			  int oldmax = MaxHaloGal;
			  AllocValue_MaxHaloGal *= ALLOC_INCREASE_FACTOR;
			  MaxHaloGal = AllocValue_MaxHaloGal;
              if(MaxHaloGal<NHaloGal+1) MaxHaloGal=NHaloGal+1;
			  HaloGal = myrealloc_movable(HaloGal, sizeof(struct GALAXY) * MaxHaloGal);
			  HaloGalHeap = myrealloc_movable(HaloGalHeap, sizeof(int) * MaxHaloGal);
			  for(i = oldmax; i < MaxHaloGal; i++)
				  HaloGalHeap[i] = i;
	  	    }

		  Gal[p].SnapNum = Halo[currenthalo].SnapNum;

#ifndef GUO10
#ifdef UPDATETYPETWO
		  update_type_two_coordinate_and_velocity(treenr, p, Gal[0].CentralGal);
#endif
#endif

		  /* when galaxies are outputed, the slot is filled with the
		   * last galaxy in the heap. New galaxies always take the last spot */
		  int nextgal = HaloGalHeap[NHaloGal];
		  HaloGal[nextgal] = Gal[p];
		  HaloGal[nextgal].HeapIndex = NHaloGal;

		  if(HaloAux[currenthalo].FirstGalaxy < 0)
			  HaloAux[currenthalo].FirstGalaxy = nextgal;

		  if(prevgal >= 0)
			  HaloGal[prevgal].NextGalaxy = nextgal;
		  prevgal = nextgal;

		  HaloAux[currenthalo].NGalaxies++;
		  NHaloGal++;


#ifdef GALAXYTREE
		  if(NGalTree >= MaxGalTree)
		    {
			  AllocValue_MaxGalTree *= ALLOC_INCREASE_FACTOR;
			  MaxGalTree = AllocValue_MaxGalTree;
			  if(MaxGalTree<NGalTree+1) MaxGalTree=NGalTree+1;
			  GalTree = myrealloc_movable(GalTree, sizeof(struct galaxy_tree_data) * MaxGalTree);
		    }
		  HaloGal[nextgal].GalTreeIndex = NGalTree;

		  memset(&GalTree[NGalTree], 0, sizeof(struct galaxy_tree_data));
		  GalTree[NGalTree].HaloGalIndex = nextgal;
		  GalTree[NGalTree].SnapNum = Halo[currenthalo].SnapNum;
		  GalTree[NGalTree].NextProgGal = -1;
		  GalTree[NGalTree].DescendantGal = -1;

		  GalTree[NGalTree].FirstProgGal = Gal[p].FirstProgGal;
		  if(Gal[p].Type == 0)
			  centralgal = NGalTree;
		  NGalTree++;
#endif
	    }
    }

#ifdef GALAXYTREE
  for(p = start; p < NGalTree; p++)
    {
      if(centralgal < 0)
    	  terminate("centralgal < 0");
      GalTree[p].FOFCentralGal = centralgal;
    }
#endif


  report_memory_usage(&HighMark, "evolve_galaxies");
}