void output_tree(int treeNum){ int i, hid, pid; for(i = 0; i < halo_per_snap[OUTSNAP]; ++i){ hid = snap[OUTSNAP][i].hid; if(g[hid].flag_v == 0){ pid = g[hid].firstInFOF; centralMvir = g[pid].m_vir; subNum = 0; while(pid != -1){ output_galaxy(pid); g[pid].flag_v = 1; pid = g[pid].nextInFOF; } groupNum++; } } if(halo != NULL){ free(halo); halo = NULL; } if(g != NULL){ free(g); g = NULL; } }
/* 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"); }
/* 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"); }
/**@brief Main routine of L-Galaxies*/ int main(int argc, char **argv) { int filenr, *FileToProcess, *TaskToProcess, nfiles; char buf[1000]; time_t start, current; #ifdef PARALLEL MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask); MPI_Comm_size(MPI_COMM_WORLD, &NTask); #else NTask = 1; ThisTask = 0; #endif //PARALLEL #ifdef MCMC time(&global_starting_time); #endif if(ThisTask==0) { printf("\n\n\n"); printf("**************************************************************************\n"); printf("* *\n"); printf("* Copyright (C) <2016> <L-Galaxies> *\n"); printf("* *\n"); printf("* This program is free software: you can redistribute it and/or modify *\n"); printf("* it under the terms of the GNU General Public License as published by *\n"); printf("* the Free Software Foundation, either version 3 of the License, or *\n"); printf("* (at your option) any later version. *\n"); printf("* *\n"); printf("* This program is distributed in the hope that it will be useful, *\n"); printf("* but WITHOUT ANY WARRANTY; without even the implied warranty of *\n"); printf("* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *\n"); printf("* GNU General Public License for more details. *\n"); printf("* *\n"); printf("* You should have received a copy of the GNU General Public License *\n"); printf("* along with this program. If not, see <http://www.gnu.org/licenses/> *\n"); printf("* *\n"); printf("**************************************************************************\n\n\n"); } if(argc > 3 || argc<2) { printf("\n Wrong number of runtime arguments\n\n"); printf("\n usage: ./L-Galaxies <parameterfile>\n\n"); endrun(0); } if (ThisTask == 0) printf("%s\n",COMPILETIMESETTINGS); /* check compatibility of some Makefile Options*/ check_options(); /*Reads the parameter file, given as an argument at run time. */ read_parameter_file(argv[1]); #ifdef MR_PLUS_MRII //Start with MR files and later change to MRII LastDarkMatterSnapShot=LastDarkMatterSnapShot_MR; sprintf(FileWithZList, "%s", FileWithZList_MR); sprintf(FileWithZList_OriginalCosm, "%s", FileWithZList_OriginalCosm_MR); #endif mymalloc_init(); sprintf(FinalOutputDir, "%s", OutputDir); #ifndef MCMC if(argc == 3) sprintf(OutputDir, "%s", argv[2]); #else FirstChainNumber=0; if(argc == 3) FirstChainNumber=atoi(argv[2]); #endif //time(&start); #ifdef COMPUTE_SPECPHOT_PROPERTIES //for dust_model mu_seed = -150; #endif init(); #ifdef STAR_FORMATION_HISTORY #ifdef PARALLEL if(ThisTask == 0) #endif write_sfh_bins(); #endif #ifndef MCMC nfiles=get_nr_files_to_process(ThisTask); FileToProcess=mymalloc("FileToProcess", sizeof(int) * nfiles); TaskToProcess=mymalloc("TaskToProcess", sizeof(int) * nfiles); assign_files_to_tasks(FileToProcess, TaskToProcess, ThisTask, NTask, nfiles); int file; for(file = 0; file < nfiles; file++) { if(ThisTask==TaskToProcess[file]) filenr=FileToProcess[file]; else continue; #else //MCMC /* In MCMC mode only one file is loaded into memory * and the sampling for all the steps is done on it */ sprintf(SimulationDir, "%s/", SimulationDir); for(filenr = MCMCTreeSampleFile; filenr <= MCMCTreeSampleFile; filenr++) { #endif //MCMC time(&start); #ifdef PARALLEL #ifndef MCMC time_t current; do time(¤t); //while(difftime(current, start) < 5.0 * ThisTask); while(difftime(current, start) < 1.0 * ThisTask); #endif #endif load_tree_table(filenr); #ifdef MCMC Senna(); // run the model in MCMC MODE #else SAM(filenr); // run the model in NORMAL MODE #endif #ifdef MCMC break; //break loop on files since the MCMC is done on a single file #else time(¤t); printf("\ndone tree file %d in %ldmin and %lds\n\n", filenr, (current - start)/60, (current - start)%60); #endif //MCMC free_tree_table(); //if temporary directory given as argument if(argc == 3) { #ifdef GALAXYTREE sprintf(buf, "mv %s/%s_galtree_%d %s", OutputDir,FileNameGalaxies, filenr, FinalOutputDir); #else sprintf(buf, "mv %s/%s_z*_%d %s", OutputDir,FileNameGalaxies, filenr, FinalOutputDir); #endif system(buf); } } #ifndef MCMC myfree(TaskToProcess); myfree(FileToProcess); #endif #ifdef PARALLEL MPI_Finalize(); #endif return 0; } /**@brief SAM() loops on trees and calls construct_galaxies.*/ #ifdef MCMC double SAM(int filenr) #else void SAM(int filenr) #endif { int treenr, halonr; #ifdef MCMC int ii; MCMC_GAL = mymalloc("MCMC_Gal", sizeof(struct MCMC_GALAXY) * MCMCAllocFactor); for(ii=0;ii<NOUT;ii++) TotMCMCGals[ii] = 0; #ifdef MR_PLUS_MRII change_dark_matter_sim("MR"); #else if(CurrentMCMCStep==1) read_sample_info(); #ifdef HALOMODEL else { int snap, ii; for(snap=0;snap<NOUT;snap++) for(ii=0;ii<NFofsInSample[snap];ii++) MCMC_FOF[ii].NGalsInFoF[snap]=0; } #endif //HALOMODEL #endif //MR_PLUS_MRII #endif //MCMC //to be used when we have tables for the scaling in any cosmology //read_scaling_parameters(); #ifndef MCMC #ifdef GALAXYTREE create_galaxy_tree_file(filenr); #else create_galaxy_files(filenr); #endif #endif #ifdef GALAXYTREE FILE *fdg = fopen("treengal.dat", "w"); #endif //*************************************************************************************** //*************************************************************************************** //for(treenr = 0; treenr < NTrees_Switch_MR_MRII; treenr++) for(treenr = 0; treenr < Ntrees; treenr++) { //printf("doing tree %d of %d\n", treenr, Ntrees); #ifdef MR_PLUS_MRII if(treenr == NTrees_Switch_MR_MRII) change_dark_matter_sim("MRII"); #endif load_tree(treenr); #ifdef MCMC #ifdef PRELOAD_TREES if(CurrentMCMCStep==1) #endif #endif scale_cosmology(TreeNHalos[treenr]); gsl_rng_set(random_generator, filenr * 100000 + treenr); NumMergers = 0; NHaloGal = 0; #ifdef GALAXYTREE NGalTree = 0; IndexStored = 0; #endif int snapnum; //LastSnapShotNr is the highest output snapshot /* we process the snapshots now in temporal order * (as a means to reduce peak memory usage) */ for(snapnum = 0; snapnum <= LastSnapShotNr; snapnum++) { #ifdef MCMC /* read the appropriate parameter list for current snapnum * into the parameter variables to be used in construct_galaxies */ read_mcmc_par(snapnum); #ifdef HALOMODEL //because we need halo masses even for FOFs //with no galaxies it needs to be done here assign_FOF_masses(snapnum, treenr); #endif #endif for(halonr = 0; halonr < TreeNHalos[treenr]; halonr++) if(HaloAux[halonr].DoneFlag == 0 && Halo[halonr].SnapNum == snapnum) construct_galaxies(filenr, treenr, halonr); } /* output remaining galaxies as needed */ while(NHaloGal) output_galaxy(treenr, 0); #ifndef MCMC #ifdef GALAXYTREE save_galaxy_tree_finalize(filenr, treenr); #ifndef PARALLEL if((treenr/100)*100==treenr) printf("treenr=%d TotGalCount=%d\n", treenr, TotGalCount); #endif fflush(stdout); fprintf(fdg, "%d\n", NGalTree); #endif #else//ifdef MCMC #endif free_galaxies_and_tree(); }//loop on trees #ifdef MCMC double lhood = get_likelihood(); #ifdef MR_PLUS_MRII free(MCMC_FOF); #else if(CurrentMCMCStep==ChainLength) free(MCMC_FOF); #endif myfree(MCMC_GAL); return lhood; #else //MCMC #ifdef GALAXYTREE close_galaxy_tree_file(); #else close_galaxy_files(); #endif return; #endif }
/**@brief Main routine of L-Galaxies*/ int main(int argc, char **argv) { int filenr, *FileToProcess, *TaskToProcess, nfiles; char buf[1000]; time_t start, current; //Catch floating point exceptions #ifdef DEBUG #endif #ifdef PARALLEL MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask); MPI_Comm_size(MPI_COMM_WORLD, &NTask); #else NTask = 1; ThisTask = 0; #endif //PARALLEL #ifdef MCMC time(&global_starting_time); #endif if(argc > 3) { printf("\n usage: L-Galaxies <parameterfile>\n\n"); endrun(0); } if (ThisTask == 0) printf("%s\n",COMPILETIMESETTINGS); /*Reads the parameter file, given as an argument at run time. */ read_parameter_file(argv[1]); #ifdef MR_PLUS_MRII //Start with MR files and later change to MRII LastDarkMatterSnapShot=LastDarkMatterSnapShot_MR; sprintf(FileWithZList, "%s", FileWithZList_MR); sprintf(FileWithZList_OriginalCosm, "%s", FileWithZList_OriginalCosm_MR); #endif mymalloc_init(); sprintf(FinalOutputDir, "%s", OutputDir); if(argc == 3) sprintf(OutputDir, "%s", argv[2]); //time(&start); /* check compatibility of some Makefile Options*/ check_options(); #ifdef COMPUTE_SPECPHOT_PROPERTIES //for dust_model mu_seed = -150; #endif init(); #ifdef STAR_FORMATION_HISTORY #ifdef PARALLEL if(ThisTask == 0) #endif write_sfh_bins(); #endif #ifdef MCMC #ifdef PARALLEL /* a small delay to avoid all processors reading trees at the same time*/ time(&start); do time(¤t); while(difftime(current, start) < 10.0 * ThisTask); #endif #endif #ifndef MCMC nfiles=get_nr_files_to_process(ThisTask); FileToProcess=mymalloc("FileToProcess", sizeof(int) * nfiles); TaskToProcess=mymalloc("TaskToProcess", sizeof(int) * nfiles); assign_files_to_tasks(FileToProcess, TaskToProcess, ThisTask, NTask, nfiles); int file; for(file = 0; file < nfiles; file++) { if(ThisTask==TaskToProcess[file]) filenr=FileToProcess[file]; else continue; #else //MCMC /* In MCMC mode only one file is loaded into memory * and the sampling for all the steps is done on it */ sprintf(SimulationDir, "%s/MergerTrees_%d/", SimulationDir, ThisTask); for(filenr = MCMCTreeSampleFile; filenr <= MCMCTreeSampleFile; filenr++) { #endif //MCMC time(&start); #ifdef READXFRAC get_xfrac_mesh(); #endif load_tree_table(filenr); /* Read in mesh dimensions */ #ifdef MCMC #ifdef PARALLEL time_t start, start2; /* a small delay to reset processors to the same time*/ time(&start2); do time(¤t); while(difftime(current, start2) < 10.0 * (NTask-ThisTask)); #endif Senna(); // run the model in MCMC MODE #else SAM(filenr); // run the model in NORMAL MODE #endif #ifdef MCMC break; //break loop on files since the MCMC is done on a single file #else time(¤t); printf("\ndone tree file %d in %ldmin and %lds\n\n", filenr, (current - start)/60, (current - start)%60); #endif //MCMC free_tree_table(); //if temporary directory given as argument if(argc == 3) { #ifdef GALAXYTREE sprintf(buf, "mv %s/%s_galtree_%d %s", OutputDir,FileNameGalaxies, filenr, FinalOutputDir); #else sprintf(buf, "mv %s/%s_z*_%d %s", OutputDir,FileNameGalaxies, filenr, FinalOutputDir); #endif system(buf); } } #ifndef MCMC myfree(TaskToProcess); myfree(FileToProcess); #endif #ifdef PARALLEL MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); #endif return 0; } /**@brief SAM() loops on trees and calls construct_galaxies.*/ #ifdef MCMC double SAM(int filenr) #else void SAM(int filenr) #endif { int treenr, halonr; time_t t_mark_a, t_mark_b; #ifdef MCMC int ii; MCMC_GAL = mymalloc("MCMC_Gal", sizeof(struct MCMC_GALAXY) * MCMCAllocFactor); for(ii=0;ii<NOUT;ii++) TotMCMCGals[ii] = 0; if(Sample_Cosmological_Parameters==1) { reset_cosmology (); #ifdef HALOMODEL initialize_halomodel(); #endif } #ifdef MR_PLUS_MRII change_dark_matter_sim("MR"); #else if(Sample_Cosmological_Parameters==1 || CurrentMCMCStep==1) read_sample_info(); else { int snap, ii; for(snap=0;snap<NOUT;snap++) for(ii=0;ii<NFofsInSample[snap];ii++) MCMC_FOF[ii].NGalsInFoF[snap]=0; } #endif #endif //to be used when we have tables for the scaling in any cosmology //read_scaling_parameters(); #ifndef MCMC #ifdef GALAXYTREE create_galaxy_tree_file(filenr); #else create_galaxy_files(filenr); #endif #ifdef ALL_SKY_LIGHTCONE int nr; for ( nr = 0; nr < NCONES; nr++) create_galaxy_lightcone_files(filenr, nr); #endif #endif #ifdef GALAXYTREE FILE *fdg = fopen("treengal.dat", "w"); #endif //*************************************************************************************** //*************************************************************************************** //for(treenr = 0; treenr < NTrees_Switch_MR_MRII; treenr++) //for(treenr = NTrees_Switch_MR_MRII; treenr < Ntrees; treenr++) /* Scan through all trees snapshot by snapshot */ int snapnum; //for(treenr = 0; treenr < NTrees_Switch_MR_MRII; treenr++) //for(treenr = NTrees_Switch_MR_MRII; treenr < Ntrees; treenr++) for(treenr = 0; treenr < Ntrees; treenr++) //for(treenr = 0; treenr < 1;treenr++) { //printf("doing tree %d of %d\n", treenr, Ntrees); #ifdef MR_PLUS_MRII if(treenr == NTrees_Switch_MR_MRII) change_dark_matter_sim("MRII"); #endif load_tree(treenr); #ifdef MCMC #ifdef PRELOAD_TREES if(Sample_Cosmological_Parameters==1 || CurrentMCMCStep==0) #endif #endif scale_cosmology(TreeNHalos[treenr]); gsl_rng_set(random_generator, filenr * 100000 + treenr); NumMergers = 0; NHaloGal = 0; #ifdef GALAXYTREE NGalTree = 0; IndexStored = 0; #endif //LastSnapShotNr is the highest output snapshot /* we process the snapshots now in temporal order * (as a means to reduce peak memory usage) */ for(snapnum = 0; snapnum <= LastSnapShotNr; snapnum++) //for(snapnum = 0; snapnum <= 30; snapnum++) { #ifdef MCMC /* read the appropriate parameter list for current snapnum * into the parameter variables to be used in construct_galaxies */ read_mcmc_par(snapnum); #else //used to allow parameter values to vary with redshift //re_set_parameters(snapnum); #endif //printf("doing snap=%d\n",snapnum); for(halonr = 0; halonr < TreeNHalos[treenr]; halonr++) if(HaloAux[halonr].DoneFlag == 0 && Halo[halonr].SnapNum == snapnum) construct_galaxies(filenr, treenr, halonr); } /* output remaining galaxies as needed */ while(NHaloGal) output_galaxy(treenr, 0); #ifndef MCMC #ifdef GALAXYTREE save_galaxy_tree_finalize(filenr, treenr); #ifndef PARALLEL if((treenr/100)*100==treenr) printf("treenr=%d TotGalCount=%d\n", treenr, TotGalCount); #endif fflush(stdout); fprintf(fdg, "%d\n", NGalTree); #endif #else//ifdef MCMC #ifdef PRELOAD_TREES if(Sample_Cosmological_Parameters==1) un_scale_cosmology(TreeNHalos[treenr]); #endif #endif free_galaxies_and_tree(); } #ifdef MCMC double lhood = get_likelihood(); #ifdef MR_PLUS_MRII free(MCMC_FOF); #else if(Sample_Cosmological_Parameters==1 || CurrentMCMCStep==ChainLength) free(MCMC_FOF); #endif #ifdef HALOMODEL if (Sample_Cosmological_Parameters==1) { gsl_spline_free(FofSpline); gsl_interp_accel_free(FofAcc); gsl_spline_free(SigmaSpline); gsl_interp_accel_free(SigmaAcc); gsl_spline_free(ellipSpline); gsl_interp_accel_free(ellipAcc); gsl_spline_free(PowSpline); } //if #endif myfree(MCMC_GAL); return lhood; #else //MCMC #ifdef GALAXYTREE close_galaxy_tree_file(); #else close_galaxy_files(); #endif #ifdef ALL_SKY_LIGHTCONE for (nr = 0; nr < NCONES; nr++) close_galaxy_lightcone_files(nr); #endif return; #endif }