diff --git a/examples/CoolingBox/analytical_test.py b/examples/CoolingBox/analytical_test.py index 0d83f718ced588a3ea6208ff33ee2937e172c28a..16c2fc55777eafb367896b4454f2c716538e6058 100644 --- a/examples/CoolingBox/analytical_test.py +++ b/examples/CoolingBox/analytical_test.py @@ -1,3 +1,4 @@ +import sys import matplotlib matplotlib.use("Agg") from pylab import * @@ -30,33 +31,23 @@ import numpy as np import h5py as h5 import sys -def interpol_lambda(temp_list,cooling_rate,temp): - #print(temp,temp_list[0],temp_list[len(temp_list)-1]) - if temp < temp_list[0]: +# function for interpolating 1d table of cooling rates +def interpol_lambda(u_list,cooling_rate,u): + if u < u_list[0]: return[cooling_rate[0]] - if temp > temp_list[len(temp_list)-1]: + if u > u_list[len(u_list)-1]: return[cooling_rate[len(cooling_rate)-1]] j = 0 - while temp_list[j+1] < temp: + while u_list[j+1] < u: j += 1 - cooling = cooling_rate[j]*(temp_list[j+1]-temp)/(temp_list[j+1]-temp_list[j]) + cooling_rate[j+1]*(temp-temp_list[j])/(temp_list[j+1]-temp_list[j]) + cooling = cooling_rate[j]*(u_list[j+1]-u)/(u_list[j+1]-u_list[j]) + cooling_rate[j+1]*(u-u_list[j])/(u_list[j+1]-u_list[j]) return cooling -def convert_u_to_temp_sol(u,rho): - k_b = 1.38E-16 #boltzmann - m_p = 1.67e-24 #proton mass - gamma = 5.0/3.0 - n = 2.0*0.752*rho/m_p + 0.248*rho/(4.0*m_p) - pressure = u*rho*(gamma - 1.0) - temp = pressure/(k_b*n) - return temp - # File containing the total energy stats_filename = "./energy.txt" # First snapshot snap_filename = "coolingBox_0000.hdf5" -snap_filename_mat = "../../../swiftsim_matthieu_cooling_v2/examples/CoolingBox/coolingBox_0000.hdf5" # Some constants in cgs units k_b = 1.38E-16 #boltzmann @@ -67,9 +58,7 @@ T_init = 1.0e7 # Read the initial state of the gas f = h5.File(snap_filename,'r') -f_mat = h5.File(snap_filename_mat,'r') rho = np.mean(f["/PartType0/Density"]) -rho_mat = np.mean(f["/PartType0/Density"]) pressure = np.mean(f["/PartType0/Pressure"]) # Read the units parameters from the snapshot @@ -78,96 +67,86 @@ unit_mass = units.attrs["Unit mass in cgs (U_M)"] unit_length = units.attrs["Unit length in cgs (U_L)"] unit_time = units.attrs["Unit time in cgs (U_t)"] unit_vel = unit_length/unit_time -#hubble_param = 0.71 -hubble_param = 1.0 - -unit_length = unit_length/hubble_param -unit_mass = unit_mass/hubble_param - -yHe = 0.28 -temp_0 = 1.0e7 rho = rho*unit_mass/(unit_length**3) -rho_mat = rho_mat*unit_mass/(unit_length**3) # Read snapshots if len(sys.argv) >= 4: - nsnap = int(sys.argv[4]) + nsnap = int(sys.argv[5]) else: - nsnap = 501 + print("Need to specify number of snapshots, defaulting to 100.") + nsnap = 100 npart = 4096 u_snapshots_cgs = zeros(nsnap) u_part_snapshots_cgs = zeros((nsnap,npart)) t_snapshots_cgs = zeros(nsnap) +scale_factor = zeros(nsnap) for i in range(nsnap): snap = h5.File("coolingBox_%0.4d.hdf5"%i,'r') - u_part_snapshots_cgs[i][:] = snap["/PartType0/InternalEnergy"][:]*unit_length**2/(unit_time**2) + u_part_snapshots_cgs[i][:] = snap["/PartType0/InternalEnergy"][:]*(unit_length**2)/(unit_time**2) t_snapshots_cgs[i] = snap["/Header"].attrs["Time"] * unit_time - -# Read snapshots -#nsnap_mat = 25 -#npart = 4096 -#u_snapshots_cgs_mat = zeros(nsnap_mat) -#u_part_snapshots_cgs_mat = zeros((nsnap_mat,npart)) -#t_snapshots_cgs_mat = zeros(nsnap_mat) -#for i in range(nsnap_mat): -# snap = h5.File("../../../swiftsim_matthieu_cooling_v2/examples/CoolingBox/coolingBox_%0.4d.hdf5"%i,'r') -# u_part_snapshots_cgs_mat[i][:] = snap["/PartType0/InternalEnergy"][:]*unit_length**2/(unit_time**2) -# t_snapshots_cgs_mat[i] = snap["/Header"].attrs["Time"] * unit_time + scale_factor[i] = snap["/Header"].attrs["Scale-factor"] # calculate analytic solution. Since cooling rate is constant, # temperature decrease in linear in time. # read Lambda and temperatures from table -temperature = [] +internal_energy = [] cooling_rate = [] file_in = open('cooling_output.dat', 'r') for line in file_in: data = line.split() - temperature.append(float(data[0])) + internal_energy.append(float(data[0])) cooling_rate.append(-float(data[1])) tfinal = t_snapshots_cgs[nsnap-1] -nt = 1e5 -dt = tfinal/nt +tfirst = t_snapshots_cgs[0] +nt = nsnap*10 +dt = (tfinal-tfirst)/nt t_sol = np.zeros(int(nt)) -temp_sol = np.zeros(int(nt)) u_sol = np.zeros(int(nt)) lambda_sol = np.zeros(int(nt)) -u = np.mean(u_part_snapshots_cgs[0,:]) -temp_sol[0] = convert_u_to_temp_sol(u,rho) -#print(u,temp_sol[0]) +u = np.mean(u_part_snapshots_cgs[0,:])/scale_factor[0]**2 u_sol[0] = u +t_sol[0] = tfirst +# integrate explicit ODE for j in range(int(nt-1)): t_sol[j+1] = t_sol[j] + dt - Lambda_net = interpol_lambda(temperature,cooling_rate,u_sol[j]) - nH = 0.702*rho/(m_p) - #nH = 1.0e-4 - u_next = u - Lambda_net*nH**2/rho*dt - temp_sol[j+1] = convert_u_to_temp_sol(u_next,rho) + Lambda_net = interpol_lambda(internal_energy,cooling_rate,u_sol[j]) + if j < 10: + print(u,Lambda_net) + if int(sys.argv[4]) == 1: + nH = 0.702*rho/(m_p)/scale_factor[0]**3 + ratefact = nH*0.702/m_p + else: + nH = 0.752*rho/(m_p)/scale_factor[0]**3 + ratefact = nH*0.752/m_p + u_next = u - Lambda_net*ratefact*dt u_sol[j+1] = u_next - #lambda_sol[j] = Lambda_net u = u_next - -mean_temp = np.zeros(nsnap) +u_sol = u_sol*scale_factor[0]**2 + +# swift solution mean_u = np.zeros(nsnap) for j in range(nsnap): - mean_temp[j] = convert_u_to_temp_sol(np.mean(u_part_snapshots_cgs[j,:]),rho) mean_u[j] = np.mean(u_part_snapshots_cgs[j,:]) -#mean_temp_mat = np.zeros(nsnap_mat) -#for j in range(nsnap_mat): -# mean_temp_mat[j] = convert_u_to_temp_sol(np.mean(u_part_snapshots_cgs_mat[j,:]),rho_mat) +# plot and save results +log_nh = float(sys.argv[2]) +redshift = float(sys.argv[1]) p = plt.figure(figsize = (6,6)) p1, = plt.loglog(t_sol,u_sol,linewidth = 0.5,color = 'k', marker = '*', markersize = 1.5,label = 'explicit ODE') -p2, = plt.loglog(t_snapshots_cgs,mean_u,linewidth = 0.5,color = 'r', marker = '*', markersize = 1.5,label = 'swift mean') +p2, = plt.loglog(t_snapshots_cgs,mean_u,linewidth = 0.5,color = 'r', marker = '*', markersize = 1.5,label = 'swift mean alexei') l = legend(handles = [p1,p2]) xlabel("${\\rm{Time~[s]}}$", labelpad=0, fontsize = 14) ylabel("Internal energy ${\\rm{[erg \cdot g^{-1}]}}$", fontsize = 14) -title('$n_h = 1 \\rm{cm}^{-3}, z = 0$, zero metallicity,\n relative error: ' + "{0:.4f}".format( (u_sol[int(nt)-1] - mean_u[nsnap-1])/(u_sol[int(nt)-1])), fontsize = 16) -#plt.ylim([8.0e11,3.0e12]) +if int(sys.argv[4]) == 1: + title('$n_h = 10^{' + "{}".format(log_nh) + '} \\rm{cm}^{-3}, z = ' + "{}".format(redshift) + '$, solar metallicity,\n relative error alexei: ' + "{0:.4f}".format( (u_sol[int(nt)-1] - mean_u[nsnap-1])/(u_sol[int(nt)-1])), fontsize = 16) + name = "z_"+str(sys.argv[1])+"_nh_"+str(sys.argv[2])+"_pressure_"+str(sys.argv[3])+"_solar.png" +elif int(sys.argv[4]) == 0: + title('$n_h = 10^{' + "{}".format(log_nh) + '} \\rm{cm}^{-3}, z = ' + "{}".format(redshift) + '$, zero metallicity,\n relative error alexei: ' + "{0:.4f}".format( (u_sol[int(nt)-1] - mean_u[nsnap-1])/(u_sol[int(nt)-1])), fontsize = 16) + name = "z_"+str(sys.argv[1])+"_nh_"+str(sys.argv[2])+"_pressure_"+str(sys.argv[3])+"_zero_metal.png" -savefig("energy.png", dpi=200) +savefig(name, dpi=200) print('Final internal energy ode, swift, error ' + str(u_sol[int(nt)-1]) + ' ' + str(mean_u[nsnap-1]) + ' ' + str( (u_sol[int(nt)-1] - mean_u[nsnap-1])/(u_sol[int(nt)-1]))) -#print(u_sol[int(nt)-1], mean_u[nsnap-1], (u_sol[int(nt)-1] - mean_u[nsnap-1])/(u_sol[int(nt)-1])) diff --git a/examples/CoolingBox/makeIC.py b/examples/CoolingBox/makeIC.py index aa0597c05fecabf007af0b4cda84bbf4f324c2b0..03f5626023bf1570caa65df52673c8b5565ec4a3 100644 --- a/examples/CoolingBox/makeIC.py +++ b/examples/CoolingBox/makeIC.py @@ -27,8 +27,8 @@ from numpy import * # Parameters periodic= 1 # 1 For periodic box boxSize = 1 # 1 kiloparsec -rho = 3.271e7 # Density in code units (3.2e6 is 0.1 hydrogen atoms per cm^3) -P = 4.5e9 # Pressure in code units (at 10^6K) +rho = 34504.4797588 # Density in code units (3.2e6 is 0.1 hydrogen atoms per cm^3) +P = 44554455.4455 # Pressure in code units (at 10^6K) gamma = 5./3. # Gas adiabatic index eta = 1.2349 # 48 ngbs with cubic spline kernel fileName = "coolingBox.hdf5" diff --git a/examples/CoolingBox/run.sh b/examples/CoolingBox/run.sh index 0d3959790d77dcf4512035eb95348a45fe68121b..4c97e82d3e9019869f6517d535dcb844f9660f43 100755 --- a/examples/CoolingBox/run.sh +++ b/examples/CoolingBox/run.sh @@ -21,7 +21,7 @@ then fi # Run SWIFT -../swift -s -c -C -t 16 -n 2000 coolingBox.yml +../swift -s -c -C -t 16 -n 1000 coolingBox.yml # Check energy conservation and cooling rate # python energy_plot.py diff --git a/examples/CoolingBox/test_script.sh b/examples/CoolingBox/test_script.sh index e3673256289bf7dd7fe16d493b5f4e478122e724..31bddb8c406397081e7913785785a482f82b09c2 100644 --- a/examples/CoolingBox/test_script.sh +++ b/examples/CoolingBox/test_script.sh @@ -5,13 +5,13 @@ max_number() { } # loop over redshift -for z in 0.1; do +for z in $(seq 0.01 5.0 25.01); do # loop over solar and zero metal abundances - for solar in 1; do + for solar in {0..1}; do # loop over log_10 hydrogen number density - for nh in -1; do + for nh_exp in $(seq -3 2.0 -1); do #change parameters in yml file for calculating explicit ode solution of cooling - cd ../CoolingTest_Alexei + cd ../CoolingRates if [ $solar == 1 ] then sed -i "/InitMetallicity: / s/: \+[[:alnum:],\.,-]\+/: 0.014/g" testCooling.yml @@ -41,10 +41,10 @@ for z in 0.1; do sed -i "/CalciumOverSilicon: / s/: \+[[:alnum:],\.,-]\+/: 0.0941736/g" testCooling.yml sed -i "/SulphurOverSilicon: / s/: \+[[:alnum:],\.,-]\+/: 0.6054160/g" testCooling.yml fi - # ./testCooling metals $nh - ./testCooling -z $z -d $nh -t + rm cooling_*.dat + ./testCooling -z $z -d $nh_exp cd ../CoolingBox - cp ../CoolingTest_Alexei/cooling_output.dat ./ + cp ../CoolingRates/cooling_output.dat ./ #change parameters in coolingBox.yml if [ $solar == 1 ] @@ -79,7 +79,7 @@ for z in 0.1; do # set starting, ending redshift, how often to write to file a_begin=$(python -c "print 1.0/(1.0+$z)") - a_end=$(python -c "print min(1.0, $a_begin*1.001)") + a_end=$(python -c "print min(1.0, $a_begin*1.0001)") first_ouput_a=$a_begin delta_a=$(python -c "print 1.0 + ($a_end/$a_begin - 1.0)/500.") sed -i "/a_begin: / s/: \+[[:alnum:],\.,-]\+/: $a_begin/g" coolingBox.yml @@ -88,26 +88,28 @@ for z in 0.1; do sed -i "/delta_time: / s/: \+[[:alnum:],\.,-]\+/: $delta_a/g" coolingBox.yml # change hydrogen number density - sed -i "/^rho =/ s/= \S*/= 3.2e$(expr $nh + 7)/g" makeIC.py - for pressure in 7; do + nh=$(python -c "print 3.555*10.0**($nh_exp+7)/(1.0+$z)**3") + sed -i "/^rho =/ s/= \S*/= $nh/g" makeIC.py + for pressure_index in 7; do + pressure=$(python -c "print 4.5*10.0**($pressure_index + $nh_exp + 3)/(1.0+$z)") # change pressure (and hence energy) - sed -i "/^P =/ s/= \S*/= 4.5e$(expr $pressure + $nh + 2)/g" makeIC.py + sed -i "/^P =/ s/= \S*/= $pressure/g" makeIC.py python makeIC.py + rm coolingBox_*hdf5 # run cooling box ./run.sh max=0 - for file in $( ls coolingBox_*.hdf5 ); do + for file in $( ls -lth coolingBox_*.hdf5 | head -n 1 ); do f=${file//hdf5/} f=${f//[!0-9]/} - max=$(max_number $max $f) done - frames=$((10#$max)) + frames=$((10#$f)) echo "number of frames $frames" # check if everything worked and create plots - python analytical_test.py $nh $pressure $solar $frames + python analytical_test.py $z $nh_exp $pressure_index $solar $frames done done done diff --git a/examples/CoolingRates/plots.py b/examples/CoolingRates/plots.py new file mode 100644 index 0000000000000000000000000000000000000000..969e6de713a4c421cc14d5f88ef68bafaab59a41 --- /dev/null +++ b/examples/CoolingRates/plots.py @@ -0,0 +1,58 @@ +import matplotlib.pyplot as plt + +elements = 11 +temperature = [] +cooling_rate = [[] for i in range(elements+1)] +u = [] +fu = [] +length = 0 +file_in = open('cooling_output.dat', 'r') +for line in file_in: + data = line.split() + temperature.append(float(data[0])) + cooling_rate[0].append(-float(data[1])) + +file_in.close() + +for elem in range(elements): + file_in = open('cooling_element_'+str(elem)+'.dat','r') + for line in file_in: + data = line.split() + cooling_rate[elem+1].append(-float(data[0])) + file_in.close() + +#file_in = open('newton_output.dat', 'r') +#for line in file_in: +# data = line.split() +# u.append(float(data[0])) +# fu.append(float(data[1])) +# +#file_in.close() + +#p0, = plt.plot(u,fu, color = 'k') +#p1, = plt.plot(u,[0 for x in u], color = 'r') +#p1, = plt.loglog(u,[-x for x in fu], color = 'r') +#plt.xlim([1e13,2.0e14]) +#plt.ylim([0e13,2e14]) +#plt.xlabel('u') +#plt.ylabel('f(u)') +#plt.show() + +p0, = plt.loglog(temperature, cooling_rate[0], linewidth = 0.5, color = 'k', label = 'Total') +p1, = plt.loglog(temperature, cooling_rate[1], linewidth = 0.5, color = 'k', linestyle = '--', label = 'H + He') +p2, = plt.loglog(temperature, cooling_rate[3], linewidth = 0.5, color = 'b', label = 'Carbon') +p3, = plt.loglog(temperature, cooling_rate[4], linewidth = 0.5, color = 'g', label = 'Nitrogen') +p4, = plt.loglog(temperature, cooling_rate[5], linewidth = 0.5, color = 'r', label = 'Oxygen') +p5, = plt.loglog(temperature, cooling_rate[6], linewidth = 0.5, color = 'c', label = 'Neon') +p6, = plt.loglog(temperature, cooling_rate[7], linewidth = 0.5, color = 'm', label = 'Magnesium') +p7, = plt.loglog(temperature, cooling_rate[8], linewidth = 0.5, color = 'y', label = 'Silicon') +p8, = plt.loglog(temperature, cooling_rate[9], linewidth = 0.5, color = 'lightgray', label = 'Sulphur') +p9, = plt.loglog(temperature, cooling_rate[10], linewidth = 0.5, color = 'olive', label = 'Calcium') +p10, = plt.loglog(temperature, cooling_rate[11], linewidth = 0.5, color = 'saddlebrown', label = 'Iron') +#plt.ylim([1e-24,1e-21]) +#plt.xlim([1e2,1e8]) +plt.xlabel('Temperature (K)') +plt.ylabel('Cooling rate (eagle units...)') +plt.legend(handles = [p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10]) +#plt.legend(handles = [p0,p2,p3,p4,p5,p6,p7,p8,p9]) +plt.show() diff --git a/examples/CoolingRates/plots_nh.py b/examples/CoolingRates/plots_nh.py new file mode 100644 index 0000000000000000000000000000000000000000..ab3300750e2497ec8026dbe2d5c6c7d358f87831 --- /dev/null +++ b/examples/CoolingRates/plots_nh.py @@ -0,0 +1,47 @@ +import matplotlib.pyplot as plt + +elements = 6 +temperature = [[] for i in range(elements+1)] +cooling_rate = [[] for i in range(elements+1)] +u = [] +fu = [] +length = 0 + +for elem in range(elements): + file_in = open('cooling_output_'+str(elem)+'.dat','r') + for line in file_in: + data = line.split() + temperature[elem+1].append(float(data[0])) + cooling_rate[elem+1].append(-float(data[1])) + file_in.close() + +#file_in = open('newton_output.dat', 'r') +#for line in file_in: +# data = line.split() +# u.append(float(data[0])) +# fu.append(float(data[1])) +# +#file_in.close() + +#p0, = plt.plot(u,fu, color = 'k') +#p1, = plt.plot(u,[0 for x in u], color = 'r') +#p1, = plt.loglog(u,[-x for x in fu], color = 'r') +#plt.xlim([1e13,2.0e14]) +#plt.ylim([0e13,2e14]) +#plt.xlabel('u') +#plt.ylabel('f(u)') +#plt.show() + +#p0, = plt.loglog(temperature[0], cooling_rate[0], linewidth = 0.5, color = 'k', label = 'Total') +p1, = plt.loglog(temperature[1], cooling_rate[1], linewidth = 0.5, color = 'k', label = 'nh = 10^0') +p2, = plt.loglog(temperature[2], cooling_rate[2], linewidth = 0.5, color = 'b', label = 'nh = 10^-1') +p3, = plt.loglog(temperature[3], cooling_rate[3], linewidth = 0.5, color = 'g', label = 'nh = 10^-2') +p4, = plt.loglog(temperature[4], cooling_rate[4], linewidth = 0.5, color = 'r', label = 'nh = 10^-3') +p5, = plt.loglog(temperature[5], cooling_rate[5], linewidth = 0.5, color = 'c', label = 'nh = 10^-4') +p6, = plt.loglog(temperature[6], cooling_rate[6], linewidth = 0.5, color = 'm', label = 'nh = 10^-5') +plt.ylim([1e-24,1e-21]) +plt.xlim([1e4,1e8]) +plt.legend(handles = [p1,p2,p3,p4,p5,p6]) +plt.xlabel('Temperature (K)') +plt.ylabel('Cooling rate (eagle units...)') +plt.show() diff --git a/examples/CoolingRates/testCooling.c b/examples/CoolingRates/testCooling.c index 22ca23423ebc87cf8ca5a9ba0b08762641df13ab..4f141097a99d1b73e4eac4c6ffb3f3098cebdd9f 100644 --- a/examples/CoolingRates/testCooling.c +++ b/examples/CoolingRates/testCooling.c @@ -69,6 +69,299 @@ void set_quantities(struct part *restrict p, if(cosmo->z >= 1) hydro_set_init_internal_energy(p,(u*pow(scale_factor,2))/cooling->internal_energy_scale); } +/* + * @brief Construct 1d tables from 4d EAGLE tables by + * interpolating over redshift, hydrogen number density + * and helium fraction. + * + * @param p Particle data structure + * @param cooling Cooling function data structure + * @param cosmo Cosmology data structure + * @param internal_const Physical constants data structure + * @param temp_table Pointer to 1d interpolated table of temperature values + * @param H_plus_He_heat_table Pointer to 1d interpolated table of cooling rates + * due to hydrogen and helium + * @param H_plus_He_electron_abundance_table Pointer to 1d interpolated table + * of electron abundances due to hydrogen and helium + * @param element_electron_abundance_table Pointer to 1d interpolated table + * of electron abundances due to metals + * @param element_print_cooling_table Pointer to 1d interpolated table of + * cooling rates due to each of the metals + * @param element_cooling_table Pointer to 1d interpolated table of cooling + * rates due to the contribution of all the metals + * @param abundance_ratio Pointer to array of ratios of metal abundances to solar + * @param ub Upper bound in temperature on table construction + * @param lb Lower bound in temperature on table construction + */ +void construct_1d_tables_test(const struct part *restrict p, + const struct cooling_function_data *restrict cooling, + const struct cosmology *restrict cosmo, + const struct phys_const *restrict internal_const, + double *temp_table, + double *H_plus_He_heat_table, + double *H_plus_He_electron_abundance_table, + double *element_electron_abundance_table, + double *element_print_cooling_table, + double *element_cooling_table, + float *abundance_ratio, + float *ub, float *lb){ + + // obtain mass fractions and number density for particle + float XH = p->chemistry_data.metal_mass_fraction[chemistry_element_H]; + float HeFrac = p->chemistry_data.metal_mass_fraction[chemistry_element_He] / + (XH + p->chemistry_data.metal_mass_fraction[chemistry_element_He]); + float inn_h = chemistry_get_number_density(p, cosmo, chemistry_element_H, + internal_const) * + cooling->number_density_scale; + + // find redshift, helium fraction, hydrogen number density indices and offsets + int z_index,He_i,n_h_i; + float dz,d_He,d_n_h; + get_redshift_index(cosmo->z, &z_index, &dz, cooling); + get_index_1d(cooling->HeFrac, cooling->N_He, HeFrac, &He_i, &d_He); + get_index_1d(cooling->nH, cooling->N_nH, log10(inn_h), &n_h_i, &d_n_h); + + if (cosmo->z > cooling->reionisation_redshift) { + // Photodissociation table + printf("Eagle testCooling.c photodissociation table redshift reionisation redshift %.5e %.5e\n", cosmo->z, cooling->reionisation_redshift); + construct_1d_table_from_3d(p, cooling, cosmo, internal_const, + cooling->table.photodissociation_cooling.temperature, + n_h_i, d_n_h, cooling->N_nH, He_i, d_He, cooling->N_He, cooling->N_Temp, temp_table, ub, lb); + construct_1d_table_from_3d( + p, cooling, cosmo, internal_const, + cooling->table.photodissociation_cooling.H_plus_He_heating, n_h_i, d_n_h, cooling->N_nH, + He_i, d_He, cooling->N_He, cooling->N_Temp, H_plus_He_heat_table, ub, lb); + construct_1d_table_from_3d( + p, cooling, cosmo, internal_const, + cooling->table.photodissociation_cooling.H_plus_He_electron_abundance, + n_h_i, d_n_h, cooling->N_nH, He_i, d_He, cooling->N_He, + cooling->N_Temp, H_plus_He_electron_abundance_table, ub, lb); + construct_1d_table_from_3d_elements( + p, cooling, cosmo, internal_const, + cooling->table.photodissociation_cooling.metal_heating, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_cooling_table, abundance_ratio, ub, lb); + construct_1d_print_table_from_3d_elements( + p, cooling, cosmo, internal_const, + cooling->table.photodissociation_cooling.metal_heating, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_print_cooling_table, abundance_ratio, ub, lb); + construct_1d_table_from_2d( + p, cooling, cosmo, internal_const, + cooling->table.photodissociation_cooling.electron_abundance, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_electron_abundance_table, ub, lb); + } else if (cosmo->z > cooling->Redshifts[cooling->N_Redshifts - 1]) { + printf("Eagle testCooling.c no compton table redshift max redshift %.5e %.5e\n", cosmo->z, cooling->Redshifts[cooling->N_Redshifts - 1]); + // High redshift table + construct_1d_table_from_3d(p, cooling, cosmo, internal_const, + cooling->table.no_compton_cooling.temperature, + n_h_i, d_n_h, cooling->N_nH, He_i, d_He, cooling->N_He, cooling->N_Temp, temp_table, ub, lb); + construct_1d_table_from_3d( + p, cooling, cosmo, internal_const, + cooling->table.no_compton_cooling.H_plus_He_heating, n_h_i, d_n_h, cooling->N_nH, + He_i, d_He, cooling->N_He, cooling->N_Temp, H_plus_He_heat_table, ub, lb); + construct_1d_table_from_3d( + p, cooling, cosmo, internal_const, + cooling->table.no_compton_cooling.H_plus_He_electron_abundance, + n_h_i, d_n_h, cooling->N_nH, He_i, d_He, cooling->N_He, + cooling->N_Temp, H_plus_He_electron_abundance_table, ub, lb); + construct_1d_table_from_3d_elements( + p, cooling, cosmo, internal_const, + cooling->table.no_compton_cooling.metal_heating, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_cooling_table, abundance_ratio, ub, lb); + construct_1d_print_table_from_3d_elements( + p, cooling, cosmo, internal_const, + cooling->table.no_compton_cooling.metal_heating, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_print_cooling_table, abundance_ratio, ub, lb); + construct_1d_table_from_2d( + p, cooling, cosmo, internal_const, + cooling->table.no_compton_cooling.electron_abundance, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_electron_abundance_table, ub, lb); + } else { + // Normal tables + printf("Eagle testCooling.c normal table redshift %.5e\n", cosmo->z); + construct_1d_table_from_4d(p, cooling, cosmo, internal_const, + cooling->table.element_cooling.temperature, + z_index, dz, cooling->N_Redshifts, n_h_i, d_n_h, + cooling->N_nH, He_i, d_He, cooling->N_He, cooling->N_Temp, temp_table, ub, lb); + construct_1d_table_from_4d( + p, cooling, cosmo, internal_const, + cooling->table.element_cooling.H_plus_He_heating, z_index, dz, cooling->N_Redshifts, n_h_i, d_n_h, + cooling->N_nH, He_i, d_He, cooling->N_He, cooling->N_Temp, H_plus_He_heat_table, ub, lb); + construct_1d_table_from_4d( + p, cooling, cosmo, internal_const, + cooling->table.element_cooling.H_plus_He_electron_abundance, z_index, + dz, cooling->N_Redshifts, n_h_i, d_n_h, cooling->N_nH, He_i, d_He, + cooling->N_He, cooling->N_Temp, H_plus_He_electron_abundance_table, ub, lb); + construct_1d_table_from_4d_elements( + p, cooling, cosmo, internal_const, + cooling->table.element_cooling.metal_heating, z_index, dz, cooling->N_Redshifts, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_cooling_table, abundance_ratio, ub, lb); + construct_1d_print_table_from_4d_elements( + p, cooling, cosmo, internal_const, + cooling->table.element_cooling.metal_heating, z_index, dz, cooling->N_Redshifts, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_print_cooling_table, abundance_ratio, ub, lb); + construct_1d_table_from_3d( + p, cooling, cosmo, internal_const, + cooling->table.element_cooling.electron_abundance, z_index, dz, cooling->N_Redshifts, + n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_electron_abundance_table, ub, lb); + } + +} + +/* + * @brief Compare calculation of dlambda/du (gradient of cooling rate, + * needed for Newton's method) between interpolating 1d tables and + * 4d tables + * + * @param us Units data structure + * @param p Particle data structure + * @param xp Extended particle data structure + * @param internal_const Physical constants data structure + * @param cooling Cooling function data structure + * @param cosmo Cosmology data structure + */ +void compare_dlambda_du( + const struct unit_system *restrict us, + struct part *restrict p, + const struct xpart *restrict xp, + const struct phys_const *restrict internal_const, + const struct cooling_function_data *restrict cooling, + const struct cosmology *restrict cosmo){ + + // allocate tables + double H_plus_He_heat_table[cooling->N_Temp]; + double H_plus_He_electron_abundance_table[cooling->N_Temp]; + double temp_table[cooling->N_Temp]; + double element_cooling_table[cooling->N_Temp]; + double element_print_cooling_table[cooling->N_Elements * cooling->N_Temp]; + double element_electron_abundance_table[cooling->N_Temp]; + double rate_element_table[cooling->N_Elements+2]; + float *abundance_ratio, cooling_du_dt1, cooling_du_dt2; + double dlambda_du1, dlambda_du2; + + // calculate ratio of particle metal abundances to solar + abundance_ratio = malloc((chemistry_element_count + 2)*sizeof(float)); + abundance_ratio_to_solar(p, cooling, abundance_ratio); + + // set hydrogen number density and internal energy + float nh = 1.0e-1, u = 1.0e9; + set_quantities(p, us, cooling, cosmo, internal_const, nh, u); + + // extract hydrogen and helium mass fractions + float XH = p->chemistry_data.metal_mass_fraction[chemistry_element_H]; + float HeFrac = p->chemistry_data.metal_mass_fraction[chemistry_element_He] / + (XH + p->chemistry_data.metal_mass_fraction[chemistry_element_He]); + float inn_h = chemistry_get_number_density(p, cosmo, chemistry_element_H, + internal_const) * + cooling->number_density_scale; + + // find redshift, hydrogen number density and helium fraction indices and offsets + int z_index,He_i,n_h_i; + float dz,d_He,d_n_h; + get_redshift_index(cosmo->z, &z_index, &dz, cooling); + get_index_1d(cooling->HeFrac, cooling->N_He, HeFrac, &He_i, &d_He); + get_index_1d(cooling->nH, cooling->N_nH, log10(inn_h), &n_h_i, &d_n_h); + + + // construct tables + float upper_bound = cooling->Temp[cooling->N_Temp-1]/eagle_log_10_e; + float lower_bound = cooling->Temp[0]/eagle_log_10_e; + construct_1d_tables_test(p, cooling, cosmo, internal_const, temp_table, + H_plus_He_heat_table, H_plus_He_electron_abundance_table, + element_electron_abundance_table, element_print_cooling_table, + element_cooling_table, abundance_ratio, &upper_bound, &lower_bound); + + // calculate dlambda/du for different values of internal energy + int nt = 10; + for(int i = 0; i < nt; i++){ + u = pow(10.0,9 + i); + set_quantities(p, us, cooling, cosmo, internal_const, nh, u); + cooling_du_dt1 = eagle_metal_cooling_rate_1d_table(log10(u),&dlambda_du1,H_plus_He_heat_table, + H_plus_He_electron_abundance_table, + element_print_cooling_table, + element_electron_abundance_table, + temp_table, + p,cooling,cosmo,internal_const,rate_element_table); + cooling_du_dt2 = eagle_metal_cooling_rate(log10(u), + &dlambda_du2,z_index, dz, n_h_i, d_n_h, He_i, d_He, + p,cooling,cosmo,internal_const,NULL, + abundance_ratio); + printf("u du_dt_1d du_dt_4d dlambda_du_1d dlambda_du_4d %.5e %.5e %.5e %.5e %.5e\n",u,cooling_du_dt1,cooling_du_dt2,dlambda_du1,dlambda_du2); + } +} + +/* + * @brief Compare calculating temperature between interpolating 1d tables and + * 4d tables + * + * @param us Units data structure + * @param p Particle data structure + * @param xp Extended particle data structure + * @param internal_const Physical constants data structure + * @param cooling Cooling function data structure + * @param cosmo Cosmology data structure + */ +void compare_temp( + const struct unit_system *restrict us, + struct part *restrict p, + const struct xpart *restrict xp, + const struct phys_const *restrict internal_const, + const struct cooling_function_data *restrict cooling, + const struct cosmology *restrict cosmo){ + + // allocate tables + double H_plus_He_heat_table[cooling->N_Temp]; + double H_plus_He_electron_abundance_table[cooling->N_Temp]; + double temp_table[cooling->N_Temp]; + double element_cooling_table[cooling->N_Temp]; + double element_print_cooling_table[cooling->N_Elements * cooling->N_Temp]; + double element_electron_abundance_table[cooling->N_Temp]; + float *abundance_ratio; + + // calculate ratio of particle metal abundances to solar + abundance_ratio = malloc((chemistry_element_count + 2)*sizeof(float)); + abundance_ratio_to_solar(p, cooling, abundance_ratio); + + // set hydrogen number density and internal energy + float nh = 1.0e-1, u = 1.0e9; + set_quantities(p, us, cooling, cosmo, internal_const, nh, u); + + // extract hydrogen and helium mass fractions + float XH = p->chemistry_data.metal_mass_fraction[chemistry_element_H]; + float HeFrac = p->chemistry_data.metal_mass_fraction[chemistry_element_He] / + (XH + p->chemistry_data.metal_mass_fraction[chemistry_element_He]); + float inn_h = chemistry_get_number_density(p, cosmo, chemistry_element_H, + internal_const) * + cooling->number_density_scale; + + // find redshift, hydrogen number density and helium fraction indices and offsets + int z_index,He_i,n_h_i; + float dz,d_He,d_n_h; + get_redshift_index(cosmo->z, &z_index, &dz, cooling); + get_index_1d(cooling->HeFrac, cooling->N_He, HeFrac, &He_i, &d_He); + get_index_1d(cooling->nH, cooling->N_nH, log10(inn_h), &n_h_i, &d_n_h); + + // construct tables + float upper_bound = cooling->Temp[cooling->N_Temp-1]/eagle_log_10_e; + float lower_bound = cooling->Temp[0]/eagle_log_10_e; + construct_1d_tables_test(p, cooling, cosmo, internal_const, temp_table, + H_plus_He_heat_table, H_plus_He_electron_abundance_table, + element_electron_abundance_table, element_print_cooling_table, + element_cooling_table, abundance_ratio, &upper_bound, &lower_bound); + + // calculate temperature for different values of internal energy + float T1d, T4d, delta_u; + int nt = 10; + for(int i = 0; i < nt; i++){ + u = pow(10.0,9 + i); + set_quantities(p, us, cooling, cosmo, internal_const, nh, u); + T1d = eagle_convert_u_to_temp_1d_table(log10(u), &delta_u, temp_table, + cooling); + T4d = eagle_convert_u_to_temp(log10(u), &delta_u, z_index, n_h_i, He_i, + dz, d_n_h, d_He,cooling, cosmo); + printf("u T1d T4d %.5e %.5e %.5e\n",u,pow(10.0,T1d),pow(10.0,T4d)); + } +} + /* * @brief Produces contributions to cooling rates for different * hydrogen number densities, from different metals, @@ -154,6 +447,14 @@ int main(int argc, char **argv) { abundance_ratio = malloc((chemistry_element_count + 2)*sizeof(float)); abundance_ratio_to_solar(&p, &cooling, abundance_ratio); + // Declare 1D tables + double H_plus_He_heat_table[cooling.N_Temp]; + double H_plus_He_electron_abundance_table[cooling.N_Temp]; + double temp_table[cooling.N_Temp]; + double element_cooling_table[cooling.N_Temp]; + double element_print_cooling_table[cooling.N_Elements * cooling.N_Temp]; + double element_electron_abundance_table[cooling.N_Temp]; + // extract mass fractions, calculate table indices and offsets float XH = p.chemistry_data.metal_mass_fraction[chemistry_element_H]; float HeFrac = p.chemistry_data.metal_mass_fraction[chemistry_element_He] / @@ -163,48 +464,139 @@ int main(int argc, char **argv) { get_redshift_index(cosmo.z, &z_index, &dz, &cooling); get_index_1d(cooling.HeFrac, cooling.N_He, HeFrac, &He_i, &d_He); - int nt = 250; + float upper_bound = cooling.Temp[cooling.N_Temp-1]/eagle_log_10_e; + float lower_bound = cooling.Temp[0]/eagle_log_10_e; + + int nt = 250;//, n_nh = 6; double u = pow(10.0,10); + //if (argc == 1 || strcmp(argv[1], "nh") == 0){ + // Calculate cooling rates at different densities + //for(int i = 0; i < n_nh; i++){ + // // Open files + // char output_filename[21]; + // sprintf(output_filename, "%s%d%s", "cooling_output_", i, ".dat"); + // FILE *output_file = fopen(output_filename, "w"); + // if (output_file == NULL) { + // printf("Error opening file!\n"); + // exit(1); + // } + + // // set hydrogen number density, construct tables + // nh = pow(10.0,-i); + // set_quantities(&p, &us, &cooling, &cosmo, &internal_const, nh, u); + // construct_1d_tables_test(&p, &cooling, &cosmo, &internal_const, + // temp_table, H_plus_He_heat_table, + // H_plus_He_electron_abundance_table, + // element_electron_abundance_table, + // element_print_cooling_table, + // element_cooling_table, + // abundance_ratio, &upper_bound, &lower_bound); + // get_index_1d(cooling.nH, cooling.N_nH, log10(nh), &n_h_i, &d_n_h); + + // for(int j = 0; j < nt; j++){ + // // set internal energy + // set_quantities(&p, &us, &cooling, &cosmo, &internal_const, nh, pow(10.0,11.0 + j*8.0/nt)); + // u = hydro_get_physical_internal_energy(&p,&cosmo)*cooling.internal_energy_scale; + // double dlambda_du; + // float delta_u, cooling_du_dt, logT; + + // // calculate cooling rates using 1d tables + // if (tables == 1) { + // cooling_du_dt = eagle_metal_cooling_rate_1d_table(log10(u),&dlambda_du,H_plus_He_heat_table, + // H_plus_He_electron_abundance_table, + // element_print_cooling_table, + // element_electron_abundance_table, + // temp_table, + // z_index, dz, n_h_i, d_n_h, He_i, d_He, + // &p,&cooling,&cosmo,&internal_const,NULL, + // abundance_ratio); + // logT = eagle_convert_u_to_temp_1d_table(log10(u), &delta_u, temp_table, + // &p,&cooling, &cosmo, &internal_const); + // } else { + // // calculate cooling rates using 4d tables + // cooling_du_dt = eagle_metal_cooling_rate(log10(u), + // &dlambda_du,z_index, dz, n_h_i, d_n_h, He_i, d_He, + // &p,&cooling,&cosmo,&internal_const,NULL, + // abundance_ratio); + // logT = eagle_convert_u_to_temp(log10(u), &delta_u, z_index, n_h_i, He_i, + // dz, d_n_h, d_He, &p,&cooling, &cosmo, &internal_const); + // } + // float temperature_swift = pow(10.0,logT); + // fprintf(output_file,"%.5e %.5e\n", temperature_swift,cooling_du_dt); + // } + // fclose(output_file); + //} + //} // Calculate contributions from metals to cooling rate - // open file - char output_filename[21]; - sprintf(output_filename, "%s", "cooling_output.dat"); - FILE *output_file = fopen(output_filename, "w"); - if (output_file == NULL) { - printf("Error opening file!\n"); - exit(1); - } + //if (argc >= 1 || strcmp(argv[1],"metals") == 0) { + // open file + char output_filename[21]; + sprintf(output_filename, "%s", "cooling_output.dat"); + FILE *output_file = fopen(output_filename, "w"); + if (output_file == NULL) { + printf("Error opening file!\n"); + exit(1); + } - // set hydrogen number density, construct 1d tables - if (log_10_nh == 100) { - nh = 1.0e-1; - } else { - nh = pow(10.0,log_10_nh); - } - //if (argc > 2) nh = pow(10.0,strtod(argv[2],NULL)); - u = pow(10.0,14.0); - set_quantities(&p, &us, &cooling, &cosmo, &internal_const, nh, u); - float inn_h = chemistry_get_number_density(&p, &cosmo, chemistry_element_H, - &internal_const) * - cooling.number_density_scale; - get_index_1d(cooling.nH, cooling.N_nH, log10(inn_h), &n_h_i, &d_n_h); - - // Loop over internal energy - for(int j = 0; j < nt; j++){ - set_quantities(&p, &us, &cooling, &cosmo, &internal_const, nh, pow(10.0,10.0 + j*8.0/nt)); - u = hydro_get_physical_internal_energy(&p,&cosmo)*cooling.internal_energy_scale; - float cooling_du_dt; - - // calculate cooling rates using 4d tables - cooling_du_dt = eagle_print_metal_cooling_rate( - z_index, dz, n_h_i, d_n_h, He_i, d_He, - &p,&cooling,&cosmo,&internal_const, - abundance_ratio); - fprintf(output_file,"%.5e %.5e\n", u,cooling_du_dt); - } - fclose(output_file); - printf("done\n"); + // set hydrogen number density, construct 1d tables + if (log_10_nh == 100) { + nh = 1.0e-1; + } else { + nh = pow(10.0,log_10_nh); + } + //if (argc > 2) nh = pow(10.0,strtod(argv[2],NULL)); + printf("Eagle testcooling.c nh %.5e\n", nh); + u = pow(10.0,14.0); + set_quantities(&p, &us, &cooling, &cosmo, &internal_const, nh, u); + construct_1d_tables_test(&p, &cooling, &cosmo, &internal_const, + temp_table, H_plus_He_heat_table, + H_plus_He_electron_abundance_table, + element_electron_abundance_table, + element_print_cooling_table, + element_cooling_table, + abundance_ratio, &upper_bound, &lower_bound); + float inn_h = chemistry_get_number_density(&p, &cosmo, chemistry_element_H, + &internal_const) * + cooling.number_density_scale; + printf("Eagle testcooling.c inn_h %.5e\n", inn_h); + get_index_1d(cooling.nH, cooling.N_nH, log10(inn_h), &n_h_i, &d_n_h); + + // Loop over internal energy + for(int j = 0; j < nt; j++){ + set_quantities(&p, &us, &cooling, &cosmo, &internal_const, nh, pow(10.0,10.0 + j*8.0/nt)); + u = hydro_get_physical_internal_energy(&p,&cosmo)*cooling.internal_energy_scale; + float delta_u, cooling_du_dt, logT; + + // calculate cooling rates using 1d tables + if (tables == 1) { + cooling_du_dt = eagle_print_metal_cooling_rate_1d_table(H_plus_He_heat_table, + H_plus_He_electron_abundance_table, + element_print_cooling_table, + element_electron_abundance_table, + temp_table, + &p,&cooling,&cosmo,&internal_const); + logT = eagle_convert_u_to_temp_1d_table(log10(u), &delta_u, temp_table, + &cooling); + } else { + // calculate cooling rates using 4d tables + cooling_du_dt = eagle_print_metal_cooling_rate( + z_index, dz, n_h_i, d_n_h, He_i, d_He, + &p,&cooling,&cosmo,&internal_const, + abundance_ratio); + logT = eagle_convert_u_to_temp(log10(u), &delta_u, z_index, n_h_i, He_i, + dz, d_n_h, d_He,&cooling, &cosmo); + } + //float temperature_swift = pow(10.0,logT); + //fprintf(output_file,"%.5e %.5e\n", temperature_swift,cooling_du_dt); + fprintf(output_file,"%.5e %.5e\n", u,cooling_du_dt); + } + fclose(output_file); + //} + + // compare temperatures and dlambda/du calculated from 1d and 4d tables + //compare_temp(&us, &p, &xp, &internal_const, &cooling, &cosmo); + //compare_dlambda_du(&us, &p, &xp, &internal_const, &cooling, &cosmo); free(params); return 0; diff --git a/examples/CoolingRates/testCooling.yml b/examples/CoolingRates/testCooling.yml index 3010636433d35421009539d1858722ea89820bc9..db3a7cc00a529dcc403d4c24c11b30186baa7896 100644 --- a/examples/CoolingRates/testCooling.yml +++ b/examples/CoolingRates/testCooling.yml @@ -59,16 +59,16 @@ InitialConditions: cleanup_h_factors: 1 # Remove the h-factors inherited from Gadget EAGLEChemistry: - InitMetallicity: 0.014 - InitAbundance_Hydrogen: 0.70649785 - InitAbundance_Helium: 0.28055534 - InitAbundance_Carbon: 2.0665436e-3 - InitAbundance_Nitrogen: 8.3562563e-4 - InitAbundance_Oxygen: 5.4926244e-3 - InitAbundance_Neon: 1.4144605e-3 - InitAbundance_Magnesium: 5.907064e-4 - InitAbundance_Silicon: 6.825874e-4 - InitAbundance_Iron: 1.1032152e-3 + InitMetallicity: 0.0 + InitAbundance_Hydrogen: 0.752 + InitAbundance_Helium: 0.248 + InitAbundance_Carbon: 0.000 + InitAbundance_Nitrogen: 0.000 + InitAbundance_Oxygen: 0.000 + InitAbundance_Neon: 0.000 + InitAbundance_Magnesium: 0.000 + InitAbundance_Silicon: 0.000 + InitAbundance_Iron: 0.000 CalciumOverSilicon: 0.0941736 SulphurOverSilicon: 0.6054160 diff --git a/src/chemistry/EAGLE/chemistry.h b/src/chemistry/EAGLE/chemistry.h index 5d7e0e8883d81996c1f8e10288f7d63bdeb9c365..04bc6371973743bfdd88c68bde38a2d95ec0fe80 100644 --- a/src/chemistry/EAGLE/chemistry.h +++ b/src/chemistry/EAGLE/chemistry.h @@ -214,8 +214,6 @@ chemistry_get_number_density(const struct part* restrict p, double element_mass = internal_const->const_proton_mass * atomic_number; number_density = p->chemistry_data.metal_mass_fraction[elem] * hydro_get_physical_density(p, cosmo) / element_mass; - // number_density = - // p->chemistry_data.metal_mass_fraction[elem]*hydro_get_comoving_density(p)/element_mass; return number_density; } diff --git a/src/cooling/EAGLE/cooling.c b/src/cooling/EAGLE/cooling.c index 419a2fb162926afe56fe6e0473a80300bc3c7050..0f0b90b17140ed38570e09733318c53f6a7c6abc 100644 --- a/src/cooling/EAGLE/cooling.c +++ b/src/cooling/EAGLE/cooling.c @@ -17,8 +17,8 @@ * ******************************************************************************/ /** - * @file src/cooling/EAGLE/cooling.h - * @brief EAGLE cooling function + * @file src/cooling/EAGLE/cooling.c + * @brief EAGLE cooling functions */ /* Config parameters. */ @@ -45,6 +45,9 @@ #include "units.h" const float explicit_tolerance = 0.05; +const float newton_tolerance = 1.0e-2; // lower than bisection_tol because using log(u) +const float bisection_tolerance = 1.0e-6; +const double bracket_factor = 1.0488088481701; // sqrt(1.1) to match EAGLE /* * @brief calculates heating due to helium reionization @@ -116,7 +119,7 @@ __attribute__((always_inline)) INLINE double eagle_metal_cooling_rate( double T_gam, solar_electron_abundance, solar_electron_abundance1, solar_electron_abundance2, elem_cool1, elem_cool2; double n_h = chemistry_get_number_density(p, cosmo, chemistry_element_H, internal_const) * - cooling->number_density_scale; // chemistry_data + cooling->number_density_scale; double z = cosmo->z; double cooling_rate = 0.0, temp_lambda, temp_lambda1, temp_lambda2; float du; @@ -135,8 +138,8 @@ __attribute__((always_inline)) INLINE double eagle_metal_cooling_rate( // the temperature table. temp = eagle_convert_u_to_temp(log_10_u, &du, z_index, n_h_i, He_i, - dz, d_n_h, d_He, p, - cooling, cosmo, internal_const); + dz, d_n_h, d_He, + cooling, cosmo); get_index_1d(cooling->Temp, cooling->N_Temp, temp, &temp_i, &d_temp); /* ------------------ */ @@ -305,14 +308,12 @@ __attribute__((always_inline)) INLINE double eagle_metal_cooling_rate_1d_table( double log_10_u, double *dlambda_du, double *H_plus_He_heat_table, double *H_plus_He_electron_abundance_table, double *element_cooling_table, - double *element_electron_abundance_table, double *temp_table, int z_index, - float dz, int n_h_i, float d_n_h, int He_i, float d_He, + double *element_electron_abundance_table, double *temp_table, const struct part *restrict p, const struct cooling_function_data *restrict cooling, const struct cosmology *restrict cosmo, const struct phys_const *internal_const, - double *element_lambda, - float *solar_ratio) { + double *element_lambda) { double T_gam, solar_electron_abundance; double n_h = chemistry_get_number_density(p, cosmo, chemistry_element_H, internal_const) * @@ -330,8 +331,7 @@ eagle_metal_cooling_rate_1d_table( // interpolate to get temperature of particles, find where we are in // the temperature table. - temp = eagle_convert_u_to_temp_1d_table(log_10_u, &du, temp_table, p, cooling, cosmo, - internal_const); + temp = eagle_convert_u_to_temp_1d_table(log_10_u, &du, temp_table, cooling); get_index_1d(cooling->Temp, cooling->N_Temp, temp, &temp_i, &d_temp); /* ------------------ */ @@ -480,15 +480,14 @@ __attribute__((always_inline)) INLINE double eagle_cooling_rate_1d_table( lambda_net = eagle_metal_cooling_rate_1d_table( logu/eagle_log_10, dLambdaNet_du, H_plus_He_heat_table, H_plus_He_electron_abundance_table, element_cooling_table, - element_electron_abundance_table, temp_table, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, internal_const, element_lambda, abundance_ratio); + element_electron_abundance_table, temp_table, p, cooling, cosmo, internal_const, element_lambda); return lambda_net; } /* * @brief Wrapper function used to calculate cooling rate and dLambda_du. - * Prints contribution from each element to cooling rate for testing purposes. + * Writes to file contribution from each element to cooling rate for testing purposes. * Table indices and offsets for redshift, hydrogen number density and * helium fraction are passed it so as to compute them only once per particle. * @@ -554,12 +553,6 @@ eagle_print_metal_cooling_rate( * @param element_electron_abundance_table 1D table of electron abundances due * to metals * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset * @param p Particle structure * @param cooling Cooling data structure * @param cosmo Cosmology structure @@ -570,12 +563,10 @@ __attribute__((always_inline)) INLINE double eagle_print_metal_cooling_rate_1d_table( double *H_plus_He_heat_table, double *H_plus_He_electron_abundance_table, double *element_print_cooling_table, double *element_electron_abundance_table, - double *temp_table, int z_index, float dz, int n_h_i, float d_n_h, int He_i, - float d_He, const struct part *restrict p, + double *temp_table, const struct part *restrict p, const struct cooling_function_data *restrict cooling, const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, - float *abundance_ratio) { + const struct phys_const *internal_const) { double *element_lambda, lambda_net = 0.0; element_lambda = malloc((cooling->N_Elements + 2) * sizeof(double)); double u = hydro_get_physical_internal_energy(p, cosmo) * @@ -597,8 +588,7 @@ eagle_print_metal_cooling_rate_1d_table( lambda_net = eagle_metal_cooling_rate_1d_table( log10(u), &dLambdaNet_du, H_plus_He_heat_table, H_plus_He_electron_abundance_table, element_print_cooling_table, - element_electron_abundance_table, temp_table, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, internal_const, element_lambda, abundance_ratio); + element_electron_abundance_table, temp_table, p, cooling, cosmo, internal_const, element_lambda); for (int j = 0; j < cooling->N_Elements + 2; j++) { fprintf(output_file[j], "%.5e\n", element_lambda[j]); } @@ -614,13 +604,6 @@ eagle_print_metal_cooling_rate_1d_table( * * @param logu_init Initial guess for log(internal energy) * @param u_ini Internal energy at beginning of hydro step - * @param H_plus_He_heat_table 1D table of heating rates due to H, He - * @param H_plus_He_electron_abundance_table 1D table of electron abundances due - * to H,He - * @param element_cooling_table 1D table of heating rates due to metals - * @param element_electron_abundance_table 1D table of electron abundances due - * to metals - * @param temp_table 1D table of temperatures * @param z_index Redshift index of particle * @param dz Redshift offset of particle * @param n_h_i Particle hydrogen number density index @@ -634,18 +617,15 @@ eagle_print_metal_cooling_rate_1d_table( * @param dt Hydro timestep */ __attribute__((always_inline)) INLINE float bisection_iter( - float logu_init, double u_ini, double *H_plus_He_heat_table, - double *H_plus_He_electron_abundance_table, double *element_cooling_table, - double *element_electron_abundance_table, double *temp_table, int z_index, + float logu_init, double u_ini, int z_index, float dz, int n_h_i, float d_n_h, int He_i, float d_He, float He_reion_heat, struct part *restrict p, const struct cosmology *restrict cosmo, const struct cooling_function_data *restrict cooling, const struct phys_const *restrict phys_const, - float *abundance_ratio, float dt, float *ub, float *lb) { - double logu_upper, logu_lower, logu_next, LambdaNet_upper, LambdaNet_lower, LambdaNet_next, LambdaNet, dLambdaNet_du; + float *abundance_ratio, float dt) { + double u_upper, u_lower, u_next, LambdaNet, dLambdaNet_du; int i = 0; - const float bisection_tolerance = 1.0e-8; - const double bracket_factor = log(sqrt(1.1)); + double u_init = exp(logu_init); float XH = p->chemistry_data.metal_mass_fraction[chemistry_element_H]; @@ -659,64 +639,60 @@ __attribute__((always_inline)) INLINE float bisection_iter( double ratefact = inn_h * (XH / eagle_proton_mass_cgs); // Bracketing - logu_lower = logu_init; - logu_upper = logu_init; + u_lower = u_init; + u_upper = u_init; LambdaNet = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( - logu_init, &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, + log(u_init), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); if (LambdaNet < 0){ - logu_lower -= bracket_factor; - logu_upper += bracket_factor; + u_lower /= bracket_factor; + u_upper *= bracket_factor; - while(LambdaNet < 0) { - logu_lower -= bracket_factor; - logu_upper -= bracket_factor; + LambdaNet = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( + log(u_lower), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, + He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); + while(u_lower - u_ini - LambdaNet*ratefact*dt > 0) { + u_lower /= bracket_factor; + u_upper /= bracket_factor; LambdaNet = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( - logu_lower, &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, + log(u_lower), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); } - LambdaNet_lower = LambdaNet; - LambdaNet_upper = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( - logu_upper, &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); } else { - logu_lower -= bracket_factor; - logu_upper += bracket_factor; + u_lower /= bracket_factor; + u_upper *= bracket_factor; - while(LambdaNet > 0) { - logu_lower += bracket_factor; - logu_upper += bracket_factor; + LambdaNet = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( + log(u_upper), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, + He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); + while(u_upper - u_ini - LambdaNet*ratefact*dt < 0) { + u_lower *= bracket_factor; + u_upper *= bracket_factor; LambdaNet = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( - logu_upper, &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, + log(u_upper), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); } - LambdaNet_upper = LambdaNet; - LambdaNet_lower = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( - logu_lower, &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); } // bisection iterations i = 0; do { - logu_next = 0.5 * (logu_lower + logu_upper); - LambdaNet_next = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( - logu_next, &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, + u_next = 0.5 * (u_lower + u_upper); + LambdaNet = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( + log(u_next), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); - if (LambdaNet_lower * LambdaNet_next < 0) { - logu_upper = logu_next; - LambdaNet_upper = LambdaNet_next; + if (u_next - u_ini - LambdaNet*ratefact*dt > 0.0) { + u_upper = u_next; } else { - logu_lower = logu_next; - LambdaNet_lower = LambdaNet_next; + u_lower = u_next; } i++; - } while (fabs(logu_lower - logu_upper) > bisection_tolerance && i < 50*eagle_max_iterations); + } while (fabs(u_upper - u_lower)/u_next > bisection_tolerance && i < 50*eagle_max_iterations); - if (i >= 50*eagle_max_iterations) n_eagle_cooling_rate_calls_4++; + if (i >= 50*eagle_max_iterations) error("Particle id %llu failed to converge", p->id); - return logu_upper; + return log(u_upper); } @@ -740,9 +716,7 @@ __attribute__((always_inline)) INLINE float bisection_iter( * @param phys_const Physical constants structure * @param abundance_ratio Array of ratios of metal abundance to solar * @param dt timestep - * @param printflag Flag to identify if scheme failed to converge - * @param lb lower bound to be used by bisection scheme - * @param ub upper bound to be used by bisection scheme + * @param bisection_flag Flag to identify if scheme failed to converge */ __attribute__((always_inline)) INLINE float newton_iter( float logu_init, double u_ini, int z_index, @@ -751,12 +725,10 @@ __attribute__((always_inline)) INLINE float newton_iter( const struct cosmology *restrict cosmo, const struct cooling_function_data *restrict cooling, const struct phys_const *restrict phys_const, - float *abundance_ratio, float dt, int *printflag, - float *lb, float *ub) { + float *abundance_ratio, float dt, int *bisection_flag) { /* this routine does the iteration scheme, call one and it iterates to * convergence */ - const float newton_tolerance = 1.0e-2; double logu, logu_old; double dLambdaNet_du, LambdaNet; float XH = p->chemistry_data.metal_mass_fraction[chemistry_element_H]; @@ -773,30 +745,17 @@ __attribute__((always_inline)) INLINE float newton_iter( logu_old = logu_init; logu = logu_old; int i = 0; - // float log_table_bound_high = 43.749, log_table_bound_low = 20.723; float log_table_bound_high = (cooling->Therm[cooling->N_Temp-1]+1)/eagle_log_10_e; float log_table_bound_low = (cooling->Therm[0]+1)/eagle_log_10_e; do /* iterate to convergence */ { - // Count how many steps - n_eagle_cooling_rate_calls_1++; - logu_old = logu; LambdaNet = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate( logu_old, &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); - // Assign to upper, lower bounds the highest or lowest values of - // cooling rate seen so far. - if (LambdaNet < 0) { - *ub = fmin(*ub,logu_old); - } else if (LambdaNet > 0) { - *lb = fmax(*lb,logu_old); - } - - // Newton iteration. logu = logu_old - (1.0 - u_ini * exp(-logu_old) - LambdaNet * ratefact * dt * exp(-logu_old)) / @@ -814,10 +773,8 @@ __attribute__((always_inline)) INLINE float newton_iter( i++; } while (fabs(logu - logu_old) > newton_tolerance && i < eagle_max_iterations); if (i >= eagle_max_iterations) { - // count how many failed to converge - n_eagle_cooling_rate_calls_3++; // flag to trigger bisection scheme - if (*printflag == 0) *printflag = 1; + *bisection_flag = 1; } return logu; @@ -883,10 +840,10 @@ void cooling_cool_part( double ratefact, u, LambdaNet, LambdaTune = 0, dLambdaNet_du; int He_i, n_h_i; float d_He, d_n_h; - const float hydro_du_dt = hydro_get_internal_energy_dt(p); + const float hydro_du_dt = hydro_get_physical_internal_energy_dt(p, cosmo); double u_old = (hydro_get_physical_internal_energy(p, cosmo) - + hydro_get_internal_energy_dt(p) * dt) * + + hydro_du_dt * dt) * cooling->internal_energy_scale; get_redshift_index(cosmo->z, &z_index, &dz, cooling); @@ -909,6 +866,7 @@ void cooling_cool_part( /* ratefact = inn_h * inn_h / rho; Might lead to round-off error: replaced by * equivalent expression below */ ratefact = inn_h * (XH / eagle_proton_mass_cgs); + /* set helium and hydrogen reheating term */ if (cooling->he_reion == 1) LambdaTune = eagle_helium_reionization_extraheat(z_index, dz, cooling); @@ -922,51 +880,24 @@ void cooling_cool_part( log(u_ini), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); - if (p->id == 1823) printf("Eagle cooling.h id dt dt normalised %llu %.5e %.5e\n", p->id, dt, dt/units_cgs_conversion_factor(us, UNIT_CONV_TIME)); - if (fabs(ratefact * LambdaNet * dt) < explicit_tolerance * u_old) { // if cooling rate is small, take the explicit solution u = u_old + ratefact * LambdaNet * dt; } else { - // count how many times we use newton scheme - n_eagle_cooling_rate_calls_2++; - float logu, lower_bound = cooling->Therm[0]/eagle_log_10_e, upper_bound = cooling->Therm[cooling->N_Temp-1]/eagle_log_10_e; + float logu; double u_eq = u_ini; if (dt > 0) { + // newton method double log_u_temp = log(u_eq); - - int printflag = 0; + int bisection_flag = 0; logu = newton_iter(log_u_temp, u_ini, z_index, dz, n_h_i, d_n_h, He_i, d_He, LambdaTune, p, cosmo, cooling, phys_const, - abundance_ratio, dt, &printflag, &lower_bound, &upper_bound); - if (printflag == 1) { + abundance_ratio, dt, &bisection_flag); + if (bisection_flag == 1) { // newton method didn't work, so revert to bisection - - // construct 1d table of cooling rates wrt temperature - double temp_table[cooling->N_Temp]; // WARNING sort out how it is declared/allocated - double H_plus_He_heat_table[cooling->N_Temp]; - double H_plus_He_electron_abundance_table[cooling->N_Temp]; - double element_cooling_table[cooling->N_Temp]; - double element_cooling_print_table[cooling->N_Elements*cooling->N_Temp]; - double element_electron_abundance_table[cooling->N_Temp]; - construct_1d_tables(z_index, dz, n_h_i, d_n_h, He_i, d_He, - phys_const, us, cosmo, cooling, p, - abundance_ratio, - H_plus_He_heat_table, - H_plus_He_electron_abundance_table, - element_cooling_table, - element_cooling_print_table, - element_electron_abundance_table, - temp_table, - &upper_bound, - &lower_bound); - // perform bisection scheme - logu = bisection_iter(log_u_temp,u_ini,H_plus_He_heat_table,H_plus_He_electron_abundance_table,element_cooling_print_table,element_electron_abundance_table,temp_table,z_index,dz,n_h_i,d_n_h,He_i,d_He,LambdaTune,p,cosmo,cooling,phys_const,abundance_ratio,dt,&upper_bound,&lower_bound); - - // do not trigger bisection again. - printflag = 2; + logu = bisection_iter(log_u_temp,u_ini,z_index,dz,n_h_i,d_n_h,He_i,d_He,LambdaTune,p,cosmo,cooling,phys_const,abundance_ratio,dt); } u = exp(logu); } @@ -975,11 +906,12 @@ void cooling_cool_part( // calculate du/dt float cooling_du_dt = 0.0; if (dt > 0) { - cooling_du_dt = (u - u_ini) / dt / cooling->power_scale; + cooling_du_dt = (u - u_ini) / dt / cooling->power_scale / cosmo->a2_inv; } /* Update the internal energy time derivative */ - hydro_set_internal_energy_dt(p, hydro_du_dt + cooling_du_dt); + + hydro_set_physical_internal_energy_dt(p, cosmo, hydro_du_dt + cooling_du_dt); /* Store the radiated energy */ xp->cooling_data.radiated_energy += @@ -1123,7 +1055,7 @@ INLINE void cooling_update(const struct phys_const* phys_const, * @param cooling Cooling data structure containing properties to initialize */ INLINE void cooling_init_backend( - const struct swift_params *parameter_file, const struct unit_system *us, + struct swift_params *parameter_file, const struct unit_system *us, const struct phys_const *phys_const, struct cooling_function_data *cooling) { @@ -1152,7 +1084,6 @@ INLINE void cooling_init_backend( sprintf(fname, "%sz_0.000.hdf5", cooling->cooling_table_path); ReadCoolingHeader(fname, cooling); cooling->table = eagle_readtable(cooling->cooling_table_path, cooling); - printf("Eagle cooling.h read table \n"); // allocate array for solar abundances cooling->solar_abundances = malloc(cooling->N_Elements * sizeof(double)); diff --git a/src/cooling/EAGLE/cooling.h b/src/cooling/EAGLE/cooling.h index 1266b1aede587274bbdd8750e5c09b09bcbf8bb0..c6d4cb269ca50e34834453fdf04a6464fc86eb9d 100644 --- a/src/cooling/EAGLE/cooling.h +++ b/src/cooling/EAGLE/cooling.h @@ -21,39 +21,17 @@ /** * @file src/cooling/EAGLE/cooling.h - * @brief EAGLE cooling function + * @brief EAGLE cooling function declarations */ -/* Config parameters. */ -#include "../config.h" - -/* Some standard headers. */ -#include <float.h> -#include <hdf5.h> -#include <math.h> -#include <time.h> - /* Local includes. */ -#include "chemistry.h" #include "cooling_struct.h" +#include "cosmology.h" #include "eagle_cool_tables.h" -#include "error.h" -#include "hydro.h" -#include "io_properties.h" -#include "parser.h" #include "part.h" #include "physical_constants.h" #include "units.h" -/* number of calls to eagle cooling rate */ -extern int n_eagle_cooling_rate_calls_1; -extern int n_eagle_cooling_rate_calls_2; -extern int n_eagle_cooling_rate_calls_3; -extern int n_eagle_cooling_rate_calls_4; - -static int get_redshift_index_first_call = 0; -static int get_redshift_index_previous = -1; - enum hdf5_allowed_types { hdf5_short, hdf5_int, @@ -63,2248 +41,126 @@ enum hdf5_allowed_types { hdf5_char }; +double eagle_helium_reionization_extraheat(double, double, const struct cooling_function_data *restrict); -/** - * @brief Returns the 1d index of element with 2d indices i,j - * from a flattened 2d array in row major order - * - * @param i, j Indices of element of interest - * @param nx, ny Sizes of array dimensions - */ -__attribute__((always_inline)) INLINE int row_major_index_2d(int i, int j, - int nx, int ny) { - int index = i * ny + j; -#ifdef SWIFT_DEBUG_CHECKS - assert(i < nx); - assert(j < ny); -#endif - return index; -} - -/** - * @brief Returns the 1d index of element with 3d indices i,j,k - * from a flattened 3d array in row major order - * - * @param i, j, k Indices of element of interest - * @param nx, ny, nz Sizes of array dimensions - */ -__attribute__((always_inline)) INLINE int row_major_index_3d(int i, int j, - int k, int nx, - int ny, int nz) { - int index = i * ny * nz + j * nz + k; -#ifdef SWIFT_DEBUG_CHECKS - assert(i < nx); - assert(j < ny); - assert(k < nz); -#endif - return index; -} - -/** - * @brief Returns the 1d index of element with 4d indices i,j,k,l - * from a flattened 4d array in row major order - * - * @param i, j, k, l Indices of element of interest - * @param nx, ny, nz, nw Sizes of array dimensions - */ -__attribute__((always_inline)) INLINE int row_major_index_4d(int i, int j, - int k, int l, - int nx, int ny, - int nz, int nw) { - int index = i * ny * nz * nw + j * nz * nw + k * nw + l; -#ifdef SWIFT_DEBUG_CHECKS - assert(i < nx); - assert(j < ny); - assert(k < nz); - assert(l < nw); -#endif - return index; -} - -/* - * @brief This routine returns the position i of a value x in a 1D table and the - * displacement dx needed for the interpolation. The table is assumed to - * be evenly spaced. - * - * @param table Pointer to table of values - * @param ntable Size of the table - * @param x Value whose position within the array we are interested in - * @param i Pointer to the index whose corresponding table value - * is the greatest value in the table less than x - * @param dx Pointer to offset of x within table cell - */ -__attribute__((always_inline)) INLINE void get_index_1d(float *table, - int ntable, double x, - int *i, float *dx) { - float dxm1; - const float EPS = 1.e-4; - - dxm1 = (float)(ntable - 1) / (table[ntable - 1] - table[0]); - - if ((float)x <= table[0] + EPS) { - *i = 0; - *dx = 0; - } else if ((float)x >= table[ntable - 1] - EPS) { - *i = ntable - 2; - *dx = 1; - } else { - *i = (int)floor(((float)x - table[0]) * dxm1); - *dx = ((float)x - table[*i]) * dxm1; - } -} - -/* - * @brief This routine returns the position i of a value z in the redshift table - * and the - * displacement dx needed for the interpolation. - * - * @param z Redshift whose position within the redshift array we are interested - * in - * @param z_index i Pointer to the index whose corresponding redshift - * is the greatest value in the redshift table less than x - * @param dx Pointer to offset of z within redshift cell - * @param cooling Pointer to cooling structure (contains redshift table) - */ -__attribute__((always_inline)) INLINE static void get_redshift_index( - float z, int *z_index, float *dz, - const struct cooling_function_data *restrict cooling) { - int i, iz; - - if (get_redshift_index_first_call == 0) { - get_redshift_index_first_call = 1; - get_redshift_index_previous = cooling->N_Redshifts - 2; - - /* this routine assumes cooling_redshifts table is in increasing order. Test - * this. */ - for (i = 0; i < cooling->N_Redshifts - 2; i++) - if (cooling->Redshifts[i + 1] < cooling->Redshifts[i]) { - error("[get_redshift_index]: table should be in increasing order\n"); - } - } - - /* before the earliest redshift or before hydrogen reionization, flag for - * collisional cooling */ - if (z > cooling->reionisation_redshift) { - *z_index = cooling->N_Redshifts; - *dz = 0.0; - } - /* from reionization use the cooling tables */ - else if (z > cooling->Redshifts[cooling->N_Redshifts - 1] && - z <= cooling->reionisation_redshift) { - *z_index = cooling->N_Redshifts + 1; - *dz = 0.0; - } - /* at the end, just use the last value */ - else if (z <= cooling->Redshifts[0]) { - *z_index = 0; - *dz = 0.0; - } else { - /* start at the previous index and search */ - for (iz = get_redshift_index_previous; iz >= 0; iz--) { - if (z > cooling->Redshifts[iz]) { - *dz = (z - cooling->Redshifts[iz]) / - (cooling->Redshifts[iz + 1] - cooling->Redshifts[iz]); - - get_redshift_index_previous = *z_index = iz; - - break; - } - } - } -} - -/* - * @brief Performs 1d interpolation - * - * @param table Pointer to 1d table of values - * @param i Index of cell we are interpolating - * @param dx Offset within cell - */ -__attribute__((always_inline)) INLINE float interpol_1d(float *table, int i, - float dx) { - float result; - - result = (1 - dx) * table[i] + dx * table[i + 1]; - - return result; -} - -/* - * @brief Performs 1d interpolation (double precision) - * - * @param table Pointer to 1d table of values - * @param i Index of cell we are interpolating - * @param dx Offset within cell - */ -__attribute__((always_inline)) INLINE double interpol_1d_dbl(double *table, - int i, float dx) { - double result; - - result = (1 - dx) * table[i] + dx * table[i + 1]; - - return result; -} - -/* - * @brief Performs 2d interpolation - * - * @param table Pointer to flattened 2d table of values - * @param i,j Indices of cell we are interpolating - * @param dx,dy Offset within cell - * @param nx,ny Table dimensions - */ -__attribute__((always_inline)) INLINE float interpol_2d(float *table, int i, - int j, float dx, - float dy, int nx, - int ny) { - float result; - int index[4]; - - index[0] = row_major_index_2d(i, j, nx, ny); - index[1] = row_major_index_2d(i, j + 1, nx, ny); - index[2] = row_major_index_2d(i + 1, j, nx, ny); - index[3] = row_major_index_2d(i + 1, j + 1, nx, ny); -#ifdef SWIFT_DEBUG_CHECKS - if (index[0] >= nx * ny || index[0] < 0) - fprintf(stderr, "index 0 out of bounds %d, i,j %d, %d, table size %d\n", - index[0], i, j, nx * ny); - if (index[1] >= nx * ny || index[1] < 0) - fprintf(stderr, "index 1 out of bounds %d, i,j %d, %d, table size %d\n", - index[1], i, j + 1, nx * ny); - if (index[2] >= nx * ny || index[2] < 0) - fprintf(stderr, "index 2 out of bounds %d, i,j %d, %d, table size %d\n", - index[2], i + 1, j, nx * ny); - if (index[3] >= nx * ny || index[3] < 0) - fprintf(stderr, "index 3 out of bounds %d, i,j %d, %d, table size %d\n", - index[3], i + 1, j + 1, nx * ny); -#endif - - result = (1 - dx) * (1 - dy) * table[index[0]] + - (1 - dx) * dy * table[index[1]] + dx * (1 - dy) * table[index[2]] + - dx * dy * table[index[3]]; - - return result; -} - -/* - * @brief Performs 2d interpolation (double precision) - * - * @param table Pointer to flattened 2d table of values - * @param i,j Indices of cell we are interpolating - * @param dx,dy Offset within cell - * @param nx,ny Table dimensions - */ -__attribute__((always_inline)) INLINE double interpol_2d_dbl( - double *table, int i, int j, double dx, double dy, int nx, int ny) { - double result; - int index[4]; - - index[0] = row_major_index_2d(i, j, nx, ny); - index[1] = row_major_index_2d(i, j + 1, nx, ny); - index[2] = row_major_index_2d(i + 1, j, nx, ny); - index[3] = row_major_index_2d(i + 1, j + 1, nx, ny); -#ifdef SWIFT_DEBUG_CHECKS - if (index[0] >= nx * ny || index[0] < 0) - fprintf(stderr, "index 0 out of bounds %d, i,j %d, %d, table size %d\n", - index[0], i, j, nx * ny); - if (index[1] >= nx * ny || index[1] < 0) - fprintf(stderr, "index 1 out of bounds %d, i,j %d, %d, table size %d\n", - index[1], i, j + 1, nx * ny); - if (index[2] >= nx * ny || index[2] < 0) - fprintf(stderr, "index 2 out of bounds %d, i,j %d, %d, table size %d\n", - index[2], i + 1, j, nx * ny); - if (index[3] >= nx * ny || index[3] < 0) - fprintf(stderr, "index 3 out of bounds %d, i,j %d, %d, table size %d\n", - index[3], i + 1, j + 1, nx * ny); -#endif - - result = (1 - dx) * (1 - dy) * table[index[0]] + - (1 - dx) * dy * table[index[1]] + dx * (1 - dy) * table[index[2]] + - dx * dy * table[index[3]]; - - return result; -} - -/* - * @brief Performs 3d interpolation - * - * @param table Pointer to flattened 3d table of values - * @param i,j,k Indices of cell we are interpolating - * @param dx,dy,dz Offset within cell - * @param nx,ny,nz Table dimensions - */ -__attribute__((always_inline)) INLINE float interpol_3d(float *table, int i, - int j, int k, float dx, - float dy, float dz, - int nx, int ny, - int nz, double *upper, - double *lower) { - float result; - int index[8]; - - index[0] = row_major_index_3d(i, j, k, nx, ny, nz); - index[1] = row_major_index_3d(i, j, k + 1, nx, ny, nz); - index[2] = row_major_index_3d(i, j + 1, k, nx, ny, nz); - index[3] = row_major_index_3d(i, j + 1, k + 1, nx, ny, nz); - index[4] = row_major_index_3d(i + 1, j, k, nx, ny, nz); - index[5] = row_major_index_3d(i + 1, j, k + 1, nx, ny, nz); - index[6] = row_major_index_3d(i + 1, j + 1, k, nx, ny, nz); - index[7] = row_major_index_3d(i + 1, j + 1, k + 1, nx, ny, nz); -#ifdef SWIFT_DEBUG_CHECKS - if (index[0] >= nx * ny * nz || index[0] < 0) - fprintf(stderr, - "index 0 out of bounds %d, i,j,k %d, %d, %d, table size %d\n", - index[0], i, j, k, nx * ny * nz); - if (index[1] >= nx * ny * nz || index[1] < 0) - fprintf(stderr, - "index 1 out of bounds %d, i,j,k %d, %d, %d, table size %d\n", - index[1], i, j, k + 1, nx * ny * nz); - if (index[2] >= nx * ny * nz || index[2] < 0) - fprintf(stderr, - "index 2 out of bounds %d, i,j,k %d, %d, %d, table size %d\n", - index[2], i, j + 1, k, nx * ny * nz); - if (index[3] >= nx * ny * nz || index[3] < 0) - fprintf(stderr, - "index 3 out of bounds %d, i,j,k %d, %d, %d, table size %d\n", - index[3], i, j + 1, k + 1, nx * ny * nz); - if (index[4] >= nx * ny * nz || index[4] < 0) - fprintf(stderr, - "index 4 out of bounds %d, i,j,k %d, %d, %d, table size %d\n", - index[4], i + 1, j, k, nx * ny * nz); - if (index[5] >= nx * ny * nz || index[5] < 0) - fprintf(stderr, - "index 5 out of bounds %d, i,j,k %d, %d, %d, table size %d\n", - index[5], i + 1, j, k + 1, nx * ny * nz); - if (index[6] >= nx * ny * nz || index[6] < 0) - fprintf(stderr, - "index 6 out of bounds %d, i,j,k %d, %d, %d, table size %d\n", - index[6], i + 1, j + 1, k, nx * ny * nz); - if (index[7] >= nx * ny * nz || index[7] < 0) - fprintf(stderr, - "index 7 out of bounds %d, i,j,k %d, %d, %d, table size %d\n", - index[7], i + 1, j + 1, k + 1, nx * ny * nz); -#endif - - float table0 = table[index[0]]; - float table1 = table[index[1]]; - float table2 = table[index[2]]; - float table3 = table[index[3]]; - float table4 = table[index[4]]; - float table5 = table[index[5]]; - float table6 = table[index[6]]; - float table7 = table[index[7]]; - - result = (1 - dx) * (1 - dy) * (1 - dz) * table0 + - (1 - dx) * (1 - dy) * dz * table1 + - (1 - dx) * dy * (1 - dz) * table2 + - (1 - dx) * dy * dz * table3 + - dx * (1 - dy) * (1 - dz) * table4 + - dx * (1 - dy) * dz * table5 + - dx * dy * (1 - dz) * table6 + - dx * dy * dz * table7; - dz = 1.0; - *upper = (1 - dx) * (1 - dy) * (1 - dz) * table0 + - (1 - dx) * (1 - dy) * dz * table1 + - (1 - dx) * dy * (1 - dz) * table2 + - (1 - dx) * dy * dz * table3 + - dx * (1 - dy) * (1 - dz) * table4 + - dx * (1 - dy) * dz * table5 + - dx * dy * (1 - dz) * table6 + - dx * dy * dz * table7; - dz = 0.0; - *lower = (1 - dx) * (1 - dy) * (1 - dz) * table0 + - (1 - dx) * (1 - dy) * dz * table1 + - (1 - dx) * dy * (1 - dz) * table2 + - (1 - dx) * dy * dz * table3 + - dx * (1 - dy) * (1 - dz) * table4 + - dx * (1 - dy) * dz * table5 + - dx * dy * (1 - dz) * table6 + - dx * dy * dz * table7; - - return result; -} - -/* - * @brief Performs 4d interpolation - * - * @param table Pointer to flattened 4d table of values - * @param i,j,k,l Indices of cell we are interpolating - * @param dx,dy,dz,dw Offset within cell - * @param nx,ny,nz,nw Table dimensions - */ -__attribute__((always_inline)) INLINE float interpol_4d( - float *table, int i, int j, int k, int l, float dx, float dy, float dz, - float dw, int nx, int ny, int nz, int nw, double *upper, double *lower) { - float result; - int index[16]; - - index[0] = row_major_index_4d(i, j, k, l, nx, ny, nz, nw); - index[1] = row_major_index_4d(i, j, k, l + 1, nx, ny, nz, nw); - index[2] = row_major_index_4d(i, j, k + 1, l, nx, ny, nz, nw); - index[3] = row_major_index_4d(i, j, k + 1, l + 1, nx, ny, nz, nw); - index[4] = row_major_index_4d(i, j + 1, k, l, nx, ny, nz, nw); - index[5] = row_major_index_4d(i, j + 1, k, l + 1, nx, ny, nz, nw); - index[6] = row_major_index_4d(i, j + 1, k + 1, l, nx, ny, nz, nw); - index[7] = row_major_index_4d(i, j + 1, k + 1, l + 1, nx, ny, nz, nw); - index[8] = row_major_index_4d(i + 1, j, k, l, nx, ny, nz, nw); - index[9] = row_major_index_4d(i + 1, j, k, l + 1, nx, ny, nz, nw); - index[10] = row_major_index_4d(i + 1, j, k + 1, l, nx, ny, nz, nw); - index[11] = row_major_index_4d(i + 1, j, k + 1, l + 1, nx, ny, nz, nw); - index[12] = row_major_index_4d(i + 1, j + 1, k, l, nx, ny, nz, nw); - index[13] = row_major_index_4d(i + 1, j + 1, k, l + 1, nx, ny, nz, nw); - index[14] = row_major_index_4d(i + 1, j + 1, k + 1, l, nx, ny, nz, nw); - index[15] = row_major_index_4d(i + 1, j + 1, k + 1, l + 1, nx, ny, nz, nw); -#ifdef SWIFT_DEBUG_CHECKS - if (index[0] >= nx * ny * nz * nw || index[0] < 0) - fprintf( - stderr, - "index 0 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[0], i, j, k, l, nx * ny * nz * nw); - if (index[1] >= nx * ny * nz * nw || index[1] < 0) - fprintf( - stderr, - "index 1 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[1], i, j, k, l + 1, nx * ny * nz * nw); - if (index[2] >= nx * ny * nz * nw || index[2] < 0) - fprintf( - stderr, - "index 2 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[2], i, j, k + 1, l, nx * ny * nz * nw); - if (index[3] >= nx * ny * nz * nw || index[3] < 0) - fprintf( - stderr, - "index 3 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[3], i, j, k + 1, l + 1, nx * ny * nz * nw); - if (index[4] >= nx * ny * nz * nw || index[4] < 0) - fprintf( - stderr, - "index 4 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[4], i, j + 1, k, l, nx * ny * nz * nw); - if (index[5] >= nx * ny * nz * nw || index[5] < 0) - fprintf( - stderr, - "index 5 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[5], i, j + 1, k, l + 1, nx * ny * nz * nw); - if (index[6] >= nx * ny * nz * nw || index[6] < 0) - fprintf( - stderr, - "index 6 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[6], i, j + 1, k + 1, l, nx * ny * nz * nw); - if (index[7] >= nx * ny * nz * nw || index[7] < 0) - fprintf( - stderr, - "index 7 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[7], i, j + 1, k + 1, l + 1, nx * ny * nz * nw); - if (index[8] >= nx * ny * nz * nw || index[8] < 0) - fprintf( - stderr, - "index 8 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[8], i + 1, j, k, l, nx * ny * nz * nw); - if (index[9] >= nx * ny * nz * nw || index[9] < 0) - fprintf( - stderr, - "index 9 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[9], i + 1, j, k, l + 1, nx * ny * nz * nw); - if (index[10] >= nx * ny * nz * nw || index[10] < 0) - fprintf( - stderr, - "index 10 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[10], i + 1, j, k + 1, l, nx * ny * nz * nw); - if (index[11] >= nx * ny * nz * nw || index[11] < 0) - fprintf( - stderr, - "index 11 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[11], i + 1, j, k + 1, l + 1, nx * ny * nz * nw); - if (index[12] >= nx * ny * nz * nw || index[12] < 0) - fprintf( - stderr, - "index 12 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[12], i + 1, j + 1, k, l, nx * ny * nz * nw); - if (index[13] >= nx * ny * nz * nw || index[13] < 0) - fprintf( - stderr, - "index 13 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[13], i + 1, j + 1, k, l + 1, nx * ny * nz * nw); - if (index[14] >= nx * ny * nz * nw || index[14] < 0) - fprintf( - stderr, - "index 14 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[14], i + 1, j + 1, k + 1, l, nx * ny * nz * nw); - if (index[15] >= nx * ny * nz * nw || index[15] < 0) - fprintf( - stderr, - "index 15 out of bounds %d, i,j,k,l, %d, %d, %d, %d, table size %d\n", - index[15], i + 1, j + 1, k + 1, l + 1, nx * ny * nz * nw); -#endif - - float table0 = table[index[0]]; - float table1 = table[index[1]]; - float table2 = table[index[2]]; - float table3 = table[index[3]]; - float table4 = table[index[4]]; - float table5 = table[index[5]]; - float table6 = table[index[6]]; - float table7 = table[index[7]]; - float table8 = table[index[8]]; - float table9 = table[index[9]]; - float table10 = table[index[10]]; - float table11 = table[index[11]]; - float table12 = table[index[12]]; - float table13 = table[index[13]]; - float table14 = table[index[14]]; - float table15 = table[index[15]]; - - result = (1 - dx) * (1 - dy) * (1 - dz) * (1 - dw) * table0 + - (1 - dx) * (1 - dy) * (1 - dz) * dw * table1 + - (1 - dx) * (1 - dy) * dz * (1 - dw) * table2 + - (1 - dx) * (1 - dy) * dz * dw * table3 + - (1 - dx) * dy * (1 - dz) * (1 - dw) * table4 + - (1 - dx) * dy * (1 - dz) * dw * table5 + - (1 - dx) * dy * dz * (1 - dw) * table6 + - (1 - dx) * dy * dz * dw * table7 + - dx * (1 - dy) * (1 - dz) * (1 - dw) * table8 + - dx * (1 - dy) * (1 - dz) * dw * table9 + - dx * (1 - dy) * dz * (1 - dw) * table10 + - dx * (1 - dy) * dz * dw * table11 + - dx * dy * (1 - dz) * (1 - dw) * table12 + - dx * dy * (1 - dz) * dw * table13 + - dx * dy * dz * (1 - dw) * table14 + - dx * dy * dz * dw * table15; - if (nw == 9) { - dz = 1.0; - } else { - dw = 1.0; - } - *upper = (1 - dx) * (1 - dy) * (1 - dz) * (1 - dw) * table0 + - (1 - dx) * (1 - dy) * (1 - dz) * dw * table1 + - (1 - dx) * (1 - dy) * dz * (1 - dw) * table2 + - (1 - dx) * (1 - dy) * dz * dw * table3 + - (1 - dx) * dy * (1 - dz) * (1 - dw) * table4 + - (1 - dx) * dy * (1 - dz) * dw * table5 + - (1 - dx) * dy * dz * (1 - dw) * table6 + - (1 - dx) * dy * dz * dw * table7 + - dx * (1 - dy) * (1 - dz) * (1 - dw) * table8 + - dx * (1 - dy) * (1 - dz) * dw * table9 + - dx * (1 - dy) * dz * (1 - dw) * table10 + - dx * (1 - dy) * dz * dw * table11 + - dx * dy * (1 - dz) * (1 - dw) * table12 + - dx * dy * (1 - dz) * dw * table13 + - dx * dy * dz * (1 - dw) * table14 + - dx * dy * dz * dw * table15; - if (nw == 9) { - dz = 0.0; - } else { - dw = 0.0; - } - *lower = (1 - dx) * (1 - dy) * (1 - dz) * (1 - dw) * table0 + - (1 - dx) * (1 - dy) * (1 - dz) * dw * table1 + - (1 - dx) * (1 - dy) * dz * (1 - dw) * table2 + - (1 - dx) * (1 - dy) * dz * dw * table3 + - (1 - dx) * dy * (1 - dz) * (1 - dw) * table4 + - (1 - dx) * dy * (1 - dz) * dw * table5 + - (1 - dx) * dy * dz * (1 - dw) * table6 + - (1 - dx) * dy * dz * dw * table7 + - dx * (1 - dy) * (1 - dz) * (1 - dw) * table8 + - dx * (1 - dy) * (1 - dz) * dw * table9 + - dx * (1 - dy) * dz * (1 - dw) * table10 + - dx * (1 - dy) * dz * dw * table11 + - dx * dy * (1 - dz) * (1 - dw) * table12 + - dx * dy * (1 - dz) * dw * table13 + - dx * dy * dz * (1 - dw) * table14 + - dx * dy * dz * dw * table15; - - return result; -} - -/* - * @brief Interpolates 2d EAGLE table in redshift and hydrogen - * number density. Produces 1d table depending only - * on log(temperature) - * - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param table Pointer to table we are interpolating - * @param z_i Redshift index - * @param d_z Redshift offset - * @param n_h_i Hydrogen number density index - * @param d_n_h Hydrogen number density offset - * @param result_table Pointer to 1d interpolated table - */ -__attribute__((always_inline)) INLINE static void construct_1d_table_from_2d( - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, float *table, int x_i, float d_x, - int n_x, int array_size, double *result_table, float *ub, float *lb) { - - const double log_10 = 2.302585092994; - int index_low, index_high; - float d_high, d_low; - - get_index_1d(cooling->Temp, cooling->N_Temp,(*ub)/log_10,&index_high,&d_high); - get_index_1d(cooling->Temp, cooling->N_Temp,(*lb)/log_10,&index_low,&d_low); - if (index_high < array_size-1) { - index_high += 2; - } else { - index_high = array_size; - } - if (index_low > 0) index_low--; - - int index[2]; - for (int i = index_low; i < index_high; i++) { - index[0] = row_major_index_2d(x_i, i, n_x, - array_size); - index[1] = row_major_index_2d(x_i + 1, i, n_x, - array_size); - - result_table[i] = (1 - d_x) * table[index[0]] + - d_x * table[index[1]]; - } -} - -/* - * @brief Interpolates 3d EAGLE table in redshift and hydrogen - * number density. Produces 1d table depending only - * on log(temperature) - * - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param table Pointer to table we are interpolating - * @param z_i Redshift index - * @param d_z Redshift offset - * @param n_h_i Hydrogen number density index - * @param d_n_h Hydrogen number density offset - * @param result_table Pointer to 1d interpolated table - */ -__attribute__((always_inline)) INLINE static void construct_1d_table_from_3d( - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, float *table, int x_i, float d_x, - int n_x, int y_i, float d_y, int n_y, int array_size, double *result_table, float *ub, float *lb) { - - const double log_10 = 2.302585092994; - int index_low, index_high; - float d_high, d_low; - - get_index_1d(cooling->Temp, cooling->N_Temp,(*ub)/log_10,&index_high,&d_high); - get_index_1d(cooling->Temp, cooling->N_Temp,(*lb)/log_10,&index_low,&d_low); - if (index_high < array_size-1) { - index_high += 2; - } else { - index_high = array_size; - } - if (index_low > 0) index_low--; - - int index[4]; - for (int i = index_low; i < index_high; i++) { - index[0] = row_major_index_3d(x_i, y_i, i, n_x, - n_y, array_size); - index[1] = row_major_index_3d(x_i, y_i + 1, i, n_x, - n_y, array_size); - index[2] = row_major_index_3d(x_i + 1, y_i, i, n_x, - n_y, array_size); - index[3] = row_major_index_3d(x_i + 1, y_i + 1, i, n_x, - n_y, array_size); - - result_table[i] = (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]] + - d_x * d_y * table[index[3]]; - } -} - -/* - * @brief Interpolates 4d EAGLE hydrogen and helium cooling - * table in redshift, helium fraction and hydrogen number - * density. Produces 1d table depending only on log(temperature) - * and location of maximum cooling gradient with respect to - * internal energy. NOTE: calculation of location of maximum - * cooling gradient is still work in progress. - * - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param table Pointer to table we are interpolating - * @param z_i Redshift index - * @param d_z Redshift offset - * @param He_i Helium fraction index - * @param d_He Helium fraction offset - * @param n_h_i Hydrogen number density index - * @param d_n_h Hydrogen number density offset - * @param result_table Pointer to 1d interpolated table - * @param x_max_grad Pointer to location of maximum gradient - * @param u_ini Internal energy at start of hydro timestep - * @param dt Hydro timestep - */ -__attribute__((always_inline)) INLINE static void -construct_1d_table_from_4d_H_He( - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, float *table, int x_i, float d_x, int n_x, - int y_i, float d_y, int n_y, int w_i, float d_w, int n_w, int array_size, double *result_table, - double *x_max_grad, double u_ini, float dt, float *ub, float *lb) { - - const double log_10 = 2.302585092994; - int index_low, index_high; - float d_high, d_low; - - get_index_1d(cooling->Temp, cooling->N_Temp,(*ub)/log_10,&index_high,&d_high); - get_index_1d(cooling->Temp, cooling->N_Temp,(*lb)/log_10,&index_low,&d_low); - if (index_high < array_size-1) { - index_high += 2; - } else { - index_high = array_size; - } - if (index_low > 0) index_low--; - - int index[8]; - for (int i = index_low; i < index_high; i++) { - index[0] = - row_major_index_4d(x_i, y_i, w_i, i, n_x, - n_y, n_w, array_size); - index[1] = - row_major_index_4d(x_i, y_i, w_i + 1, i, n_x, - n_y, n_w, array_size); - index[2] = - row_major_index_4d(x_i, y_i + 1, w_i, i, n_x, - n_y, n_w, array_size); - index[3] = - row_major_index_4d(x_i, y_i + 1, w_i + 1, i, n_x, - n_y, n_w, array_size); - index[4] = - row_major_index_4d(x_i + 1, y_i, w_i, i, n_x, - n_y, n_w, array_size); - index[5] = - row_major_index_4d(x_i + 1, y_i, w_i + 1, i, n_x, - n_y, n_w, array_size); - index[6] = - row_major_index_4d(x_i + 1, y_i + 1, w_i, i, n_x, - n_y, n_w, array_size); - index[7] = row_major_index_4d(x_i + 1, y_i + 1, w_i + 1, i, - n_x, n_y, - n_w, array_size); - - result_table[i] = (1 - d_x) * (1 - d_y) * (1 - d_w) * table[index[0]] + - (1 - d_x) * (1 - d_y) * d_w * table[index[1]] + - (1 - d_x) * d_y * (1 - d_w) * table[index[2]] + - (1 - d_x) * d_y * d_w * table[index[3]] + - d_x * (1 - d_y) * (1 - d_w) * table[index[4]] + - d_x * (1 - d_y) * d_w * table[index[5]] + - d_x * d_y * (1 - d_w) * table[index[6]] + - d_x * d_y * d_w * table[index[7]]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 1 i dz dnh dHe table values %d %.5e %.5e %.5e %.5e " - "%.5e %.5e %.5e %.5e %.5e %.5e %.5e \n", - i, d_x, d_y, d_w, table[index[0]], table[index[1]], - table[index[2]], table[index[3]], table[index[4]], table[index[5]], - table[index[6]], table[index[7]]); -#endif - } -} - -/* - * @brief Interpolates 4d EAGLE table in redshift, - * helium fraction and hydrogen number density. - * Produces 1d table depending only on log(temperature) - * - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param table Pointer to table we are interpolating - * @param z_i Redshift index - * @param d_z Redshift offset - * @param He_i Helium fraction index - * @param d_He Helium fraction offset - * @param n_h_i Hydrogen number density index - * @param d_n_h Hydrogen number density offset - * @param result_table Pointer to 1d interpolated table - */ -__attribute__((always_inline)) INLINE static void construct_1d_table_from_4d( - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, float *table, int x_i, float d_x, int n_x, - int y_i, float d_y, int n_y, int w_i, float d_w, int n_w, int array_size, double *result_table, float *ub, float *lb) { - - const double log_10 = 2.302585092994; - int index_low, index_high; - float d_high, d_low; - - get_index_1d(cooling->Temp, cooling->N_Temp,(*ub)/log_10,&index_high,&d_high); - get_index_1d(cooling->Temp, cooling->N_Temp,(*lb)/log_10,&index_low,&d_low); - if (index_high < array_size-1) { - index_high += 2; - } else { - index_high = array_size; - } - if (index_low > 0) index_low--; - - int index[8]; - for (int i = index_low; i < index_high; i++) { - index[0] = - row_major_index_4d(x_i, y_i, w_i, i, n_x, - n_y, n_w, array_size); - index[1] = - row_major_index_4d(x_i, y_i, w_i + 1, i, n_x, - n_y, n_w, array_size); - index[2] = - row_major_index_4d(x_i, y_i + 1, w_i, i, n_x, - n_y, n_w, array_size); - index[3] = - row_major_index_4d(x_i, y_i + 1, w_i + 1, i, n_x, - n_y, n_w, array_size); - index[4] = - row_major_index_4d(x_i + 1, y_i, w_i, i, n_x, - n_y, n_w, array_size); - index[5] = - row_major_index_4d(x_i + 1, y_i, w_i + 1, i, n_x, - n_y, n_w, array_size); - index[6] = - row_major_index_4d(x_i + 1, y_i + 1, w_i, i, n_x, - n_y, n_w, array_size); - index[7] = row_major_index_4d(x_i + 1, y_i + 1, w_i + 1, i, - n_x, n_y, - n_w, array_size); - - result_table[i] = (1 - d_x) * (1 - d_y) * (1 - d_w) * table[index[0]] + - (1 - d_x) * (1 - d_y) * d_w * table[index[1]] + - (1 - d_x) * d_y * (1 - d_w) * table[index[2]] + - (1 - d_x) * d_y * d_w * table[index[3]] + - d_x * (1 - d_y) * (1 - d_w) * table[index[4]] + - d_x * (1 - d_y) * d_w * table[index[5]] + - d_x * d_y * (1 - d_w) * table[index[6]] + - d_x * d_y * d_w * table[index[7]]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 2 i dz dnh dHe table values %d %.5e %.5e %.5e %.5e " - "%.5e %.5e %.5e %.5e %.5e %.5e %.5e \n", - i, d_x, d_y, d_w, table[index[0]], table[index[1]], - table[index[2]], table[index[3]], table[index[4]], table[index[5]], - table[index[6]], table[index[7]]); -#endif - } -} - -/* - * @brief calculates heating due to helium reionization - * - * @param z redshift - * @param dz redshift offset - */ -__attribute__((always_inline)) INLINE double eagle_helium_reionization_extraheat(double z, double dz, const struct cooling_function_data *restrict cooling) { - - double extra_heating = 0.0; - -/* dz is the change in redshift (start to finish) and hence *should* be < 0 */ -#ifdef SWIFT_DEBUG_CHECKS - if (dz > 0) { - error(" formulation of helium reionization expects dz<0, whereas you have " - "dz=%e\n", dz); - } -#endif - - /* Helium reionization */ - if (cooling->he_reion == 1) { - double he_reion_erg_pG = cooling->he_reion_ev_pH * eagle_ev_to_erg / eagle_proton_mass_cgs; - extra_heating += he_reion_erg_pG * - (erf((z - dz - cooling->he_reion_z_center) / - (pow(2., 0.5) * cooling->he_reion_z_sigma)) - - erf((z - cooling->he_reion_z_center) / - (pow(2., 0.5) * cooling->he_reion_z_sigma))) / - 2.0; - } else - extra_heating = 0.0; - - return extra_heating; -} - -/* - * @brief Interpolates 4d EAGLE metal cooling tables in redshift, - * helium fraction and hydrogen number density. - * Produces 1d table depending only on log(temperature) - * NOTE: Will need to be modified to incorporate particle to solar - * electron abundance ratio. - * - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param table Pointer to table we are interpolating - * @param z_i Redshift index - * @param d_z Redshift offset - * @param He_i Helium fraction index - * @param d_He Helium fraction offset - * @param n_h_i Hydrogen number density index - * @param d_n_h Hydrogen number density offset - * @param result_table Pointer to 1d interpolated table - */ -__attribute__((always_inline)) INLINE static void -construct_1d_print_table_from_4d_elements( - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, float *table, int x_i, float d_x, - int n_x, int y_i, float d_y, int n_y, int array_size, double *result_table, float *abundance_ratio, float *ub, float *lb) { - - const double log_10 = 2.302585092994; - int index_low, index_high; - float d_high, d_low; - - get_index_1d(cooling->Temp, cooling->N_Temp,(*ub)/log_10,&index_high,&d_high); - get_index_1d(cooling->Temp, cooling->N_Temp,(*lb)/log_10,&index_low,&d_low); - if (index_high < array_size-1) { - index_high += 2; - } else { - index_high = array_size; - } - if (index_low > 0) index_low--; - - int index[4]; - - for (int j = 0; j < cooling->N_Elements; j++) { - for (int i = index_low; i < index_high; i++) { - if (j == 0) result_table[i] = 0.0; - index[0] = row_major_index_4d(x_i, y_i, i, j, n_x, - n_y, array_size, cooling->N_Elements); - index[1] = row_major_index_4d(x_i, y_i+1, i, j, n_x, - n_y, array_size, cooling->N_Elements); - index[2] = row_major_index_4d(x_i+1, y_i, i, j, n_x, - n_y, array_size, cooling->N_Elements); - index[3] = row_major_index_4d(x_i+1, y_i+1, i, j, n_x, - n_y, array_size, cooling->N_Elements); - - result_table[i+array_size*j] = ((1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]] + - d_x * d_y * table[index[3]]) * abundance_ratio[j+2]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 3 i partial sums %d %.5e %.5e %.5e %.5e %.5e \n", - i, result_table[i], (1 - d_x) * (1 - d_y) * table[index[0]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]] + - d_x * d_y * table[index[3]]); -#endif - } - } -} - -/* - * @brief Interpolates 4d EAGLE metal cooling tables in redshift, - * helium fraction and hydrogen number density. - * Produces 1d table depending only on log(temperature) - * NOTE: Will need to be modified to incorporate particle to solar - * electron abundance ratio. - * - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param table Pointer to table we are interpolating - * @param z_i Redshift index - * @param d_z Redshift offset - * @param He_i Helium fraction index - * @param d_He Helium fraction offset - * @param n_h_i Hydrogen number density index - * @param d_n_h Hydrogen number density offset - * @param result_table Pointer to 1d interpolated table - */ -__attribute__((always_inline)) INLINE static void -construct_1d_table_from_4d_elements( - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, float *table, int x_i, float d_x, - int n_x, int y_i, float d_y, int n_y, int array_size, double *result_table, float *abundance_ratio, float *ub, float *lb) { - int index[4]; - - const double log_10 = 2.302585092994; - int index_low, index_high; - float d_high, d_low; - - get_index_1d(cooling->Temp, cooling->N_Temp,(*ub)/log_10,&index_high,&d_high); - get_index_1d(cooling->Temp, cooling->N_Temp,(*lb)/log_10,&index_low,&d_low); - if (index_high < array_size-1) { - index_high += 2; - } else { - index_high = array_size; - } - if (index_low > 0) index_low--; - - for (int j = 0; j < cooling->N_Elements; j++) { - for (int i = index_low; i < index_high; i++) { - if (j == 0) result_table[i] = 0.0; - index[0] = row_major_index_4d(x_i, y_i, i, j, n_x, - n_y, array_size, cooling->N_Elements); - index[1] = row_major_index_4d(x_i, y_i+1, i, j, n_x, - n_y, array_size, cooling->N_Elements); - index[2] = row_major_index_4d(x_i+1, y_i, i, j, n_x, - n_y, array_size, cooling->N_Elements); - index[3] = row_major_index_4d(x_i+1, y_i+1, i, j, n_x, - n_y, array_size, cooling->N_Elements); - - result_table[i] += ((1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]] + - d_x * d_y * table[index[3]]) * abundance_ratio[j+2]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 3 i partial sums %d %.5e %.5e %.5e %.5e %.5e \n", - i, result_table[i], (1 - d_x) * (1 - d_y) * table[index[0]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]] + - d_x * d_y * table[index[3]]); -#endif - } - } -} - -/* - * @brief Interpolates 3d EAGLE cooling tables in redshift, - * helium fraction and hydrogen number density. - * Produces 1d table depending only on log(temperature) - * NOTE: Will need to be modified to incorporate particle to solar - * electron abundance ratio. - * - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param table Pointer to table we are interpolating - * @param z_i Redshift index - * @param d_z Redshift offset - * @param He_i Helium fraction index - * @param d_He Helium fraction offset - * @param n_h_i Hydrogen number density index - * @param d_n_h Hydrogen number density offset - * @param result_table Pointer to 1d interpolated table - */ -__attribute__((always_inline)) INLINE static void -construct_1d_table_from_3d_elements( - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, float *table, int x_i, float d_x, - int n_x, int array_size, double *result_table, float *abundance_ratio, float *ub, float *lb) { - int index[2]; - - const double log_10 = 2.302585092994; - int index_low, index_high; - float d_high, d_low; - - get_index_1d(cooling->Temp, cooling->N_Temp,(*ub)/log_10,&index_high,&d_high); - get_index_1d(cooling->Temp, cooling->N_Temp,(*lb)/log_10,&index_low,&d_low); - if (index_high < array_size-1) { - index_high += 2; - } else { - index_high = array_size; - } - if (index_low > 0) index_low--; - - for (int j = 0; j < cooling->N_Elements; j++) { - for (int i = index_low; i < index_high; i++) { - if (j == 0) result_table[i] = 0.0; - index[0] = row_major_index_3d(j, x_i, i, - cooling->N_Elements, n_x, - array_size); - index[1] = row_major_index_3d(j, x_i + 1, i, - cooling->N_Elements, n_x, - array_size); - - result_table[i] += ((1 - d_x) * table[index[0]] + - d_x * table[index[1]])*abundance_ratio[j+2]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 3 i partial sums %d %.5e %.5e %.5e \n", - i, result_table[i], (1 - d_x) * table[index[0]], - (1 - d_x) * table[index[0]] + - d_x * table[index[1]]); -#endif - } - } -} - -/* - * @brief Interpolates temperature from internal energy based on table - * - * @param temp Temperature - * @param temperature_table Table of EAGLE temperature values - * @param cooling Cooling data structure - */ -__attribute__((always_inline)) INLINE static double -eagle_convert_temp_to_u_1d_table(double temp, float *temperature_table, - const struct cooling_function_data *restrict - cooling) { - - int temp_i; - float d_temp, u; - - get_index_1d(temperature_table, cooling->N_Temp, log10(temp), &temp_i, - &d_temp); - - u = pow(10.0, interpol_1d(cooling->Therm, temp_i, d_temp)); - - return u; -} - -/* - * @brief Interpolates temperature from internal energy based on table and - * calculates the size of the internal energy cell for the specified - * temperature. - * - * @param u Internal energy - * @param delta_u Pointer to size of internal energy cell - * @param temperature_table Table of EAGLE temperature values - * @param cooling Cooling data structure - */ -__attribute__((always_inline)) INLINE static double -eagle_convert_u_to_temp( - double log_10_u, float *delta_u, - int z_i, int n_h_i, int He_i, - float d_z, float d_n_h, float d_He, - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const) { - - int u_i; - float d_u, logT; - double upper, lower; - - get_index_1d(cooling->Therm, cooling->N_Temp, log_10_u, &u_i, &d_u); - - logT = interpol_4d(cooling->table.element_cooling.temperature, z_i,n_h_i,He_i,u_i,d_z,d_n_h,d_He,d_u, - cooling->N_Redshifts,cooling->N_nH,cooling->N_He,cooling->N_Temp,&upper,&lower); - - *delta_u = - pow(10.0, cooling->Therm[u_i + 1]) - pow(10.0, cooling->Therm[u_i]); - - return logT; -} - - -/* - * @brief Interpolates temperature from internal energy based on table and - * calculates the size of the internal energy cell for the specified - * temperature. - * - * @param u Internal energy - * @param delta_u Pointer to size of internal energy cell - * @param temperature_table Table of EAGLE temperature values - * @param cooling Cooling data structure - */ -__attribute__((always_inline)) INLINE static double -eagle_convert_u_to_temp_1d_table( - double log_10_u, float *delta_u, double *temperature_table, - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const) { - - int u_i; - float d_u, logT;//, T; - - get_index_1d(cooling->Therm, cooling->N_Temp, log_10_u, &u_i, &d_u); - - logT = interpol_1d_dbl(temperature_table, u_i, d_u); - - *delta_u = - pow(10.0, cooling->Therm[u_i + 1]) - pow(10.0, cooling->Therm[u_i]); - - return logT; -} - -/* - * @brief Calculates cooling rate from multi-d tables - * - * @param u Internal energy - * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param element_lambda Pointer for printing contribution to cooling rate - * from each of the metals. - */ -__attribute__((always_inline)) INLINE static double eagle_metal_cooling_rate( - double log_10_u, double *dlambda_du, int z_index, float dz, int n_h_i, float d_n_h, - int He_i, float d_He, const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, - double *element_lambda, - float *solar_ratio) { - double T_gam, solar_electron_abundance, solar_electron_abundance1, solar_electron_abundance2, elem_cool1, elem_cool2; - double n_h = chemistry_get_number_density(p, cosmo, chemistry_element_H, - internal_const) * - cooling->number_density_scale; // chemistry_data - double z = cosmo->z; - double cooling_rate = 0.0, temp_lambda, temp_lambda1, temp_lambda2; - float du; - double h_plus_he_electron_abundance; - double h_plus_he_electron_abundance1; - double h_plus_he_electron_abundance2; - - int i; - double temp; - int temp_i; - float d_temp; - - *dlambda_du = 0.0; - - temp = eagle_convert_u_to_temp(log_10_u, &du, z_index, n_h_i, He_i, - dz, d_n_h, d_He, p, - cooling, cosmo, internal_const); - - get_index_1d(cooling->Temp, cooling->N_Temp, temp, &temp_i, &d_temp); - - /* ------------------ */ - /* Metal-free cooling */ - /* ------------------ */ - - /* redshift tables */ - temp_lambda = interpol_4d(cooling->table.element_cooling.H_plus_He_heating, - z_index, n_h_i, He_i, temp_i, dz, d_n_h, d_He, - d_temp, cooling->N_Redshifts, cooling->N_nH, - cooling->N_He, cooling->N_Temp,&temp_lambda2,&temp_lambda1); - h_plus_he_electron_abundance = interpol_4d( - cooling->table.element_cooling.H_plus_He_electron_abundance, z_index, - n_h_i, He_i, temp_i, dz, d_n_h, d_He, d_temp, cooling->N_Redshifts, - cooling->N_nH, cooling->N_He, cooling->N_Temp,&h_plus_he_electron_abundance2,&h_plus_he_electron_abundance1); - cooling_rate += temp_lambda; - *dlambda_du += (temp_lambda2 - temp_lambda1)/du; - if (element_lambda != NULL) element_lambda[0] = temp_lambda; - - /* ------------------ */ - /* Compton cooling */ - /* ------------------ */ - - if (z > cooling->Redshifts[cooling->N_Redshifts - 1] || - z > cooling->reionisation_redshift) { - /* inverse Compton cooling is not in collisional table - before reionisation so add now */ +double eagle_metal_cooling_rate( + double, double *, int, float, int, float, + int, float, const struct part *restrict, + const struct cooling_function_data *restrict, + const struct cosmology *restrict, + const struct phys_const *, + double *, + float *); - T_gam = eagle_cmb_temperature * (1 + z); - - temp_lambda = -eagle_compton_rate * - (temp - eagle_cmb_temperature * (1 + z)) * pow((1 + z), 4) * - h_plus_he_electron_abundance / n_h; - cooling_rate += temp_lambda; - if (element_lambda != NULL) element_lambda[1] = temp_lambda; - } - - /* ------------- */ - /* Metal cooling */ - /* ------------- */ - - /* for each element, find the abundance and multiply it - by the interpolated heating-cooling */ - - /* redshift tables */ - solar_electron_abundance = - interpol_3d(cooling->table.element_cooling.electron_abundance, z_index, - n_h_i, temp_i, dz, d_n_h, d_temp, cooling->N_Redshifts, - cooling->N_nH, cooling->N_Temp,&solar_electron_abundance2,&solar_electron_abundance1); - - for (i = 0; i < cooling->N_Elements; i++) { - temp_lambda = - interpol_4d(cooling->table.element_cooling.metal_heating, z_index, - n_h_i, temp_i, i, dz, d_n_h, d_temp, 0.0, cooling->N_Redshifts, - cooling->N_nH, cooling->N_Temp, cooling->N_Elements,&elem_cool2,&elem_cool1) * - (h_plus_he_electron_abundance / solar_electron_abundance)* - solar_ratio[i+2]; - cooling_rate += temp_lambda; - *dlambda_du += - (elem_cool2 * h_plus_he_electron_abundance2 / - solar_electron_abundance2 - - elem_cool1 * h_plus_he_electron_abundance1 / - solar_electron_abundance1) / du * solar_ratio[i+2]; - if (element_lambda != NULL) element_lambda[i + 2] = temp_lambda; - } - - return cooling_rate; -} - -/* - * @brief Calculates cooling rate from 1d tables - * - * @param u Internal energy - * @param dlambda_du Pointer to gradient of cooling rate - * @param H_plus_He_heat_table 1D table of heating rates due to H, He - * @param H_plus_He_electron_abundance_table 1D table of electron abundances due - * to H,He - * @param element_cooling_table 1D table of heating rates due to metals - * @param element_electron_abundance_table 1D table of electron abundances due - * to metals - * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - * @param element_lambda Pointer for printing contribution to cooling rate - * from each of the metals. - */ -__attribute__((always_inline)) INLINE static double +double eagle_metal_cooling_rate_1d_table( - double log_10_u, double *dlambda_du, double *H_plus_He_heat_table, - double *H_plus_He_electron_abundance_table, double *element_cooling_table, - double *element_electron_abundance_table, double *temp_table, int z_index, - float dz, int n_h_i, float d_n_h, int He_i, float d_He, - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, - double *element_lambda, - float *solar_ratio) { - double T_gam, solar_electron_abundance; - double n_h = chemistry_get_number_density(p, cosmo, chemistry_element_H, - internal_const) * - cooling->number_density_scale; // chemistry_data - double z = cosmo->z; - double cooling_rate = 0.0, temp_lambda; - float du; - float h_plus_he_electron_abundance; - - int i; - double temp; - int temp_i; - float d_temp; - - *dlambda_du = 0.0; - - temp = eagle_convert_u_to_temp_1d_table(log_10_u, &du, temp_table, p, cooling, cosmo, - internal_const); - - get_index_1d(cooling->Temp, cooling->N_Temp, temp, &temp_i, &d_temp); - //printf("Eagle cooling.h 1d log_10_u, temp, temp_i, d_temp %.5e %.5e %d %.5e\n", log_10_u, temp, temp_i, d_temp); - - /* ------------------ */ - /* Metal-free cooling */ - /* ------------------ */ - - /* redshift tables */ - temp_lambda = interpol_1d_dbl(H_plus_He_heat_table, temp_i, d_temp); - h_plus_he_electron_abundance = - interpol_1d_dbl(H_plus_He_electron_abundance_table, temp_i, d_temp); - cooling_rate += temp_lambda; - *dlambda_du += (((double)H_plus_He_heat_table[temp_i + 1]) - - ((double)H_plus_He_heat_table[temp_i])) / - ((double)du); - if (element_lambda != NULL) element_lambda[0] = temp_lambda; - - /* ------------------ */ - /* Compton cooling */ - /* ------------------ */ - - if (z > cooling->Redshifts[cooling->N_Redshifts - 1] || - z > cooling->reionisation_redshift) { - /* inverse Compton cooling is not in collisional table - before reionisation so add now */ - - T_gam = eagle_cmb_temperature * (1 + z); - - temp_lambda = -eagle_compton_rate * - (temp - eagle_cmb_temperature * (1 + z)) * pow((1 + z), 4) * - h_plus_he_electron_abundance / n_h; - cooling_rate += temp_lambda; - if (element_lambda != NULL) element_lambda[1] = temp_lambda; - } - - /* ------------- */ - /* Metal cooling */ - /* ------------- */ - - /* for each element, find the abundance and multiply it - by the interpolated heating-cooling */ - - /* redshift tables */ - solar_electron_abundance = - interpol_1d_dbl(element_electron_abundance_table, temp_i, d_temp); - - for (i = 0; i < cooling->N_Elements; i++) { - temp_lambda = interpol_1d_dbl(element_cooling_table + i*cooling->N_Temp, temp_i, d_temp) * - (h_plus_he_electron_abundance / solar_electron_abundance); // hydrogen and helium aren't included here. - cooling_rate += temp_lambda; - *dlambda_du += - (((double)element_cooling_table[i*cooling->N_Temp + temp_i + 1]) * - ((double)H_plus_He_electron_abundance_table[temp_i + 1]) / - ((double)element_electron_abundance_table[temp_i + 1]) - - ((double)element_cooling_table[i*cooling->N_Temp + temp_i]) * - ((double)H_plus_He_electron_abundance_table[temp_i]) / - ((double)element_electron_abundance_table[temp_i])) / - ((double)du); - if (element_lambda != NULL) element_lambda[i + 2] = temp_lambda; - } - - return cooling_rate; -} - -/* - * @brief Wrapper function previously used to calculate cooling rate and - * dLambda_du - * Can be used to check whether calculation of dLambda_du is done correctly. - * Should be removed when finished - * - * @param u Internal energy - * @param dlambda_du Pointer to gradient of cooling rate - * @param H_plus_He_heat_table 1D table of heating rates due to H, He - * @param H_plus_He_electron_abundance_table 1D table of electron abundances due - * to H,He - * @param element_cooling_table 1D table of heating rates due to metals - * @param element_electron_abundance_table 1D table of electron abundances due - * to metals - * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - */ -__attribute__((always_inline)) INLINE static double eagle_cooling_rate( - double logu, double *dLambdaNet_du, int z_index, - float dz, int n_h_i, float d_n_h, int He_i, float d_He, - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, - float *abundance_ratio) { - double *element_lambda = NULL, lambda_net = 0.0; - const double log_10 = 2.30258509299404; - - lambda_net = eagle_metal_cooling_rate( - logu/log_10, dLambdaNet_du, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, internal_const, element_lambda, abundance_ratio); - - return lambda_net; -} - -/* - * @brief Wrapper function previously used to calculate cooling rate and - * dLambda_du - * Can be used to check whether calculation of dLambda_du is done correctly. - * Should be removed when finished - * - * @param u Internal energy - * @param dlambda_du Pointer to gradient of cooling rate - * @param H_plus_He_heat_table 1D table of heating rates due to H, He - * @param H_plus_He_electron_abundance_table 1D table of electron abundances due - * to H,He - * @param element_cooling_table 1D table of heating rates due to metals - * @param element_electron_abundance_table 1D table of electron abundances due - * to metals - * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - */ -__attribute__((always_inline)) INLINE static double eagle_cooling_rate_1d_table( - double logu, double *dLambdaNet_du, double *H_plus_He_heat_table, - double *H_plus_He_electron_abundance_table, double *element_cooling_table, - double *element_electron_abundance_table, double *temp_table, int z_index, - float dz, int n_h_i, float d_n_h, int He_i, float d_He, - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, - float *abundance_ratio) { - double *element_lambda = NULL, lambda_net = 0.0; - const double log_10 = 2.30258509299404; - - lambda_net = eagle_metal_cooling_rate_1d_table( - logu/log_10, dLambdaNet_du, H_plus_He_heat_table, - H_plus_He_electron_abundance_table, element_cooling_table, - element_electron_abundance_table, temp_table, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, internal_const, element_lambda, abundance_ratio); - - return lambda_net; -} - -/* - * @brief Calculates cooling rate from 1d tables, used to print cooling rates - * to files for checking against Wiersma et al 2009 idl scripts. - * - * @param H_plus_He_heat_table 1D table of heating rates due to H, He - * @param H_plus_He_electron_abundance_table 1D table of electron abundances due - * to H,He - * @param element_cooling_table 1D table of heating rates due to metals - * @param element_electron_abundance_table 1D table of electron abundances due - * to metals - * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - */ -__attribute__((always_inline)) INLINE static double + double, double *, double *, + double *, double *, + double *, double *, + const struct part *restrict, + const struct cooling_function_data *restrict, + const struct cosmology *restrict, + const struct phys_const *, + double *); + +double eagle_cooling_rate( + double, double *, int, + float, int, float, int, float, + const struct part *restrict, + const struct cooling_function_data *restrict, + const struct cosmology *restrict, + const struct phys_const *, + float *); + +double eagle_cooling_rate_1d_table( + double, double *, double *, + double *, double *, + double *, double *, int, + float, int, float, int, float, + const struct part *restrict, + const struct cooling_function_data *restrict, + const struct cosmology *restrict, + const struct phys_const *, + float *); + +double eagle_print_metal_cooling_rate( - int z_index, float dz, int n_h_i, float d_n_h, int He_i, - float d_He, const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, - float *abundance_ratio) { - double *element_lambda, lambda_net = 0.0, dLambdaNet_du; - element_lambda = malloc((cooling->N_Elements + 2) * sizeof(double)); - double u = hydro_get_physical_internal_energy(p, cosmo) * - cooling->internal_energy_scale; - - char output_filename[25]; - FILE **output_file = malloc((cooling->N_Elements + 2) * sizeof(FILE *)); - for (int element = 0; element < cooling->N_Elements + 2; element++) { - sprintf(output_filename, "%s%d%s", "cooling_element_", element, ".dat"); - output_file[element] = fopen(output_filename, "a"); - if (output_file == NULL) { - printf("Error opening file!\n"); - exit(1); - } - } - - for (int j = 0; j < cooling->N_Elements + 2; j++) element_lambda[j] = 0.0; - lambda_net = eagle_metal_cooling_rate( - log10(u), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, internal_const, element_lambda, abundance_ratio); - for (int j = 0; j < cooling->N_Elements + 2; j++) { - fprintf(output_file[j], "%.5e\n", element_lambda[j]); - } - - for (int i = 0; i < cooling->N_Elements + 2; i++) fclose(output_file[i]); - - return lambda_net; -} - -/* - * @brief Calculates cooling rate from 1d tables, used to print cooling rates - * to files for checking against Wiersma et al 2009 idl scripts. - * - * @param H_plus_He_heat_table 1D table of heating rates due to H, He - * @param H_plus_He_electron_abundance_table 1D table of electron abundances due - * to H,He - * @param element_cooling_table 1D table of heating rates due to metals - * @param element_electron_abundance_table 1D table of electron abundances due - * to metals - * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset - * @param p Particle structure - * @param cooling Cooling data structure - * @param cosmo Cosmology structure - * @param internal_const Physical constants structure - */ -__attribute__((always_inline)) INLINE static double + int, float, int, float, int, + float, const struct part *restrict, + const struct cooling_function_data *restrict, + const struct cosmology *restrict, + const struct phys_const *, + float *); + +double eagle_print_metal_cooling_rate_1d_table( - double *H_plus_He_heat_table, double *H_plus_He_electron_abundance_table, - double *element_print_cooling_table, double *element_electron_abundance_table, - double *temp_table, int z_index, float dz, int n_h_i, float d_n_h, int He_i, - float d_He, const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const, - float *abundance_ratio) { - double *element_lambda, lambda_net = 0.0; - element_lambda = malloc((cooling->N_Elements + 2) * sizeof(double)); - double u = hydro_get_physical_internal_energy(p, cosmo) * - cooling->internal_energy_scale; - double dLambdaNet_du; - - char output_filename[25]; - FILE **output_file = malloc((cooling->N_Elements + 2) * sizeof(FILE *)); - for (int element = 0; element < cooling->N_Elements + 2; element++) { - sprintf(output_filename, "%s%d%s", "cooling_element_", element, ".dat"); - output_file[element] = fopen(output_filename, "a"); - if (output_file == NULL) { - printf("Error opening file!\n"); - exit(1); - } - } - - for (int j = 0; j < cooling->N_Elements + 2; j++) element_lambda[j] = 0.0; - lambda_net = eagle_metal_cooling_rate_1d_table( - log10(u), &dLambdaNet_du, H_plus_He_heat_table, - H_plus_He_electron_abundance_table, element_print_cooling_table, - element_electron_abundance_table, temp_table, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, internal_const, element_lambda, abundance_ratio); - for (int j = 0; j < cooling->N_Elements + 2; j++) { - fprintf(output_file[j], "%.5e\n", element_lambda[j]); - } - - for (int i = 0; i < cooling->N_Elements + 2; i++) fclose(output_file[i]); - - return lambda_net; -} - -/* - * @brief Bisection integration scheme for when Newton Raphson method fails to - * converge - * - * @param x_init Initial guess for log(internal energy) - * @param u_ini Internal energy at beginning of hydro step - * @param H_plus_He_heat_table 1D table of heating rates due to H, He - * @param H_plus_He_electron_abundance_table 1D table of electron abundances due - * to H,He - * @param element_cooling_table 1D table of heating rates due to metals - * @param element_electron_abundance_table 1D table of electron abundances due - * to metals - * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset - * @param p Particle structure - * @param cosmo Cosmology structure - * @param cooling Cooling data structure - * @param phys_const Physical constants structure - * @param dt Hydro timestep - */ -__attribute__((always_inline)) INLINE static float bisection_iter( - float x_init, double u_ini, double *H_plus_He_heat_table, - double *H_plus_He_electron_abundance_table, double *element_cooling_table, - double *element_electron_abundance_table, double *temp_table, int z_index, - float dz, int n_h_i, float d_n_h, int He_i, float d_He, float He_reion_heat, - struct part *restrict p, const struct cosmology *restrict cosmo, - const struct cooling_function_data *restrict cooling, - const struct phys_const *restrict phys_const, - float *abundance_ratio, float dt, float *ub, float *lb) { - double x_a, x_b, x_next, f_a, f_b, f_next, dLambdaNet_du; - int i = 0; - const float bisection_tolerance = 1.0e-8; - - float XH = p->chemistry_data.metal_mass_fraction[chemistry_element_H]; - - /* convert Hydrogen mass fraction in Hydrogen number density */ - double inn_h = - chemistry_get_number_density(p, cosmo, chemistry_element_H, phys_const) * - cooling->number_density_scale; - - /* ratefact = inn_h * inn_h / rho; Might lead to round-off error: replaced by - * equivalent expression below */ - double ratefact = inn_h * (XH / eagle_proton_mass_cgs); - - /* set helium and hydrogen reheating term */ - - // Add bracketing? - x_a = *ub; - x_b = *lb; - f_a = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate_1d_table( - x_a, &dLambdaNet_du, H_plus_He_heat_table, - H_plus_He_electron_abundance_table, element_cooling_table, - element_electron_abundance_table, temp_table, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); - f_b = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate_1d_table( - x_b, &dLambdaNet_du, H_plus_He_heat_table, - H_plus_He_electron_abundance_table, element_cooling_table, - element_electron_abundance_table, temp_table, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); - -#if SWIFT_DEBUG_CHECKS - assert(f_a * f_b < 0); -#endif - - i = 0; - do { - x_next = 0.5 * (x_a + x_b); - f_next = (He_reion_heat / (dt * ratefact)) + eagle_cooling_rate_1d_table( - x_next, &dLambdaNet_du, H_plus_He_heat_table, - H_plus_He_electron_abundance_table, element_cooling_table, - element_electron_abundance_table, temp_table, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); - if (f_a * f_next < 0) { - x_b = x_next; - f_b = f_next; - } else { - x_a = x_next; - f_a = f_next; - } - i++; - } while (fabs(x_a - x_b) > bisection_tolerance && i < 50*eagle_max_iterations); - - if (i >= 50*eagle_max_iterations) n_eagle_cooling_rate_calls_4++; - - return x_b; -} - - -/* - * @brief Newton Raphson integration scheme to calculate particle cooling over - * hydro timestep - * - * @param x_init Initial guess for log(internal energy) - * @param u_ini Internal energy at beginning of hydro step - * @param H_plus_He_heat_table 1D table of heating rates due to H, He - * @param H_plus_He_electron_abundance_table 1D table of electron abundances due - * to H,He - * @param element_cooling_table 1D table of heating rates due to metals - * @param element_electron_abundance_table 1D table of electron abundances due - * to metals - * @param temp_table 1D table of temperatures - * @param z_index Redshift index of particle - * @param dz Redshift offset of particle - * @param n_h_i Particle hydrogen number density index - * @param d_n_h Particle hydrogen number density offset - * @param He_i Particle helium fraction index - * @param d_He Particle helium fraction offset - * @param p Particle structure - * @param cosmo Cosmology structure - * @param cooling Cooling data structure - * @param phys_const Physical constants structure - * @param dt Hydro timestep - * @param printflag Flag to identify if scheme failed to converge - * @param lb lower bound to be used by bisection scheme - * @param ub upper bound to be used by bisection scheme - */ -__attribute__((always_inline)) INLINE static float newton_iter( - float x_init, double u_ini, int z_index, - float dz, int n_h_i, float d_n_h, int He_i, float d_He, - float He_reion_heat, struct part *restrict p, - const struct cosmology *restrict cosmo, - const struct cooling_function_data *restrict cooling, - const struct phys_const *restrict phys_const, - float *abundance_ratio, float dt, int *printflag, - float *lb, float *ub) { - /* this routine does the iteration scheme, call one and it iterates to - * convergence */ - - const float newton_tolerance = 1.0e-2; - double x, x_old; - double dLambdaNet_du, LambdaNet; - float XH = p->chemistry_data.metal_mass_fraction[chemistry_element_H]; - - /* convert Hydrogen mass fraction in Hydrogen number density */ - double inn_h = - chemistry_get_number_density(p, cosmo, chemistry_element_H, phys_const) * - cooling->number_density_scale; - - /* ratefact = inn_h * inn_h / rho; Might lead to round-off error: replaced by - * equivalent expression below */ - double ratefact = inn_h * (XH / eagle_proton_mass_cgs); - - x_old = x_init; - x = x_old; - int i = 0; - float relax = 1.0; - float log_table_bound_high = 43.749, log_table_bound_low = 20.723; // Corresponds to u = 10^19, 10^9 - - do /* iterate to convergence */ - { - if (relax == 1.0) x_old = x; - LambdaNet = (He_reion_heat / (dt * ratefact)) + - eagle_cooling_rate( - x_old, &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); - if (LambdaNet < 0) { - *ub = fmin(*ub,x_old); - } else if (LambdaNet > 0) { - *lb = fmax(*lb,x_old); - } - - n_eagle_cooling_rate_calls_1++; - - // Newton iteration. - x = x_old - - relax * (1.0 - u_ini * exp(-x_old) - - LambdaNet * ratefact * dt * exp(-x_old)) / - (1.0 - dLambdaNet_du * ratefact * dt); - - // check whether iterations go out of bounds of table, - // if out of bounds, try again with smaller newton step - if (x > log_table_bound_high) { - x = (log_table_bound_high + x_old)/2.0; - } else if (x < log_table_bound_low) { - x = (log_table_bound_low + x_old)/2.0; - } - - i++; - } while (fabs(x - x_old) > newton_tolerance && i < eagle_max_iterations); - if (i >= eagle_max_iterations) { - n_eagle_cooling_rate_calls_3++; - // failed to converge the first time - if (*printflag == 0) *printflag = 1; - } - - return x; -} - -/* - * @brief Calculate ratio of particle element abundances - * to solar abundance - * - * @param p Pointer to particle data - * @param cooling Pointer to cooling data - */ -__attribute__((always_inline)) INLINE static void abundance_ratio_to_solar( - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - float *ratio_solar) { - for(enum chemistry_element elem = chemistry_element_H; elem < chemistry_element_count; elem++){ - if (elem == chemistry_element_Fe) { - ratio_solar[elem] = p->chemistry_data.metal_mass_fraction[elem]/ - cooling->SolarAbundances[elem+2]; // NOTE: solar abundances have iron last with calcium and sulphur directly before, hence +2 - } else { - ratio_solar[elem] = p->chemistry_data.metal_mass_fraction[elem]/ - cooling->SolarAbundances[elem]; - } - } - ratio_solar[chemistry_element_count] = p->chemistry_data.metal_mass_fraction[chemistry_element_Si]* - cooling->sulphur_over_silicon_ratio/ - cooling->SolarAbundances[chemistry_element_count-1]; // NOTE: solar abundances have iron last with calcium and sulphur directly before, hence -1 - ratio_solar[chemistry_element_count+1] = p->chemistry_data.metal_mass_fraction[chemistry_element_Si]* - cooling->calcium_over_silicon_ratio/ - cooling->SolarAbundances[chemistry_element_count]; // NOTE: solar abundances have iron last with calcium and sulphur directly before -} - -/** - * @brief construct all 1d tables - * - * @param - */ -__attribute__((always_inline)) INLINE void static construct_1d_tables( - int z_index, float dz, int n_h_i, float d_n_h, - int He_i, float d_He, - const struct phys_const *restrict phys_const, - const struct unit_system *restrict us, - const struct cosmology *restrict cosmo, - const struct cooling_function_data *restrict cooling, - const struct part *restrict p, - float *abundance_ratio, - double *H_plus_He_heat_table, - double *H_plus_He_electron_abundance_table, - double *element_cooling_table, - double *element_cooling_print_table, - double *element_electron_abundance_table, - double *temp_table, - float *ub, float *lb) { - - construct_1d_table_from_4d(p, cooling, cosmo, phys_const, - cooling->table.element_cooling.temperature, - z_index, dz, cooling->N_Redshifts, n_h_i, d_n_h, - cooling->N_nH, He_i, d_He, cooling->N_He, cooling->N_Temp, temp_table, ub, lb); - - // element cooling - construct_1d_table_from_4d( - p, cooling, cosmo, phys_const, - cooling->table.element_cooling.H_plus_He_heating, z_index, dz, cooling->N_Redshifts, n_h_i, d_n_h, - cooling->N_nH, He_i, d_He, cooling->N_He, cooling->N_Temp, H_plus_He_heat_table, ub, lb); - construct_1d_table_from_4d( - p, cooling, cosmo, phys_const, - cooling->table.element_cooling.H_plus_He_electron_abundance, z_index, - dz, cooling->N_Redshifts, n_h_i, d_n_h, cooling->N_nH, He_i, d_He, - cooling->N_He, cooling->N_Temp, H_plus_He_electron_abundance_table, ub, lb); - construct_1d_table_from_4d_elements( - p, cooling, cosmo, phys_const, - cooling->table.element_cooling.metal_heating, z_index, dz, cooling->N_Redshifts, - n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_cooling_table, abundance_ratio, ub, lb); - construct_1d_print_table_from_4d_elements( - p, cooling, cosmo, phys_const, - cooling->table.element_cooling.metal_heating, z_index, dz, cooling->N_Redshifts, - n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_cooling_print_table, abundance_ratio, ub, lb); - construct_1d_table_from_3d( - p, cooling, cosmo, phys_const, - cooling->table.element_cooling.electron_abundance, z_index, dz, cooling->N_Redshifts, - n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_electron_abundance_table, ub, lb); - - // photodissociation cooling - //construct_1d_table_from_3d( - // p, cooling, cosmo, phys_const, - // cooling->table.photodissociation_cooling.H_plus_He_heating, n_h_i, d_n_h, cooling->N_nH, - // He_i, d_He, cooling->N_He, cooling->N_Temp, H_plus_He_heat_table, ub, lb); - //construct_1d_table_from_3d( - // p, cooling, cosmo, phys_const, - // cooling->table.photodissociation_cooling.H_plus_He_electron_abundance, - // n_h_i, d_n_h, cooling->N_nH, He_i, d_He, cooling->N_He, - // cooling->N_Temp, H_plus_He_electron_abundance_table, ub, lb); - //construct_1d_table_from_3d_elements( - // p, cooling, cosmo, phys_const, - // cooling->table.photodissociation_cooling.metal_heating, - // n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_cooling_table, abundance_ratio, ub, lb); - //construct_1d_table_from_2d( - // p, cooling, cosmo, phys_const, - // cooling->table.photodissociation_cooling.electron_abundance, - // n_h_i, d_n_h, cooling->N_nH, cooling->N_Temp, element_electron_abundance_table, ub, lb); -} - -/** - * @brief Apply the cooling function to a particle. - * - * @param phys_const The physical constants in internal units. - * @param us The internal system of units. - * @param cosmo The current cosmological model. - * @param cooling The #cooling_function_data used in the run. - * @param p Pointer to the particle data. - * @param xp Pointer to the extended particle data. - * @param dt The time-step of this particle. - */ -__attribute__((always_inline)) INLINE static void cooling_cool_part( - const struct phys_const *restrict phys_const, - const struct unit_system *restrict us, - const struct cosmology *restrict cosmo, - const struct cooling_function_data *restrict cooling, - struct part *restrict p, struct xpart *restrict xp, float dt) { - - const float exp_factor = 0.05; - const double log_10_e = 0.43429448190325182765; - double u_old = (hydro_get_physical_internal_energy(p, cosmo) - + hydro_get_internal_energy_dt(p) * dt) * - cooling->internal_energy_scale; - float dz; - int z_index; - get_redshift_index(cosmo->z, &z_index, &dz, cooling); - - float XH, HeFrac; - double inn_h; - - double ratefact, u, LambdaNet, LambdaTune = 0, dLambdaNet_du; - - dt *= units_cgs_conversion_factor(us, UNIT_CONV_TIME); - - u = u_old; - double u_ini = u_old;//, u_temp; - - float abundance_ratio[chemistry_element_count + 2]; - abundance_ratio_to_solar(p, cooling, abundance_ratio); - - XH = p->chemistry_data.metal_mass_fraction[chemistry_element_H]; - HeFrac = p->chemistry_data.metal_mass_fraction[chemistry_element_He] / - (XH + p->chemistry_data.metal_mass_fraction[chemistry_element_He]); - - /* convert Hydrogen mass fraction in Hydrogen number density */ - inn_h = - chemistry_get_number_density(p, cosmo, chemistry_element_H, phys_const) * - cooling->number_density_scale; - /* ratefact = inn_h * inn_h / rho; Might lead to round-off error: replaced by - * equivalent expression below */ - ratefact = inn_h * (XH / eagle_proton_mass_cgs); - /* set helium and hydrogen reheating term */ - if (cooling->he_reion == 1) LambdaTune = eagle_helium_reionization_extraheat(z_index, dz, cooling); - - int He_i, n_h_i; - float d_He, d_n_h; - get_index_1d(cooling->HeFrac, cooling->N_He, HeFrac, &He_i, &d_He); - get_index_1d(cooling->nH, cooling->N_nH, log10(inn_h), &n_h_i, &d_n_h); - - - LambdaNet = LambdaTune/(dt*ratefact) + eagle_cooling_rate( - log(u_ini), &dLambdaNet_du, z_index, dz, n_h_i, d_n_h, - He_i, d_He, p, cooling, cosmo, phys_const, abundance_ratio); - - if (fabs(ratefact * LambdaNet * dt) < exp_factor * u_old) { - /* cooling rate is small, take the explicit solution */ - u = u_old + ratefact * LambdaNet * dt; - } else { - n_eagle_cooling_rate_calls_2++; - float x, lower_bound = cooling->Therm[0]/log_10_e, upper_bound = cooling->Therm[cooling->N_Temp-1]/log_10_e; - - double u_eq = u_ini; - - if (dt > 0) { - double log_u_temp = log(u_eq); - - int printflag = 0; - x = newton_iter(log_u_temp, u_ini, z_index, dz, - n_h_i, d_n_h, He_i, d_He, LambdaTune, p, cosmo, cooling, phys_const, - abundance_ratio, dt, &printflag, &lower_bound, &upper_bound); - if (printflag == 1) { - // newton method didn't work, so revert to bisection - - // construct 1d table of cooling rates wrt temperature - double temp_table[176]; // WARNING sort out how it is declared/allocated - double H_plus_He_heat_table[176]; - double H_plus_He_electron_abundance_table[176]; - double element_cooling_table[176]; - double element_cooling_print_table[9*176]; - double element_electron_abundance_table[176]; - construct_1d_tables(z_index, dz, n_h_i, d_n_h, He_i, d_He, - phys_const, us, cosmo, cooling, p, - abundance_ratio, - H_plus_He_heat_table, - H_plus_He_electron_abundance_table, - element_cooling_table, - element_cooling_print_table, - element_electron_abundance_table, - temp_table, - &upper_bound, - &lower_bound); - // perform bisection scheme - x = bisection_iter(log_u_temp,u_ini,H_plus_He_heat_table,H_plus_He_electron_abundance_table,element_cooling_print_table,element_electron_abundance_table,temp_table,z_index,dz,n_h_i,d_n_h,He_i,d_He,LambdaTune,p,cosmo,cooling,phys_const,abundance_ratio,dt,&upper_bound,&lower_bound); - - printflag = 2; - } - u = exp(x); - } - } - - const float hydro_du_dt = hydro_get_internal_energy_dt(p); - - - // calculate du/dt - float cooling_du_dt = 0.0; - if (dt > 0) { - cooling_du_dt = (u - u_ini) / dt / cooling->power_scale; - } - - /* Update the internal energy time derivative */ - hydro_set_internal_energy_dt(p, hydro_du_dt + cooling_du_dt); - - /* Store the radiated energy */ - xp->cooling_data.radiated_energy += - -hydro_get_mass(p) * cooling_du_dt * - (dt / units_cgs_conversion_factor(us, UNIT_CONV_TIME)); -} - -/** - * @brief Writes the current model of SPH to the file - * @param h_grpsph The HDF5 group in which to write - */ -__attribute__((always_inline)) INLINE static void cooling_write_flavour( - hid_t h_grpsph) { - - io_write_attribute_s(h_grpsph, "Cooling Model", "EAGLE"); -} - -/** - * @brief Computes the cooling time-step. - * - * @param cooling The #cooling_function_data used in the run. - * @param phys_const The physical constants in internal units. - * @param us The internal system of units. - * @param cosmo The current cosmological model. - * @param p Pointer to the particle data. - */ -__attribute__((always_inline)) INLINE static float cooling_timestep( - const struct cooling_function_data *restrict cooling, - const struct phys_const *restrict phys_const, - const struct cosmology *restrict cosmo, - const struct unit_system *restrict us, const struct part *restrict p, const struct xpart *restrict xp) { - - /* Remember to update when using an implicit integrator!!!*/ - // const float cooling_rate = cooling->cooling_rate; - // const float internal_energy = hydro_get_comoving_internal_energy(p); - // return cooling->cooling_tstep_mult * internal_energy / fabsf(cooling_rate); - - return FLT_MAX; -} - -/** - * @brief Sets the cooling properties of the (x-)particles to a valid start - * state. - * - * @param phys_const The physical constants in internal units. - * @param us The internal system of units. - * @param cosmo The current cosmological model. - * @param cooling The properties of the cooling function. - * @param p Pointer to the particle data. - * @param xp Pointer to the extended particle data. - */ -__attribute__((always_inline)) INLINE static void cooling_first_init_part( - const struct phys_const* restrict phys_const, - const struct unit_system* restrict us, - const struct cosmology* restrict cosmo, - const struct cooling_function_data* restrict cooling, - const struct part* restrict p, struct xpart* restrict xp) { - - xp->cooling_data.radiated_energy = 0.f; -} - -/** - * @brief Returns the total radiated energy by this particle. - * - * @param xp The extended particle data - */ -__attribute__((always_inline)) INLINE static float cooling_get_radiated_energy( - const struct xpart *restrict xp) { - - return xp->cooling_data.radiated_energy; -} - -/** - * @brief Checks the tables that are currently loaded in memory and read - * new ones if necessary. - * - * @param cooling The #cooling_function_data we play with. - * @param index_z The index along the redshift axis of the tables of the current - * z. - */ -inline static void eagle_check_cooling_tables(struct cooling_function_data* cooling, - int index_z) { - - /* Do we already have the right table in memory? */ - if (cooling->low_z_index == index_z) return; - - if (index_z >= cooling->N_Redshifts) { - - error("Missing implementation"); - // MATTHIEU: Add reading of high-z tables - - /* Record the table indices */ - cooling->low_z_index = index_z; - cooling->high_z_index = index_z; - } else { - - /* Record the table indices */ - cooling->low_z_index = index_z; - cooling->high_z_index = index_z + 1; - - /* Load the damn thing */ - eagle_read_two_tables(cooling); - } -} - -/** - * @brief Common operations performed on the cooling function at a - * given time-step or redshift. - * - * Here we load the cooling tables corresponding to our redshift. - * - * @param phys_const The physical constants in internal units. - * @param us The internal system of units. - * @param cosmo The current cosmological model. - * @param cooling The #cooling_function_data used in the run. - */ -INLINE static void cooling_update(const struct phys_const* phys_const, - const struct unit_system* us, - const struct cosmology* cosmo, - struct cooling_function_data* cooling) { - /* Current redshift */ - const float redshift = cosmo->z; - - /* Get index along the redshift index of the tables */ - int index_z; - float delta_z_table; - get_redshift_index(redshift, &index_z, &delta_z_table, cooling); - cooling->index_z = index_z; - cooling->delta_z_table = delta_z_table; - - /* Load the current table (if different from what we have) */ - eagle_check_cooling_tables(cooling, index_z); -} - - -/** - * @brief Initialises the cooling properties. - * - * @param parameter_file The parsed parameter file. - * @param us The current internal system of units. - * @param phys_const The physical constants in internal units. - * @param cooling The cooling properties to initialize - */ -static INLINE void cooling_init_backend( - const struct swift_params *parameter_file, const struct unit_system *us, - const struct phys_const *phys_const, - struct cooling_function_data *cooling) { - - char fname[200]; - - parser_get_param_string(parameter_file, "EagleCooling:filename", - cooling->cooling_table_path); - cooling->reionisation_redshift = parser_get_param_float( - parameter_file, "EagleCooling:reionisation_redshift"); - cooling->calcium_over_silicon_ratio = parser_get_param_float( - parameter_file, "EAGLEChemistry:CalciumOverSilicon"); - cooling->sulphur_over_silicon_ratio = parser_get_param_float( - parameter_file, "EAGLEChemistry:SulphurOverSilicon"); - cooling->he_reion = parser_get_param_float( - parameter_file, "EagleCooling:he_reion"); - cooling->he_reion_z_center = parser_get_param_float( - parameter_file, "EagleCooling:he_reion_z_center"); - cooling->he_reion_z_sigma = parser_get_param_float( - parameter_file, "EagleCooling:he_reion_z_sigma"); - cooling->he_reion_ev_pH = parser_get_param_float( - parameter_file, "EagleCooling:he_reion_ev_pH"); - - GetCoolingRedshifts(cooling); - sprintf(fname, "%sz_0.000.hdf5", cooling->cooling_table_path); - ReadCoolingHeader(fname, cooling); - MakeNamePointers(cooling); - cooling->table = eagle_readtable(cooling->cooling_table_path, cooling); - printf("Eagle cooling.h read table \n"); - - cooling->ElementAbundance_SOLARM1 = - malloc(cooling->N_SolarAbundances * sizeof(float)); - cooling->solar_abundances = malloc(cooling->N_Elements * sizeof(double)); - - cooling->delta_u = cooling->Therm[1] - cooling->Therm[0]; - - cooling->internal_energy_scale = - units_cgs_conversion_factor(us, UNIT_CONV_ENERGY) / - units_cgs_conversion_factor(us, UNIT_CONV_MASS); - cooling->number_density_scale = - units_cgs_conversion_factor(us, UNIT_CONV_DENSITY) / - units_cgs_conversion_factor(us, UNIT_CONV_MASS); - cooling->power_scale = units_cgs_conversion_factor(us, UNIT_CONV_POWER) / - units_cgs_conversion_factor(us, UNIT_CONV_MASS); - cooling->temperature_scale = - units_cgs_conversion_factor(us, UNIT_CONV_TEMPERATURE); -} - -/** - * @brief Prints the properties of the cooling model to stdout. - * - * @param cooling The properties of the cooling function. - */ -static INLINE void cooling_print_backend( - const struct cooling_function_data *cooling) { - - message("Cooling function is 'EAGLE'."); -} + double *, double *, + double *, double *, + double *, const struct part *restrict, + const struct cooling_function_data *restrict, + const struct cosmology *restrict, + const struct phys_const *); + +float bisection_iter( + float, double, int, + float, int, float, int, float, float, + struct part *restrict, const struct cosmology *restrict, + const struct cooling_function_data *restrict, + const struct phys_const *restrict, + float *, float); + +float newton_iter( + float, double, int, + float, int, float, int, float, + float, struct part *restrict, + const struct cosmology *restrict, + const struct cooling_function_data *restrict, + const struct phys_const *restrict, + float *, float, int *); + +void abundance_ratio_to_solar( + const struct part *restrict, + const struct cooling_function_data *restrict, + float *); + +void cooling_cool_part( + const struct phys_const *restrict, + const struct unit_system *restrict, + const struct cosmology *restrict, + const struct cooling_function_data *restrict, + struct part *restrict, struct xpart *restrict, float); + +void cooling_write_flavour( + hid_t); + +float cooling_timestep( + const struct cooling_function_data *restrict, + const struct phys_const *restrict, + const struct cosmology *restrict, + const struct unit_system *restrict, const struct part *restrict, const struct xpart *restrict); + +void cooling_first_init_part( + const struct phys_const* restrict, + const struct unit_system* restrict, + const struct cosmology* restrict, + const struct cooling_function_data* restrict, + const struct part* restrict, struct xpart* restrict); + +float cooling_get_radiated_energy( + const struct xpart *restrict); + +void eagle_check_cooling_tables(struct cooling_function_data *, int); + +void cooling_update(const struct phys_const*, + const struct unit_system*, + const struct cosmology*, + struct cooling_function_data*); + +void cooling_init_backend( + struct swift_params *, const struct unit_system *, + const struct phys_const *, + struct cooling_function_data *); + +void cooling_print_backend(const struct cooling_function_data *); #endif /* SWIFT_COOLING_EAGLE_H */ diff --git a/src/cooling/EAGLE/cooling_struct.h b/src/cooling/EAGLE/cooling_struct.h index 97be7b11be56d62a7c6f1e58d5bf78fc157a4a17..4e903d580365f6b93f8da2132f26eedfd64ab87e 100644 --- a/src/cooling/EAGLE/cooling_struct.h +++ b/src/cooling/EAGLE/cooling_struct.h @@ -29,6 +29,8 @@ #define eagle_max_iterations 15 #define eagle_proton_mass_cgs 1.6726e-24 #define eagle_ev_to_erg 1.60217646e-12 +#define eagle_log_10 2.30258509299404 +#define eagle_log_10_e 0.43429448190325182765 /* * @brief struct containing radiative and heating rates diff --git a/src/cooling/EAGLE/eagle_cool_tables.c b/src/cooling/EAGLE/eagle_cool_tables.c index 4aa8d8496095ebd703d4ecf5057c7037223aca25..58e423a58ef41e60ad671729adf88087d389b3b2 100644 --- a/src/cooling/EAGLE/eagle_cool_tables.c +++ b/src/cooling/EAGLE/eagle_cool_tables.c @@ -31,10 +31,23 @@ #include <math.h> #include <stdlib.h> #include <string.h> -#include "cooling_struct.h" #include "eagle_cool_tables.h" -#include "error.h" +#include "cooling_struct.h" #include "interpolate.h" +#include "error.h" + +/* + * @brief String assignment function from EAGLE + * + * @param s String + */ +char *mystrdup(const char *s) { + char *p; + + p = (char *)malloc((strlen(s) + 1) * sizeof(char)); + strcpy(p, s); + return p; +} /* * @brief Reads in EAGLE table of redshift values @@ -72,7 +85,8 @@ void GetCoolingRedshifts(struct cooling_function_data *cooling) { * @param fname Filepath for cooling table from which to read header * @param cooling Cooling data structure */ -void ReadCoolingHeader(char *fname, struct cooling_function_data *cooling) { +void ReadCoolingHeader(char *fname, + struct cooling_function_data *cooling) { int i; hid_t tempfile_id, dataset, datatype; @@ -121,14 +135,10 @@ void ReadCoolingHeader(char *fname, struct cooling_function_data *cooling) { cooling->HeFrac = malloc(cooling->N_He * sizeof(float)); cooling->SolarAbundances = malloc(cooling->N_SolarAbundances * sizeof(float)); cooling->Therm = malloc(cooling->N_Temp * sizeof(float)); - - cooling->ElementNames = malloc(cooling->N_Elements * sizeof(char *)); - for (i = 0; i < cooling->N_Elements; i++) - cooling->ElementNames[i] = malloc(eagle_element_name_length * sizeof(char)); - - cooling->SolarAbundanceNames = malloc(cooling->N_SolarAbundances * sizeof(char *)); - for (i = 0; i < cooling->N_SolarAbundances; i++) - cooling->SolarAbundanceNames[i] = malloc(eagle_element_name_length * sizeof(char)); + cooling->ElementNames = + malloc(cooling->N_Elements * eagle_element_name_length * sizeof(char)); + cooling->SolarAbundanceNames = malloc( + cooling->N_SolarAbundances * eagle_element_name_length * sizeof(char)); // read in values for each of the arrays dataset = H5Dopen(tempfile_id, "/Solar/Temperature_bins", H5P_DEFAULT); @@ -172,12 +182,11 @@ void ReadCoolingHeader(char *fname, struct cooling_function_data *cooling) { H5Tclose(datatype); for (i = 0; i < cooling->N_Elements; i++) - strcpy(cooling->ElementNames[i],element_names[i]); - + cooling->ElementNames[i] = mystrdup(element_names[i]); char solar_abund_names[cooling->N_SolarAbundances][eagle_element_name_length]; - // read in assumed solar abundances used in constructing the tables, + // read in assumed solar abundances used in constructing the tables, // and corresponding names datatype = H5Tcopy(H5T_C_S1); status = H5Tset_size(datatype, string_length); @@ -188,11 +197,11 @@ void ReadCoolingHeader(char *fname, struct cooling_function_data *cooling) { H5Tclose(datatype); for (i = 0; i < cooling->N_SolarAbundances; i++) - strcpy(cooling->SolarAbundanceNames[i],element_names[i]); + cooling->SolarAbundanceNames[i] = mystrdup(solar_abund_names[i]); status = H5Fclose(tempfile_id); - // Convert to temperature, density and internal energy arrays to log10 + // Convert to temperature, density and internal energy arrays to log10 for (i = 0; i < cooling->N_Temp; i++) { cooling->Temp[i] = log10(cooling->Temp[i]); cooling->Therm[i] = log10(cooling->Therm[i]); @@ -202,15 +211,14 @@ void ReadCoolingHeader(char *fname, struct cooling_function_data *cooling) { } /* - * @brief Get the table of cooling rates for photoionized cooling (before - * redshift ~9) Reads in table of cooling rates and electron abundances due to - * metals (depending on temperature, hydrogen number density), cooling rates and - * electron abundances due to hydrogen and helium (depending on temperature, - * hydrogen number density and helium fraction), and temperatures (depending on - * internal energy, hydrogen number density and helium fraction; note: this is - * distinct from table of temperatures read in ReadCoolingHeader, as that table - * is used to index the cooling, electron abundance tables, whereas this one is - * used to obtain temperature of particle) + * @brief Get the table of cooling rates for photoionized cooling (before redshift ~9) + * Reads in table of cooling rates and electron abundances due to metals + * (depending on temperature, hydrogen number density), cooling rates and electron + * abundances due to hydrogen and helium (depending on temperature, hydrogen number + * density and helium fraction), and temperatures (depending on internal energy, + * hydrogen number density and helium fraction; note: this is distinct from table of + * temperatures read in ReadCoolingHeader, as that table is used to index the cooling, + * electron abundance tables, whereas this one is used to obtain temperature of particle) * * @param cooling_table_path Directory containing cooling table * @param cooling Cooling data structure @@ -235,7 +243,7 @@ struct cooling_tables_redshift_invariant get_no_compt_table( float *he_net_cooling_rate; float *he_electron_abundance; - // allocate temporary arrays (needed to change order of dimensions + // allocate temporary arrays (needed to change order of dimensions // of arrays) net_cooling_rate = (float *)malloc(cooling->N_Temp * cooling->N_nH * sizeof(float)); @@ -276,16 +284,16 @@ struct cooling_tables_redshift_invariant get_no_compt_table( for (k = 0; k < cooling->N_nH; k++) { table_index = row_major_index_2d(j, k, cooling->N_Temp, cooling->N_nH); cooling_index = row_major_index_4d( - 0, k, j, specs, 1, cooling->N_nH, cooling->N_Temp, - cooling->N_Elements); // Redshift invariant table!!! + 0, k, j, specs, 1, cooling->N_nH, + cooling->N_Temp, cooling->N_Elements); // Redshift invariant table!!! cooling_table.metal_heating[cooling_index] = -net_cooling_rate[table_index]; } } } - // read in cooling rates due to hydrogen and helium, H + He electron - // abundances, temperatures + // read in cooling rates due to hydrogen and helium, H + He electron abundances, + // temperatures sprintf(set_name, "/Metal_free/Net_Cooling"); dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, @@ -333,7 +341,8 @@ struct cooling_tables_redshift_invariant get_no_compt_table( for (j = 0; j < cooling->N_nH; j++) { table_index = row_major_index_2d(i, j, cooling->N_Temp, cooling->N_nH); cooling_index = - row_major_index_3d(0, j, i, 1, cooling->N_nH, cooling->N_Temp); + row_major_index_3d(0, j, i, 1, cooling->N_nH, + cooling->N_Temp); cooling_table.electron_abundance[cooling_index] = electron_abundance[table_index]; } @@ -347,21 +356,20 @@ struct cooling_tables_redshift_invariant get_no_compt_table( free(he_net_cooling_rate); free(he_electron_abundance); - message("done reading in no compton table"); + printf("eagle_cool_tables.h done reading in no compton table\n"); return cooling_table; } /* - * @brief Get the table of cooling rates for collisional cooling + * @brief Get the table of cooling rates for collisional cooling * Reads in table of cooling rates and electron abundances due to metals - * (depending on temperature, hydrogen number density), cooling rates and - * electron abundances due to hydrogen and helium (depending on temperature, - * hydrogen number density and helium fraction), and temperatures (depending on - * internal energy, hydrogen number density and helium fraction; note: this is - * distinct from table of temperatures read in ReadCoolingHeader, as that table - * is used to index the cooling, electron abundance tables, whereas this one is - * used to obtain temperature of particle) + * (depending on temperature, hydrogen number density), cooling rates and electron + * abundances due to hydrogen and helium (depending on temperature, hydrogen number + * density and helium fraction), and temperatures (depending on internal energy, + * hydrogen number density and helium fraction; note: this is distinct from table of + * temperatures read in ReadCoolingHeader, as that table is used to index the cooling, + * electron abundance tables, whereas this one is used to obtain temperature of particle) * * @param cooling_table_path Directory containing cooling table * @param cooling Cooling data structure @@ -385,7 +393,7 @@ struct cooling_tables_redshift_invariant get_collisional_table( float *he_net_cooling_rate; float *he_electron_abundance; - // allocate temporary arrays (needed to change order of dimensions + // allocate temporary arrays (needed to change order of dimensions // of arrays) net_cooling_rate = (float *)malloc(cooling->N_Temp * sizeof(float)); electron_abundance = (float *)malloc(cooling->N_Temp * sizeof(float)); @@ -428,8 +436,8 @@ struct cooling_tables_redshift_invariant get_collisional_table( } } - // read in cooling rates due to hydrogen and helium, H + He electron - // abundances, temperatures + // read in cooling rates due to hydrogen and helium, H + He electron abundances, + // temperatures sprintf(set_name, "/Metal_free/Net_Cooling"); dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, @@ -482,20 +490,19 @@ struct cooling_tables_redshift_invariant get_collisional_table( free(he_net_cooling_rate); free(he_electron_abundance); - message("done reading in collisional table"); + printf("eagle_cool_tables.h done reading in collisional table\n"); return cooling_table; } /* - * @brief Get the table of cooling rates for photodissociation cooling + * @brief Get the table of cooling rates for photodissociation cooling * Reads in table of cooling rates and electron abundances due to metals - * (depending on temperature, hydrogen number density), cooling rates and - * electron abundances due to hydrogen and helium (depending on temperature, - * hydrogen number density and helium fraction), and temperatures (depending on - * internal energy, hydrogen number density and helium fraction; note: this is - * distinct from table of temperatures read in ReadCoolingHeader, as that table - * is used to index the cooling, electron abundance tables, whereas this one is - * used to obtain temperature of particle) + * (depending on temperature, hydrogen number density), cooling rates and electron + * abundances due to hydrogen and helium (depending on temperature, hydrogen number + * density and helium fraction), and temperatures (depending on internal energy, + * hydrogen number density and helium fraction; note: this is distinct from table of + * temperatures read in ReadCoolingHeader, as that table is used to index the cooling, + * electron abundance tables, whereas this one is used to obtain temperature of particle) * * @param cooling_table_path Directory containing cooling table * @param cooling Cooling data structure @@ -519,7 +526,7 @@ struct cooling_tables_redshift_invariant get_photodis_table( float *he_net_cooling_rate; float *he_electron_abundance; - // allocate temporary arrays (needed to change order of dimensions + // allocate temporary arrays (needed to change order of dimensions // of arrays) net_cooling_rate = (float *)malloc(cooling->N_Temp * cooling->N_nH * sizeof(float)); @@ -560,16 +567,16 @@ struct cooling_tables_redshift_invariant get_photodis_table( for (k = 0; k < cooling->N_nH; k++) { table_index = row_major_index_2d(j, k, cooling->N_Temp, cooling->N_nH); cooling_index = row_major_index_3d( - k, j, specs, cooling->N_nH, cooling->N_Temp, - cooling->N_Elements); // Redshift invariant table!!! + k, j, specs, cooling->N_nH, + cooling->N_Temp, cooling->N_Elements); // Redshift invariant table!!! cooling_table.metal_heating[cooling_index] = -net_cooling_rate[table_index]; } } } - // read in cooling rates due to hydrogen and helium, H + He electron - // abundances, temperatures + // read in cooling rates due to hydrogen and helium, H + He electron abundances, + // temperatures sprintf(set_name, "/Metal_free/Net_Cooling"); dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, @@ -631,7 +638,7 @@ struct cooling_tables_redshift_invariant get_photodis_table( free(he_net_cooling_rate); free(he_electron_abundance); - message("done reading in photodissociation table"); + printf("eagle_cool_tables.h done reading in photodissociation table\n"); return cooling_table; } @@ -661,7 +668,7 @@ struct cooling_tables get_cooling_table( float *he_net_cooling_rate; float *he_electron_abundance; - // allocate temporary arrays (needed to change order of dimensions + // allocate temporary arrays (needed to change order of dimensions // of arrays) net_cooling_rate = (float *)malloc(cooling->N_Temp * cooling->N_nH * sizeof(float)); @@ -713,16 +720,16 @@ struct cooling_tables get_cooling_table( table_index = row_major_index_2d(j, i, cooling->N_Temp, cooling->N_nH); cooling_index = row_major_index_4d( - z_index, i, j, specs, cooling->N_Redshifts, cooling->N_nH, - cooling->N_Temp, cooling->N_Elements); + z_index, i, j, specs, cooling->N_Redshifts, + cooling->N_nH, cooling->N_Temp, cooling->N_Elements); cooling_table.metal_heating[cooling_index] = -net_cooling_rate[table_index]; } } } - // read in cooling rates due to hydrogen and helium, H + He electron - // abundances, temperatures + // read in cooling rates due to hydrogen and helium, H + He electron abundances, + // temperatures sprintf(set_name, "/Metal_free/Net_Cooling"); dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, @@ -785,7 +792,7 @@ struct cooling_tables get_cooling_table( free(he_net_cooling_rate); free(he_electron_abundance); - message("done reading in general cooling table"); + printf("eagle_cool_tables.h done reading in general cooling table\n"); return cooling_table; } @@ -802,7 +809,8 @@ struct eagle_cooling_table eagle_readtable( struct eagle_cooling_table table; - table.no_compton_cooling = get_no_compt_table(cooling_table_path, cooling); + table.no_compton_cooling = + get_no_compt_table(cooling_table_path, cooling); table.photodissociation_cooling = get_photodis_table(cooling_table_path, cooling); table.collisional_cooling = @@ -812,4 +820,180 @@ struct eagle_cooling_table eagle_readtable( return table; } +/* + * @brief Work in progress: read in only two tables for given redshift + * + * @param cooling_table_path Directory containing cooling tables + * @param cooling Cooling function data structure + * @param filename1 filename2 Names of the two tables we need to read + */ +struct cooling_tables get_two_cooling_tables( + char *cooling_table_path, + const struct cooling_function_data *restrict cooling, + char *filename1, char *filename2) { + + struct cooling_tables cooling_table; + hid_t file_id, dataset; + + herr_t status; + + char fname[500], set_name[500]; + + int specs, i, j, k, table_index, cooling_index; + + float *net_cooling_rate; + float *electron_abundance; + float *temperature; + float *he_net_cooling_rate; + float *he_electron_abundance; + + // allocate temporary arrays (needed to change order of dimensions + // of arrays) + net_cooling_rate = + (float *)malloc(cooling->N_Temp * cooling->N_nH * sizeof(float)); + electron_abundance = + (float *)malloc(cooling->N_Temp * cooling->N_nH * sizeof(float)); + temperature = (float *)malloc(cooling->N_He * cooling->N_Temp * + cooling->N_nH * sizeof(float)); + he_net_cooling_rate = (float *)malloc(cooling->N_He * cooling->N_Temp * + cooling->N_nH * sizeof(float)); + he_electron_abundance = (float *)malloc(cooling->N_He * cooling->N_Temp * + cooling->N_nH * sizeof(float)); + + // allocate arrays that the values will be assigned to + cooling_table.metal_heating = + (float *)malloc(cooling->N_Redshifts * cooling->N_Elements * + cooling->N_Temp * cooling->N_nH * sizeof(float)); + cooling_table.electron_abundance = (float *)malloc( + cooling->N_Redshifts * cooling->N_Temp * cooling->N_nH * sizeof(float)); + cooling_table.temperature = + (float *)malloc(cooling->N_Redshifts * cooling->N_He * cooling->N_Temp * + cooling->N_nH * sizeof(float)); + cooling_table.H_plus_He_heating = + (float *)malloc(cooling->N_Redshifts * cooling->N_He * cooling->N_Temp * + cooling->N_nH * sizeof(float)); + cooling_table.H_plus_He_electron_abundance = + (float *)malloc(cooling->N_Redshifts * cooling->N_He * cooling->N_Temp * + cooling->N_nH * sizeof(float)); + + // repeat for both tables we need to read + for (int file = 0; file < 2; file++) { + if (file == 0) { + sprintf(fname, "%s%s.hdf5", cooling_table_path, filename1); + } else { + sprintf(fname, "%s%s.hdf5", cooling_table_path, filename2); + } + file_id = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); + + if (file_id < 0) { + error("[GetCoolingTables()]: unable to open file %s\n", fname); + } + + // read in cooling rates due to metals + for (specs = 0; specs < cooling->N_Elements; specs++) { + sprintf(set_name, "/%s/Net_Cooling", cooling->ElementNames[specs]); + dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); + status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + net_cooling_rate); + status = H5Dclose(dataset); + + for (i = 0; i < cooling->N_nH; i++) { + for (j = 0; j < cooling->N_Temp; j++) { + table_index = + row_major_index_2d(j, i, cooling->N_Temp, cooling->N_nH); + cooling_index = row_major_index_4d( + file, i, j, specs, cooling->N_Redshifts, + cooling->N_nH, cooling->N_Temp, cooling->N_Elements); + cooling_table.metal_heating[cooling_index] = + -net_cooling_rate[table_index]; + } + } + } + + // read in cooling rates due to hydrogen and helium, H + He electron abundances, + // temperatures + sprintf(set_name, "/Metal_free/Net_Cooling"); + dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); + status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + he_net_cooling_rate); + status = H5Dclose(dataset); + + sprintf(set_name, "/Metal_free/Temperature/Temperature"); + dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); + status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + temperature); + status = H5Dclose(dataset); + + sprintf(set_name, "/Metal_free/Electron_density_over_n_h"); + dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); + status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + he_electron_abundance); + status = H5Dclose(dataset); + + for (i = 0; i < cooling->N_He; i++) { + for (j = 0; j < cooling->N_Temp; j++) { + for (k = 0; k < cooling->N_nH; k++) { + table_index = row_major_index_3d(i, j, k, cooling->N_He, + cooling->N_Temp, cooling->N_nH); + cooling_index = + row_major_index_4d(file, k, i, j, cooling->N_Redshifts, + cooling->N_nH, cooling->N_He, cooling->N_Temp); + cooling_table.H_plus_He_heating[cooling_index] = + -he_net_cooling_rate[table_index]; + cooling_table.H_plus_He_electron_abundance[cooling_index] = + he_electron_abundance[table_index]; + cooling_table.temperature[cooling_index] = + log10(temperature[table_index]); + } + } + } + + // read in electron densities due to metals + sprintf(set_name, "/Solar/Electron_density_over_n_h"); + dataset = H5Dopen(file_id, set_name, H5P_DEFAULT); + status = H5Dread(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + electron_abundance); + status = H5Dclose(dataset); + + for (i = 0; i < cooling->N_Temp; i++) { + for (j = 0; j < cooling->N_nH; j++) { + table_index = row_major_index_2d(i, j, cooling->N_Temp, cooling->N_nH); + cooling_index = row_major_index_3d(file, j, i, cooling->N_Redshifts, + cooling->N_nH, cooling->N_Temp); + cooling_table.electron_abundance[cooling_index] = + electron_abundance[table_index]; + } + } + + status = H5Fclose(file_id); + } + + free(net_cooling_rate); + free(electron_abundance); + free(temperature); + free(he_net_cooling_rate); + free(he_electron_abundance); + + printf("eagle_cool_tables.h done reading in general cooling table\n"); + + return cooling_table; +} + +/* + * @brief Work in progress: constructs the data structure containting cooling tables + * bracketing the redshift of a particle. + * + * @param cooling_table_path Directory containing cooling table + * @param cooling Cooling data structure + */ +void eagle_read_two_tables( + struct cooling_function_data *restrict cooling) { + + struct eagle_cooling_table table; + + table.element_cooling = get_cooling_table(cooling->cooling_table_path, cooling); + cooling->table = table; +} + + #endif diff --git a/src/cooling/EAGLE/interpolate.c b/src/cooling/EAGLE/interpolate.c index 1248f6c2881ea1b891822bf86fb5d2a578e6e04d..5bba67cbcb9cfe242efff42ce3026b97f0ae2cee 100644 --- a/src/cooling/EAGLE/interpolate.c +++ b/src/cooling/EAGLE/interpolate.c @@ -57,12 +57,7 @@ const float EPS = 1.e-4; */ __attribute__((always_inline)) INLINE int row_major_index_2d(int i, int j, int nx, int ny) { - int index = i * ny + j; -#ifdef SWIFT_DEBUG_CHECKS - assert(i < nx); - assert(j < ny); -#endif - return index; + return i * ny + j; } /** @@ -75,13 +70,7 @@ __attribute__((always_inline)) INLINE int row_major_index_2d(int i, int j, __attribute__((always_inline)) INLINE int row_major_index_3d(int i, int j, int k, int nx, int ny, int nz) { - int index = i * ny * nz + j * nz + k; -#ifdef SWIFT_DEBUG_CHECKS - assert(i < nx); - assert(j < ny); - assert(k < nz); -#endif - return index; + return i * ny * nz + j * nz + k; } /** @@ -95,14 +84,7 @@ __attribute__((always_inline)) INLINE int row_major_index_4d(int i, int j, int k, int l, int nx, int ny, int nz, int nw) { - int index = i * ny * nz * nw + j * nz * nw + k * nw + l; -#ifdef SWIFT_DEBUG_CHECKS - assert(i < nx); - assert(j < ny); - assert(k < nz); - assert(l < nw); -#endif - return index; + return i * ny * nz * nw + j * nz * nw + k * nw + l; } /* @@ -143,7 +125,7 @@ __attribute__((always_inline)) INLINE void get_index_1d(float *table, * * @param z Redshift whose position within the redshift array we are interested * in - * @param z_index i Pointer to the index whose corresponding redshift + * @param z_index Pointer to the index whose corresponding redshift * is the greatest value in the redshift table less than x * @param dz Pointer to offset of z within redshift cell * @param cooling Pointer to cooling structure containing redshift table @@ -229,6 +211,10 @@ __attribute__((always_inline)) INLINE double interpol_1d_dbl(double *table, * @param i,j Indices of cell we are interpolating * @param dx,dy Offset within cell * @param nx,ny Table dimensions + * @param upper Pointer to value set to the table value at + * the when dy = 1 (used for calculating derivatives) + * @param lower Pointer to value set to the table value at + * the when dy = 0 (used for calculating derivatives) */ __attribute__((always_inline)) INLINE float interpol_2d(float *table, int i, int j, float dx, @@ -268,6 +254,10 @@ __attribute__((always_inline)) INLINE float interpol_2d(float *table, int i, * @param i,j Indices of cell we are interpolating * @param dx,dy Offset within cell * @param nx,ny Table dimensions + * @param upper Pointer to value set to the table value at + * the when dy = 1 (used for calculating derivatives) + * @param lower Pointer to value set to the table value at + * the when dy = 0 (used for calculating derivatives) */ __attribute__((always_inline)) INLINE double interpol_2d_dbl( double *table, int i, int j, double dx, double dy, int nx, int ny, @@ -305,6 +295,10 @@ __attribute__((always_inline)) INLINE double interpol_2d_dbl( * @param i,j,k Indices of cell we are interpolating * @param dx,dy,dz Offset within cell * @param nx,ny,nz Table dimensions + * @param upper Pointer to value set to the table value at + * the when dz = 1 (used for calculating derivatives) + * @param lower Pointer to value set to the table value at + * the when dz = 0 (used for calculating derivatives) */ __attribute__((always_inline)) INLINE float interpol_3d(float *table, int i, int j, int k, float dx, @@ -370,6 +364,14 @@ __attribute__((always_inline)) INLINE float interpol_3d(float *table, int i, * @param i,j,k,l Indices of cell we are interpolating * @param dx,dy,dz,dw Offset within cell * @param nx,ny,nz,nw Table dimensions + * @param upper Pointer to value set to the table value at + * the when dw = 1 when used for interpolating table + * depending on metal species, dz = 1 otherwise + * (used for calculating derivatives) + * @param upper Pointer to value set to the table value at + * the when dw = 0 when used for interpolating table + * depending on metal species, dz = 0 otherwise + * (used for calculating derivatives) */ __attribute__((always_inline)) INLINE float interpol_4d( float *table, int i, int j, int k, int l, float dx, float dy, float dz, @@ -428,6 +430,7 @@ __attribute__((always_inline)) INLINE float interpol_4d( dx * dy * dz * (1 - dw) * table14 + dx * dy * dz * dw * table15; if (nw == 9) { + // interpolating metal species dz = 1.0; } else { dw = 1.0; @@ -449,6 +452,7 @@ __attribute__((always_inline)) INLINE float interpol_4d( dx * dy * dz * (1 - dw) * table14 + dx * dy * dz * dw * table15; if (nw == 9) { + // interpolating metal species dz = 0.0; } else { dw = 0.0; @@ -475,7 +479,8 @@ __attribute__((always_inline)) INLINE float interpol_4d( /* * @brief Interpolates 2d EAGLE table over one of the dimensions, - * producing 1d table + * producing 1d table. May be useful if need to use bisection + * method often with lots of iterations. * * @param p Particle structure * @param cooling Cooling data structure @@ -635,14 +640,6 @@ construct_1d_print_table_from_3d_elements( result_table[i + array_size*j] += ((1 - d_x) * table[index[0]] + d_x * table[index[1]])*abundance_ratio[j+2]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 3 i partial sums %d %.5e %.5e %.5e \n", - i, result_table[i], (1 - d_x) * table[index[0]], - (1 - d_x) * table[index[0]] + - d_x * table[index[1]]); -#endif } } } @@ -701,14 +698,6 @@ construct_1d_table_from_3d_elements( result_table[i] += ((1 - d_x) * table[index[0]] + d_x * table[index[1]])*abundance_ratio[j+2]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 3 i partial sums %d %.5e %.5e %.5e \n", - i, result_table[i], (1 - d_x) * table[index[0]], - (1 - d_x) * table[index[0]] + - d_x * table[index[1]]); -#endif } } } @@ -788,15 +777,6 @@ __attribute__((always_inline)) INLINE void construct_1d_table_from_4d( d_x * (1 - d_y) * d_w * table[index[5]] + d_x * d_y * (1 - d_w) * table[index[6]] + d_x * d_y * d_w * table[index[7]]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 2 i dz dnh dHe table values %d %.5e %.5e %.5e %.5e " - "%.5e %.5e %.5e %.5e %.5e %.5e %.5e \n", - i, d_x, d_y, d_w, table[index[0]], table[index[1]], - table[index[2]], table[index[3]], table[index[4]], table[index[5]], - table[index[6]], table[index[7]]); -#endif } } @@ -861,21 +841,6 @@ construct_1d_print_table_from_4d_elements( (1 - d_x) * d_y * table[index[1]] + d_x * (1 - d_y) * table[index[2]] + d_x * d_y * table[index[3]]) * abundance_ratio[j+2]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 3 i partial sums %d %.5e %.5e %.5e %.5e %.5e \n", - i, result_table[i], (1 - d_x) * (1 - d_y) * table[index[0]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]] + - d_x * d_y * table[index[3]]); -#endif } } } @@ -940,21 +905,6 @@ construct_1d_table_from_4d_elements( (1 - d_x) * d_y * table[index[1]] + d_x * (1 - d_y) * table[index[2]] + d_x * d_y * table[index[3]]) * abundance_ratio[j+2]; -#if SWIFT_DEBUG_CHECKS - if (isnan(result_table[i])) - printf( - "Eagle cooling.h 3 i partial sums %d %.5e %.5e %.5e %.5e %.5e \n", - i, result_table[i], (1 - d_x) * (1 - d_y) * table[index[0]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]], - (1 - d_x) * (1 - d_y) * table[index[0]] + - (1 - d_x) * d_y * table[index[1]] + - d_x * (1 - d_y) * table[index[2]] + - d_x * d_y * table[index[3]]); -#endif } } } @@ -996,20 +946,16 @@ eagle_convert_temp_to_u_1d_table(double temp, float *temperature_table, * @param d_z Redshift offset * @param d_n_h Hydrogen number density offset * @param d_He Helium fraction offset - * @param p Particle data structure * @param cooling Cooling data structure * @param cosmo Cosmology data structure - * @param internal_const Physical constants data structure */ __attribute__((always_inline)) INLINE double eagle_convert_u_to_temp( double log_10_u, float *delta_u, int z_i, int n_h_i, int He_i, float d_z, float d_n_h, float d_He, - const struct part *restrict p, const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const) { + const struct cosmology *restrict cosmo) { int u_i; float d_u, logT; @@ -1044,18 +990,12 @@ eagle_convert_u_to_temp( * @param log_10_u Log base 10 of internal energy * @param delta_u Pointer to size of internal energy cell * @param temperature_table 1d array of temperatures - * @param p Particle data structure * @param cooling Cooling data structure - * @param cosmo Cosmology data structure - * @param internal_const Physical constants data structure */ __attribute__((always_inline)) INLINE double eagle_convert_u_to_temp_1d_table( double log_10_u, float *delta_u, double *temperature_table, - const struct part *restrict p, - const struct cooling_function_data *restrict cooling, - const struct cosmology *restrict cosmo, - const struct phys_const *internal_const) { + const struct cooling_function_data *restrict cooling) { int u_i; float d_u, logT; @@ -1080,7 +1020,6 @@ eagle_convert_u_to_temp_1d_table( * @param He_i Helium fraction index * @param d_He Helium fraction offset * @param phys_const Physical constants data structure - * @param us Units data structure * @param cosmo Cosmology data structure * @param cooling Cooling data structure * @param p Particle data structure @@ -1110,7 +1049,6 @@ __attribute__((always_inline)) INLINE void construct_1d_tables( int z_index, float dz, int n_h_i, float d_n_h, int He_i, float d_He, const struct phys_const *restrict phys_const, - const struct unit_system *restrict us, const struct cosmology *restrict cosmo, const struct cooling_function_data *restrict cooling, const struct part *restrict p, diff --git a/src/cooling/EAGLE/interpolate.h b/src/cooling/EAGLE/interpolate.h index 4d317bc668769b94aa255c08fbedc517a0a6230b..0392f234a601c9092bc32d6b8f6ee8e8ef735cd6 100644 --- a/src/cooling/EAGLE/interpolate.h +++ b/src/cooling/EAGLE/interpolate.h @@ -128,24 +128,18 @@ eagle_convert_u_to_temp( double, float *, int, int, int, float, float, float, - const struct part *restrict, const struct cooling_function_data *restrict, - const struct cosmology *restrict, - const struct phys_const *); + const struct cosmology *restrict); double eagle_convert_u_to_temp_1d_table( double, float *, double *, - const struct part *restrict, - const struct cooling_function_data *restrict, - const struct cosmology *restrict, - const struct phys_const *); + const struct cooling_function_data *restrict); void construct_1d_tables( int, float, int, float, int, float, const struct phys_const *restrict, - const struct unit_system *restrict, const struct cosmology *restrict, const struct cooling_function_data *restrict, const struct part *restrict, diff --git a/src/engine.h b/src/engine.h index 2a5a58793620e765755156d9cbcbed211312b2a1..18045d2e0c4df906e300304b4efa3833e160ec93 100644 --- a/src/engine.h +++ b/src/engine.h @@ -50,12 +50,6 @@ #include "task.h" #include "units.h" -// cooling counters -int n_eagle_cooling_rate_calls_1; -int n_eagle_cooling_rate_calls_2; -int n_eagle_cooling_rate_calls_3; -int n_eagle_cooling_rate_calls_4; - /** * @brief The different policies the #engine can follow. */