void cool_gas_onto_galaxy(int p, double dt) { double fraction,Mdisk,Mcool; int i; /** @brief cool_gas_onto_galaxy updates the fractions of hot and cold gas * due to cooling. This is done for the mass, metals and, after Guo2010, * spin components */ Mdisk=Gal[p].ColdGas; Mcool=Gal[p].CoolingGas; if (Mcool>Gal[p].HotGas) Mcool = Gal[p].HotGas; /* add the fraction 1/STEPS of the total cooling gas to the cold disk */ if(Mcool > 0.0) { //determine the xray luminosity of any cooling gas in this snapshot (White & Frenk 1991 eq21) Gal[p].XrayLum = log10(2.5 * (Mcool / dt) * 6.31 * Gal[p].Vvir * Gal[p].Vvir) + 35.0; // We already know that 0<mcool<=Gal[p].HotGas fraction=((float)Mcool)/Gal[p].HotGas; transfer_gas(p,"Cold",p,"Hot",fraction,"cool_gas_onto_galaxy", __LINE__); if (DiskRadiusModel == 0) { if (Gal[p].ColdGas != 0.0) for (i=0;i<3;i++) Gal[p].GasSpin[i]=(Gal[p].GasSpin[i]*Mdisk+Gal[p].HaloSpin[i]*Mcool)/(Gal[p].ColdGas); get_gas_disk_radius(p); } } else Gal[p].XrayLum = 0.0; }
void reincorporate_gas(int p, double dt) { double reincorporated, fraction, reinc_time; reincorporated = 0.; mass_checks("reincorporate_gas #1",p); /* DeLucia2007 -> Mdot_eject=-gama_ej * M_ejected/tdyn */ if(ReIncorporationRecipe == 0) reincorporated = ReIncorporationFactor * Gal[p].EjectedMass / (Gal[p].Rvir / Gal[p].Vvir) * dt; /* Guo2010 -> Mdot_eject=-gama_ej * M_ejected/tdyn * Vvir/220 */ else if(ReIncorporationRecipe == 1) reincorporated = ReIncorporationFactor * Gal[p].EjectedMass / (Gal[p].Rvir / Gal[p].Vvir) * Gal[p].Vvir/220. *dt ; /* Henriques2012b Mdot_eject=-gama_ej*M_ejected*M_vir * Mvir should be in units of 1e12, but inside the * code Mvir is already in units of 1.e10*/ else if(ReIncorporationRecipe == 2) { // Oppenheimer & Dave 2008 /* reinc_time= pow(Gal[p].Mvir/Hubble_h,-0.6)*ReIncorporationFactor/UnitTime_in_years; if(Gal[p].Mvir/Hubble_h > 500.) reinc_time= pow(500.,-0.6)*ReIncorporationFactor/UnitTime_in_years; reincorporated = Gal[p].EjectedMass / reinc_time * dt; */ reinc_time= (Hubble_h/Gal[p].Mvir)*(ReIncorporationFactor/UnitTime_in_years); reincorporated = Gal[p].EjectedMass / reinc_time * dt; // reinc_time= (Hubble_h)*(ReIncorporationFactor/UnitTime_in_years); // reincorporated = Gal[p].EjectedMass / reinc_time * dt; /*reinc_time= ReIncorporationFactor/UnitTime_in_years * pow((1+ZZ[Gal[p].SnapNum]),ReincZpower) * pow(Gal[p].Vvir/220.,-ReincVelocitypower) / (hubble_of_z(Gal[p].HaloNr)); reincorporated = Gal[p].EjectedMass / reinc_time *dt ;*/ } if(FeedbackRecipe == 1) { reincorporated = ReIncorporationFactor * Gal[p].EjectedMass / (Gal[p].Rvir * min(FeedbackEjectionEfficiency,1.)*sqrt(EtaSNcode * EnergySNcode)/(Gal[p].Vvir*Gal[p].Vvir)) * Gal[p].Vvir/220. * 1.e-6* dt ; //reincorporated = ReIncorporationFactor * Gal[p].EjectedMass / (Gal[p].Rvir / Gal[p].Vvir) * // min(FeedbackEjectionEfficiency,1.) * Gal[p].Vvir/220. *dt ; //reincorporated = ReIncorporationFactor * Gal[p].EjectedMass / (Gal[p].Rvir / Gal[p].Vvir) * Gal[p].Vvir/220. *dt ; //reincorporated = 0.; } if (reincorporated > Gal[p].EjectedMass) reincorporated = Gal[p].EjectedMass; mass_checks("reincorporate_gas #1.5",p); /*Update ejected and hot gas contents*/ if (Gal[p].EjectedMass > 0.) { fraction=((float)reincorporated)/Gal[p].EjectedMass; //printf("%s","Gas Reincorporated: "); //printf("%lf \n",reincorporated); transfer_gas(p,"Hot",p,"Ejected",fraction,"reincorporate_gas", __LINE__); } mass_checks("reincorporate_gas #2",p); }
void add_galaxies_together(int t, int p) { /** @brief All the components of the satellite galaxy are added to the * correspondent component of the central galaxy. Cold gas spin * is updated and a bulge is formed at the central galaxy, with * the stars of the satellite if BulgeFormationInMinorMergersOn=1. * * TODO Even though galaxy p has been set to type 3 (ie a non-galaxy), it would * make mass conservation more explicit to zero the properties of galaxy p after * the merger. * TODO Correct artificial diffusion of metals when BulgeFormationInMinorMergersOn=1. */ int outputbin, j; float tspin[3],tmass,pmass; /* t central, p satellite */ mass_checks("add_galaxies_together #0",p); mass_checks("add_galaxies_together #0.1",t); /* angular momentum transfer between gas*/ tmass= Gal[t].ColdGas; pmass= Gal[p].ColdGas; Gal[t].MergeSat +=(Gal[p].DiskMass+Gal[p].BulgeMass); Gal[p].MergeSat=0.; transfer_gas(t,"Cold",p,"Cold",1.); transfer_gas(t,"Hot",p,"Hot",1.); transfer_gas(t,"Ejected",p,"Ejected",1.); //TODO chose move to ejected or hot if(BulgeFormationInMinorMergersOn) transfer_stars(t,"Bulge",p,"Disk",1.); else transfer_stars(t,"Disk",p,"Disk",1.); transfer_stars(t,"Bulge",p,"Bulge",1.); transfer_stars(t,"ICM",p,"ICM",1.); Gal[t].BlackHoleMass += Gal[p].BlackHoleMass; Gal[p].BlackHoleMass=0.; Gal[t].BlackHoleGas += Gal[p].BlackHoleGas; Gal[p].BlackHoleGas=0.; Gal[t].StarMerge += Gal[p].StarMerge; Gal[p].StarMerge=0.; mass_checks("add_galaxies_together #1",p); mass_checks("add_galaxies_together #1.1",t); /*update the gas spin*/ for(j=0;j<3;j++) tspin[j]=Gal[t].GasSpin[j]*tmass+Gal[t].HaloSpin[j]*pmass; if (Gal[t].ColdGas != 0) for (j=0;j<3;j++) Gal[t].GasSpin[j]=tspin[j]/(Gal[t].ColdGas); #ifdef SAVE_MEMORY Gal[t].Sfr += Gal[p].Sfr; #else for(outputbin = 0; outputbin < NOUT; outputbin++) Gal[t].Sfr[outputbin] += Gal[p].Sfr[outputbin]; #endif if(BulgeFormationInMinorMergersOn) { #ifdef SAVE_MEMORY Gal[t].SfrBulge += Gal[p].Sfr; #else for(outputbin = 0; outputbin < NOUT; outputbin++) Gal[t].SfrBulge[outputbin] += Gal[p].Sfr[outputbin]; #endif } /* Add the black hole accretion rates. This makes little sense but is not * used if the superior BlackHoleGrowth==1 switch is on. */ Gal[t].QuasarAccretionRate += Gal[p].QuasarAccretionRate; Gal[t].RadioAccretionRate += Gal[p].RadioAccretionRate; #ifndef POST_PROCESS_MAGS /* Add the luminosities of the satellite and central galaxy */ #ifdef OUTPUT_REST_MAGS for(outputbin = 0; outputbin < NOUT; outputbin++) { for(j = 0; j < NMAG; j++) { Gal[t].Lum[j][outputbin] += Gal[p].Lum[j][outputbin]; Gal[t].YLum[j][outputbin] += Gal[p].YLum[j][outputbin]; #ifdef ICL Gal[t].ICLLum[j][outputbin] += Gal[p].ICLLum[j][outputbin]; #endif } if(BulgeFormationInMinorMergersOn) { for(j = 0; j < NMAG; j++) { Gal[t].LumBulge[j][outputbin] += Gal[p].Lum[j][outputbin]; Gal[t].YLumBulge[j][outputbin] += Gal[p].YLum[j][outputbin]; } } else { for(j = 0; j < NMAG; j++) { Gal[t].LumBulge[j][outputbin] += Gal[p].LumBulge[j][outputbin]; Gal[t].YLumBulge[j][outputbin] += Gal[p].YLumBulge[j][outputbin]; } } Gal[t].MassWeightAge[outputbin] += Gal[p].MassWeightAge[outputbin]; } #endif // OUTPUT_REST_MAGS #ifdef COMPUTE_OBS_MAGS for(outputbin = 0; outputbin < NOUT; outputbin++) { for(j = 0; j < NMAG; j++) { Gal[t].ObsLum[j][outputbin] += Gal[p].ObsLum[j][outputbin]; Gal[t].ObsYLum[j][outputbin] += Gal[p].ObsYLum[j][outputbin]; #ifdef ICL Gal[t].ObsICL[j][outputbin] += Gal[p].ObsICL[j][outputbin]; #endif #ifdef OUTPUT_MOMAF_INPUTS Gal[t].dObsLum[j][outputbin] += Gal[p].dObsLum[j][outputbin]; Gal[t].dObsYLum[j][outputbin] += Gal[p].dObsYLum[j][outputbin]; #endif } if(BulgeFormationInMinorMergersOn) { for(j = 0; j < NMAG; j++) { Gal[t].ObsLumBulge[j][outputbin] += Gal[p].ObsLum[j][outputbin]; Gal[t].ObsYLumBulge[j][outputbin] += Gal[p].ObsYLum[j][outputbin]; #ifdef OUTPUT_MOMAF_INPUTS Gal[t].dObsLumBulge[j][outputbin] += Gal[p].dObsLum[j][outputbin]; Gal[t].dObsYLumBulge[j][outputbin] += Gal[p].dObsYLum[j][outputbin]; #endif } } else { for(j = 0; j < NMAG; j++) { Gal[t].ObsLumBulge[j][outputbin] += Gal[p].ObsLumBulge[j][outputbin]; Gal[t].ObsYLumBulge[j][outputbin] += Gal[p].ObsYLumBulge[j][outputbin]; #ifdef OUTPUT_MOMAF_INPUTS Gal[t].dObsLumBulge[j][outputbin] += Gal[p].dObsLumBulge[j][outputbin]; Gal[t].dObsYLumBulge[j][outputbin] += Gal[p].dObsYLumBulge[j][outputbin]; #endif } } } #endif //COMPUTE_OBS_MAGS #endif //POST_PROCESS_MAGS }
void disrupt(int p, int centralgal) { double rho_sat, rho_cen; double cen_mass, r_sat, radius; int outputbin, j, q; /* If the main halo density at the pericentre (closest point in the orbit * to the central galaxy)is larger than the satellite's density at the * half mass radius, the satellite is completely disrupted. Note that since * the satellite is a type 2 the only mass components remaining and * contributing to the density are the cold gas and stellar mass. */ //TODO If we are passing in centralgal then we should not set it here centralgal=Gal[p].CentralGal; mass_checks("Top of disrupt",centralgal); mass_checks("Top of disrupt",p); /* Radius calculated at the peri-point */ radius=peri_radius(p, centralgal); if (radius < 0) { terminate("must be wrong \n"); } /* Calculate the density of the main central halo at radius (the peri-centre). * The tidal forces are caused by the dark matter of the main halo, hence Mvir * is used. */ cen_mass=Gal[centralgal].Mvir*radius/Gal[centralgal].Rvir; rho_cen=cen_mass/pow3(radius); /* Calculate the density of the satellite's baryonic material */ if (Gal[p].DiskMass+Gal[p].BulgeMass>0) { /* Calculate the rho according to the real geometry */ r_sat = sat_radius(p); /* Or use radius at the mean radius of the stellar mass */ /* r_sat=(Gal[p].BulgeMass*Gal[p].BulgeSize+(Gal[p].StellarMass-Gal[p].BulgeMass) * *Gal[p].StellarDiskRadius/3*1.68) * /(Gal[p].StellarMass); */ /* to calculate the density */ //rho_sat=Gal[p].StellarMass/pow2(r_sat); rho_sat=(Gal[p].DiskMass+Gal[p].BulgeMass+Gal[p].ColdGas)/pow3(r_sat); } else rho_sat=0.0; /* If density of the main halo is larger than that of the satellite baryonic * component, complete and instantaneous disruption is assumed. Galaxy becomes * a type 3 and all its material is transferred to the central galaxy. */ if (rho_cen > rho_sat) { Gal[p].Type = 3; #ifdef GALAXYTREE q = Gal[Gal[p].CentralGal].FirstProgGal; if (q >= 0) { // add progenitors of Gal[p] to the list of progentitors of Gal[p].CentralGal 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("this shouldn't happen"); // TODO if !(q>=0) shouldn't we set // Gal[Gal[p].CentralGal].FirstProgGal to Gal[p].FirstProgGal ?? q = GalTree[q].NextProgGal; if(q < 0) terminate("inconsistency"); if(HaloGal[GalTree[q].HaloGalIndex].GalTreeIndex != q) terminate("inconsistency"); HaloGal[GalTree[q].HaloGalIndex].DisruptOn = 1; #endif /* Put gas component to the central galaxy hot gas and stellar material into the ICM. * Note that the staellite should have no extended components. */ // TODO Shouldn't the stars end up in the bulge? - this is a close merger transfer_gas(centralgal,"Hot",p,"Cold",1.); transfer_gas(centralgal,"Hot",p,"Hot",1.); transfer_stars(centralgal,"ICM",p,"Disk",1.); transfer_stars(centralgal,"ICM",p,"Bulge",1.); /* Add satellite's luminosity into the luminosity of the ICL * component of the central galaxy. */ #ifdef ICL for(outputbin = 0; outputbin < NOUT; outputbin++) { for(j = 0; j < NMAG; j++) { #ifdef OUTPUT_REST_MAGS Gal[centralgal].ICLLum[j][outputbin] += Gal[p].Lum[j][outputbin]; #endif #ifdef COMPUTE_OBS_MAGS Gal[centralgal].ObsICL[j][outputbin] += Gal[p].ObsLum[j][outputbin]; #endif } } #endif } mass_checks("Bottom of disrupt",centralgal); mass_checks("Bottom of disrupt",p); }
/** @brief Updates cold, hot and external gas components due to SN * reheating and ejection. */ void update_from_feedback(int p, int centralgal, double reheated_mass, double ejected_mass) { double dis=0.; double massremain; double fraction; int merger_centre; //mass_checks("update_from_feedback #1",p); if(Gal[p].ColdGas > 0.) { //REHEAT // if galaxy is a type 1 or a type 2 orbiting a type 1 with hot gas being striped, //some of the reheated and ejected masses goes to the type 0 and some stays in the type 1 if(Gal[p].Type ==0) { transfer_gas(p,"Hot",p,"Cold",((float)reheated_mass)/Gal[p].ColdGas,"update_from_feedback", __LINE__); } else if(Gal[p].Type <3) { if(Gal[p].Type ==1) merger_centre=centralgal; else if(Gal[p].Type ==2) merger_centre=Gal[p].CentralGal; dis=separation_gal(centralgal,Gal[p].CentralGal)/(1+ZZ[Halo[Gal[centralgal].HaloNr].SnapNum]); //compute share of reheated mass if (dis<Gal[centralgal].Rvir && Gal[Gal[p].CentralGal].Type == 1) { //mass that remains on type1 (the rest goes to type 0) for reheat - massremain, for eject - ejected mass massremain=reheated_mass*Gal[p].HotRadius/Gal[p].Rvir; ejected_mass = ejected_mass*Gal[p].HotRadius/Gal[p].Rvir; if (massremain > reheated_mass) massremain = reheated_mass; } else massremain=reheated_mass; //needed due to precision issues, since we first remove massremain and then (reheated_mass-massremain) //from the satellite into the type 0 and type 1 the fraction might not add up on the second call //since Gal[p].ColdGas is a float and reheated_mass & massremain are doubles if((massremain + reheated_mass)>Gal[p].ColdGas) massremain=Gal[p].ColdGas-reheated_mass; //transfer massremain transfer_gas(Gal[p].CentralGal,"Hot",p,"Cold",massremain/Gal[p].ColdGas,"update_from_feedback", __LINE__); //transfer reheated_mass-massremain from galaxy to the type 0 if (reheated_mass > massremain) if(Gal[p].ColdGas > 0.) //if the reheat to itself, left cold gas below limit do not reheat to central transfer_gas(centralgal,"Hot",p,"Cold",(reheated_mass-massremain)/Gal[p].ColdGas,"update_from_feedback", __LINE__); }//types }//if(Gal[p].ColdGas > 0.) mass_checks("update_from_feedback #2",p); //DO EJECTION OF GAS if (Gal[Gal[p].CentralGal].HotGas > 0.) { if (ejected_mass > Gal[Gal[p].CentralGal].HotGas) ejected_mass = Gal[Gal[p].CentralGal].HotGas; //either eject own gas or merger_centre gas for ttype 2's fraction=((float)ejected_mass)/Gal[Gal[p].CentralGal].HotGas; if (Gal[Gal[p].CentralGal].Type == 1) { /* If type 1, or type 2 orbiting type 1 near type 0 */ if (FateOfSatellitesGas == 0) transfer_gas(Gal[p].CentralGal,"Ejected",Gal[p].CentralGal,"Hot",fraction,"update_from_feedback", __LINE__); else if (FateOfSatellitesGas == 1) { if (dis < Gal[centralgal].Rvir) transfer_gas(centralgal,"Hot",Gal[p].CentralGal,"Hot",fraction,"update_from_feedback", __LINE__); else transfer_gas(Gal[p].CentralGal,"Ejected",Gal[p].CentralGal,"Hot",fraction,"update_from_feedback", __LINE__); } } else // If galaxy type 0 or type 2 merging into type 0 transfer_gas(centralgal,"Ejected",Gal[p].CentralGal,"Hot",fraction,"update_from_feedback", __LINE__); }//(Gal[Gal[p].CentralGal].HotGas > 0.) }