62 #include <gsl/gsl_interp.h>
75 static const double GrayOpac_ydata[
NGRAY] = { 2.59e-18, 2.37e-18, 2.27e-18, 2.15e-18, 2.02e-18, 1.94e-18};
95 #define NRECOMBTAB 1000
96 #define RECOMBTMAX log(1e9)
109 Gamma->
intp = gsl_interp_alloc(gsl_interp_linear,Nelem);
110 gsl_interp_init(Gamma->
intp, xarr, Gamma->
ydata, Nelem);
117 double data = atof(strtok_r(NULL,
" \t", saveptr));
134 FILE * fd = fopen(TreeCoolFile,
"r");
136 endrun(456,
"Could not open photon background (TREECOOL) file at: '%s'\n", TreeCoolFile);
143 char * retval = fgets(buffer, 1024, fd);
147 retval = strtok(buffer,
" \t");
149 if(!retval || retval[0] ==
'#')
156 MPI_Bcast(&(
NTreeCool), 1, MPI_INT, 0, MPI_COMM_WORLD);
159 endrun(1,
"Photon background contains: %d entries, not enough.\n",
NTreeCool);
171 MPI_Comm_rank(MPI_COMM_WORLD, &
ThisTask);
179 char * line = fgets(buffer, 1024, fd);
183 char * retval = strtok_r(line,
" \t", &saveptr);
184 if(!retval || retval[0] ==
'#')
219 double log1z = log10(1+redshift);
224 photo_rate = Gamma_tab->
ydata[0];
249 double G12 = uvbg->
gJH0/1e-12;
258 return 6.73e-3 * pow(greyopac / 2.49e-18, -2./3)*pow(G12, 2./3)*pow(
CoolingParams.
fBar/0.17,-1./3);
265 struct UVBG GlobalUVBG = {0};
312 double T4 = exp(0.17 * (logt - log(1e4)));
313 double nSSh = 1.003*ssdens*T4;
314 return 0.98*pow(1+pow(nh/nSSh,1.64),-2.28)+0.02*pow(1+nh/nSSh, -0.84);
338 _Verner96Fit(
double temp,
double aa,
double bb,
double temp0,
double temp1)
340 double sqrttt0 = sqrt(temp/temp0);
341 double sqrttt1 = sqrt(temp/temp1);
342 return aa / ( sqrttt0 * pow(1 + sqrttt0, 1-bb)*pow(1+sqrttt1, 1+bb) );
352 return 8.4e-11 / sqrt(temp) / pow(temp/1000, 0.2) / (1+ pow(temp/1e6, 0.7));
356 return _Verner96Fit(temp, 7.982e-11, 0.748, 3.148, 7.036e+05);
359 return _Verner96Fit(temp, 8.318e-11, 0.7472, 2.965, 7.001e5);
361 endrun(3,
"Recombination rate not supported\n");
372 double lowTfit =
_Verner96Fit(temp, 3.294e-11, 0.6910, 1.554e+01, 3.676e+07);
373 double highTfit =
_Verner96Fit(temp, 9.356e-10, 0.7892, 4.266e-02, 4.677e+06);
378 double upper = swtmp + deltat;
379 double lower = swtmp - deltat;
381 double interpfit = (lowTfit * (upper - temp) + highTfit * (temp - lower))/(2*deltat);
382 return (temp < lower)*lowTfit + (temp > upper)*highTfit + (upper > temp)*(temp > lower)*interpfit;
392 return 1.5e-10 / pow(temp,0.6353);
396 return _Verner96Fit(temp, 1.818E-10, 0.7492, 10.17, 2.786e6);
398 endrun(3,
"Recombination rate not supported\n");
411 return 1.9e-3 / pow(temp,1.5) * exp(-4.7e5/temp)*(1+0.3*exp(-9.4e4/temp));
419 return 1.23e-3 / pow(temp,1.5) * exp(-4.72e5/temp)*(1+0.3*exp(-9.4e4/temp));
421 endrun(3,
"Recombination rate not supported\n");
441 return _Verner96Fit(temp, 1.891e-10, 0.7524, 9.370, 2.774e6);
443 return _Verner96Fit(temp, 5.235E-11, 0.6988 + 0.0829*exp(-1.682e5/temp), 7.301, 4.475e6);
445 endrun(3,
"Recombination rate not supported\n");
451 _Voronov96Fit(
double temp,
double dE,
double PP,
double AA,
double XX,
double KK)
453 double UU = dE / (
BOLEVK * temp);
454 return AA * (1 + PP * sqrt(UU))/(XX+UU) * pow(UU, KK) * exp(-UU);
464 return 5.85e-11 * sqrt(temp) * exp(-157809.1/temp) / (1 + sqrt(temp/1e5));
470 endrun(3,
"Collisional rate not supported\n");
481 return 2.38e-11 * sqrt(temp) * exp(-285335.4/temp) / (1+ sqrt(temp/1e5));
487 endrun(3,
"Collisional rate not supported\n");
498 return 5.68e-12 * sqrt(temp) * exp(-631515.0/temp) / (1+ sqrt(temp/1e5));
504 endrun(3,
"Collisional rate not supported\n");
514 int index = (int) dind;
517 return rec_func(exp(logt));
520 return rec_tab[index + 1] * (dind - index) + rec_tab[index] * (1 - (dind - index));
531 double photorate = 0;
532 if(uvbg->
gJH0 > 0. && ne > 1e-50)
533 photorate = uvbg->
gJH0/ne * photofac;
534 return alphaHp/ (alphaHp + GammaeH0 + photorate);
541 double nHp = 1. - nH0;
556 nHe_internal(double nh, double logt, double ne, const struct
UVBG * uvbg,
double photofac)
564 if(uvbg->gJHe0 > 0. && ne > 1e-50) {
565 GammaHe0 += uvbg->gJHe0/ne * photofac;
566 GammaHep += uvbg->gJHep/ne * photofac;
569 if(GammaHe0 > 1e-50) {
570 He.
nHep = nh / (1 + alphaHep / GammaHe0 + GammaHep/alphaHepp);
571 He.
nHe0 = He.
nHep * alphaHep / GammaHe0;
572 He.
nHepp = He.
nHep * GammaHep / alphaHepp;
610 double hy_mass = 1 - helium;
611 double muienergy = 4 / (hy_mass * (3 + 4*nebynh) + 1)*ienergy;
621 ne_internal(
double nh,
double ienergy,
double ne,
double helium,
double * logt,
const struct UVBG * uvbg)
623 double yy = helium / 4 / (1 - helium);
629 return nh * nHp + yy * He.
nHep + 2 * yy * He.
nHepp;
636 #define ITERCONV 1e-6
648 double ne0 = ne_init;
652 double ne1 =
ne_internal(nh, ienergy, ne0*nh, helium, &logt1, uvbg) / nh;
660 double ne2 =
ne_internal(nh, ienergy, ne1*nh, helium, &logt1, uvbg) / nh;
661 double d = ne0 + ne2 - 2.0 * ne1;
664 if (d > 1e-15 || d < -1e-15)
665 pp = ne0 - (ne1 - ne0)*(ne1 - ne0) / d;
671 if (!isfinite(ne0) || i ==
MAXITER)
672 endrun(1,
"Ionization rate network failed to converge for nh = %g temp = %g helium=%g ienergy=%g: last ne = %g (init=%g)\n", nh,
get_temp_internal(ne0, ienergy, helium), helium, ienergy, ne0, ne_init);
686 double nh =
density * (1-helium);
756 return 1+sqrt(temp/t0);
763 return 7.5e-19 * exp(-118348.0/temp) /
_t5(temp);
770 return 5.54e-17 * pow(temp, -0.397)*exp(-473638./temp)/
_t5(temp);
777 return 9.1e-27 * pow(temp, -0.1687) * exp(-473638/temp) /
_t5(temp);
811 double y = log(temp);
813 double Ryd = 2.1798741e-11;
815 double coeffslowT[6] = {213.7913, 113.9492, 25.06062, 2.762755, 0.1515352, 3.290382e-3};
816 double coeffshighT[6] = {271.25446, 98.019455, 14.00728, 0.9780842, 3.356289e-2, 4.553323e-4};
819 tot += ((temp < 1e5)*coeffslowT[j]+(temp >=1e5)*coeffshighT[j])*pow(-y, j);
820 return 1e-20 * exp(tot);
846 return 2.851e-27 * sqrt(temp) * (5.914 - 0.5 * log(temp) + 0.01184 * pow(temp, 1./3));
872 return 1.140e-26 * sqrt(temp) * (6.607 - 0.5 * log(temp) + 7.459e-3 * pow(temp, 1./3));
887 double lt = 2 * log10(temp/zz);
888 if(lt <= log10(3.2e5))
889 gff = (0.79464 + 0.1243*lt);
891 gff = (2.13164 - 0.1240*lt);
895 gff = 1.1+0.34*exp(-pow(5.5 - log10(temp),2) /3.);
897 return 1.426e-27*sqrt(temp)* pow(zz,2) * gff;
928 const double rho =
PROTONMASS * nHcgs / (1 - helium);
945 MPI_Comm_rank(MPI_COMM_WORLD, &
ThisTask);
980 if(!TreeCoolFile || strnlen(TreeCoolFile,100) == 0) {
982 message(0,
"No TreeCool file is provided. Cooling is broken. OK for DM only runs. \n");
985 message(0,
"Using uniform UVB from file %s\n", TreeCoolFile);
1036 double nh =
density * (1 - helium);
1050 double nh =
density * (1 - helium);
1051 double nebynh = ne/nh;
1058 double yy = helium / 4 / (1 - helium);
1075 Lambda = -1*nebynh * (cff * (nHp + He.
nHep) + 4 * cff * He.
nHepp);
1077 }
else if(process ==
HEAT) {
1081 else if(process ==
RECOMB) {
1086 else if(process ==
COLLIS) {
1108 double nh =
density * (1 - helium);
1109 double nebynh = ne/nh;
1115 double yy = helium / 4 / (1 - helium);
1132 double LambdaFF = 0;
1141 LambdaFF = nebynh * (cff * (nHp + He.
nHep) + 4 * cff * He.
nHepp);
1146 double Lambda = LambdaCollis + LambdaRecomb + LambdaFF + LambdaCmptn;
1153 *ne_equilib = nebynh;
1158 double LambdaNet = Heat - Lambda - MetalCooling;
1176 double nh =
density * (1 - helium);
1190 double nh =
density * (1-helium);
1206 double yy = helium / 4 / (1 - helium);
1207 double nh =
density * (1-helium);
1211 return yy * He.
nHe0 / nh;
1213 return yy * He.
nHep / nh;
1215 return yy * He.
nHepp / nh;
int during_helium_reionization(double redshift)
static double scipy_optimize_fixed_point(double ne_init, double nh, double ienergy, double helium, double *logt, const struct UVBG *uvbg)
double recomb_alphaHp(double temp)
static double cool_FreeFree(double temp, int zz)
static struct he_ions nHe_internal(double nh, double logt, double ne, const struct UVBG *uvbg, double photofac)
static double recomb_GammaeH0(double temp)
static void load_treecool(const char *TreeCoolFile)
static double * rec_GammaHe0
static double self_shield_dens(double redshift, const struct UVBG *uvbg)
static double nHp_internal(double nH0)
static double * Gamma_log1z
static struct itp_type Eps_HI Eps_HeI Eps_HeII
static gsl_interp * GrayOpac
static double * cool_recombHePP
static double * cool_freefree1
static double * cool_collisHe0
static double * cool_recombHp
static double recomb_GammaeHep(double temp)
static double cool_CollisionalExciteHe0(double temp)
double get_ne_by_nh(double density, double ienergy, double helium, const struct UVBG *uvbg, double ne_init)
double get_compton_cooling(double density, double ienergy, double helium, double redshift, double nebynh)
static double cool_InverseCompton(double temp, double redshift)
double get_equilib_ne(double density, double ienergy, double helium, double *logt, const struct UVBG *uvbg, double ne_init)
static double cool_CollisionalHe0(double temp)
static double nH0_internal(double logt, double ne, const struct UVBG *uvbg, double photofac)
static double cool_FreeFree1(double temp)
static double cool_CollisionalExciteH0(double temp)
static double get_temp_internal(double nebynh, double ienergy, double helium)
static double _Verner96Fit(double temp, double aa, double bb, double temp0, double temp1)
static double load_tree_value(char **saveptr)
static double cool_CollisionalExciteHeP(double temp)
static void init_itp_type(double *xarr, struct itp_type *Gamma, int Nelem)
static double cool_RecombHePP(double temp)
static double _Voronov96Fit(double temp, double dE, double PP, double AA, double XX, double KK)
double get_helium_ion_phys_cgs(int ion, double density, double ienergy, double helium, const struct UVBG *uvbg, double ne_init)
static const double GrayOpac_ydata[NGRAY]
static double * cool_collisHeP
static double * rec_GammaHep
static double recomb_alphad(double temp)
static double cool_CollisionalH0(double temp)
static double cool_RecombHeP(double temp)
double get_heatingcooling_rate(double density, double ienergy, double helium, double redshift, double metallicity, const struct UVBG *uvbg, double *ne_equilib)
static double * rec_alphaHp
static double get_photo_rate(double redshift, struct itp_type *Gamma_tab)
double get_temp(double density, double ienergy, double helium, const struct UVBG *uvbg, double *ne_init)
static const double GrayOpac_zz[NGRAY]
static double recomb_alphaHepd(double temp)
static double * cool_collisH0
static double self_shield_corr(double nh, double logt, double ssdens)
static double cool_RecombDielect(double temp)
void set_cooling_params(ParameterSet *ps)
static double _t5(double temp)
static double * rec_alphaHep
static double _Verner96alphaHep(double temp)
static double cool_he_reion_factor(double nHcgs, double helium, double redshift)
static double cool_CollisionalHeP(double temp)
void set_coolpar(struct cooling_params cp)
static double cool_RecombHp(double temp)
double get_neutral_fraction_phys_cgs(double density, double ienergy, double helium, const struct UVBG *uvbg, double *ne_init)
static double ne_internal(double nh, double ienergy, double ne, double helium, double *logt, const struct UVBG *uvbg)
static double cool_CollisionalIonizeHeP(double temp)
struct UVBG get_global_UVBG(double redshift)
static struct itp_type Gamma_HI Gamma_HeI Gamma_HeII
void init_cooling_rates(const char *TreeCoolFile, const char *MetalCoolFile, Cosmology *CP)
static double get_interpolated_recomb(double logt, double *rec_tab, double rec_func(double))
static double recomb_alphaHep(double temp)
static double recomb_alphaHepp(double temp)
static struct cooling_params CoolingParams
static double * rec_GammaH0
static double cool_CollisionalIonizeH0(double temp)
static double * rec_alphaHepp
static double * cool_recombHeP
static double cool_CollisionalIonizeHe0(double temp)
double get_individual_cooling(enum CoolProcess process, double density, double ienergy, double helium, const struct UVBG *uvbg, double *ne_equilib)
static double recomb_GammaeHe0(double temp)
void InitMetalCooling(const char *MetalCoolFile)
double TableMetalCoolingRate(double redshift, double temp, double nHcgs)
void density(const ActiveParticles *act, int update_hsml, int DoEgyDensity, int BlackHoleOn, double MinEgySpec, const DriftKickTimes times, Cosmology *CP, struct sph_pred_data *SPH_predicted, MyFloat *GradRho, const ForceTree *const tree)
void message(int where, const char *fmt,...)
void endrun(int where, const char *fmt,...)
#define mymalloc(name, size)
double param_get_double(ParameterSet *ps, const char *name)
int param_get_int(ParameterSet *ps, const char *name)
int param_get_enum(ParameterSet *ps, const char *name)
double UVRedshiftThreshold
static const double tt[NEXACT]