def test_proper_units(): """ Make sure two different proper units systems give the same answer. """ grackle_dir = os.path.dirname( os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) data_file_path = bytearray( os.sep.join([grackle_dir, "input", "CloudyData_UVB=HM2012.h5"]), 'utf-8') my_random_state = np.random.RandomState(20150725) for current_redshift in [0., 1., 3.]: # proper units chem_1 = chemistry_data() chem_1.use_grackle = 1 chem_1.with_radiative_cooling = 0 chem_1.primordial_chemistry = 1 chem_1.metal_cooling = 1 chem_1.UVbackground = 1 chem_1.grackle_data_file = data_file_path chem_1.comoving_coordinates = 0 chem_1.a_units = 1.0 chem_1.a_value = 1.0 / (1.0 + current_redshift) / chem_1.a_units chem_1.density_units = random_logscale(-1, 1, random_state=my_random_state) chem_1.length_units = random_logscale(0, 2, random_state=my_random_state) chem_1.time_units = random_logscale(0, 2, random_state=my_random_state) chem_1.velocity_units = chem_1.length_units / chem_1.time_units fc_1 = setup_fluid_container(chem_1, converge=False) fc_1.calculate_temperature() fc_1.calculate_cooling_time() t_sort_1 = np.argsort(fc_1["temperature"]) t_cool_1 = fc_1["cooling_time"][t_sort_1] * chem_1.time_units # proper units chem_2 = chemistry_data() chem_2.use_grackle = 1 chem_2.with_radiative_cooling = 0 chem_2.primordial_chemistry = 1 chem_2.metal_cooling = 1 chem_2.UVbackground = 1 chem_2.grackle_data_file = data_file_path chem_2.comoving_coordinates = 0 chem_2.a_units = 1.0 chem_2.a_value = 1.0 / (1.0 + current_redshift) / chem_2.a_units chem_2.density_units = random_logscale(-28, -26, random_state=my_random_state) chem_2.length_units = random_logscale(0, 2, random_state=my_random_state) chem_2.time_units = random_logscale(0, 2, random_state=my_random_state) chem_2.velocity_units = chem_2.length_units / chem_2.time_units fc_2 = setup_fluid_container(chem_2, converge=False) fc_2.calculate_temperature() fc_2.calculate_cooling_time() t_sort_2 = np.argsort(fc_2["temperature"]) t_cool_2 = fc_2["cooling_time"][t_sort_2] * chem_2.time_units comp = "\nDU1: %e, LU1: %e, TU1: %e - DU2: %e, LU2: %e, TU2L %e." % \ (chem_1.density_units, chem_1.length_units, chem_1.time_units, chem_2.density_units, chem_2.length_units, chem_2.time_units) assert_rel_equal( t_cool_1, t_cool_2, 4, (("Different proper unit system cooling times disagree for " + "z = %f with min/max = %f/%f.") % (current_redshift, (t_cool_1 / t_cool_2).min(), (t_cool_1 / t_cool_2).max()) + comp))
def test_proper_comoving_units_tabular(): """ Make sure proper and comoving units systems give the same answer with tabular cooling. """ grackle_dir = os.path.dirname( os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) data_file_path = bytearray( os.sep.join([grackle_dir, "input", "CloudyData_UVB=HM2012.h5"]), 'utf-8') my_random_state = np.random.RandomState(19650909) for current_redshift in [0., 1., 3., 6., 9.]: # comoving units chem_c = chemistry_data() chem_c.use_grackle = 1 chem_c.with_radiative_cooling = 0 chem_c.primordial_chemistry = 0 chem_c.metal_cooling = 1 chem_c.UVbackground = 1 chem_c.grackle_data_file = data_file_path set_cosmology_units(chem_c, current_redshift=current_redshift, initial_redshift=99.) fc_c = setup_fluid_container(chem_c, converge=False) fc_c.calculate_temperature() fc_c.calculate_cooling_time() t_sort_c = np.argsort(fc_c["temperature"]) t_cool_c = fc_c["cooling_time"][t_sort_c] * chem_c.time_units # proper units chem_p = chemistry_data() chem_p.use_grackle = 1 chem_p.with_radiative_cooling = 0 chem_p.primordial_chemistry = 0 chem_p.metal_cooling = 1 chem_p.UVbackground = 1 chem_p.grackle_data_file = data_file_path chem_p.comoving_coordinates = 0 chem_p.a_units = 1.0 chem_p.a_value = 1.0 / (1.0 + current_redshift) / chem_p.a_units # Set the proper units to be of similar magnitude to the # comoving system to help the solver be more efficient. chem_p.density_units = random_logscale(-2, 2, random_state=my_random_state) * \ chem_c.density_units / (1 + current_redshift)**3 chem_p.length_units = random_logscale(-2, 2, random_state=my_random_state) * \ chem_c.length_units * (1 + current_redshift) chem_p.time_units = random_logscale(-2, 2, random_state=my_random_state) * \ chem_c.time_units chem_p.velocity_units = chem_p.length_units / chem_p.time_units fc_p = setup_fluid_container(chem_p, converge=False) fc_p.calculate_temperature() fc_p.calculate_cooling_time() t_sort_p = np.argsort(fc_p["temperature"]) t_cool_p = fc_p["cooling_time"][t_sort_p] * chem_p.time_units comp = "\nDU1: %e, LU1: %e, TU1: %e - DU2: %e, LU2: %e, TU2L %e." % \ (chem_p.density_units, chem_p.length_units, chem_p.time_units, chem_c.density_units, chem_c.length_units, chem_c.time_units) assert_rel_equal( t_cool_p, t_cool_c, 4, (("Proper and comoving tabular cooling times disagree for " + "z = %f with min/max = %f/%f.\n") % (current_redshift, (t_cool_p / t_cool_c).min(), (t_cool_p / t_cool_c).max()) + comp))
def test_equilibrium(): """ Test ionization equilibrium for a primordial gas against the analytical solution using the same rates. This test takes a long time because the iteration to convergence near T = 1e4 K is slow. """ my_chem = chemistry_data() my_chem.use_grackle = 1 my_chem.with_radiative_cooling = 0 my_chem.primordial_chemistry = 1 my_chem.metal_cooling = 0 my_chem.UVbackground = 0 my_chem.comoving_coordinates = 0 my_chem.a_units = 1.0 my_chem.a_value = 1.0 my_chem.density_units = mass_hydrogen_cgs my_chem.length_units = 1.0 my_chem.time_units = 1.0 my_chem.velocity_units = my_chem.length_units / my_chem.time_units fc = setup_fluid_container(my_chem, temperature=np.logspace(4.5, 9, 200), converge=True, tolerance=1e-6, max_iterations=np.inf) fc.calculate_temperature() fc.calculate_cooling_time() t_sort = np.argsort(fc["temperature"]) t_cool = fc["cooling_time"][t_sort] * my_chem.time_units my_T = fc["temperature"][t_sort] my_nH = fc.calculate_hydrogen_number_density().mean() cooling_rate_eq = -1 * total_cooling(my_T, my_nH) / my_nH**2 cooling_rate_g = fc["energy"][t_sort] / t_cool * fc["density"] * \ my_chem.density_units / my_nH**2 # Make a cooling rate figure fontsize = 14 axes = pyplot.axes() axes.loglog(my_T, -1 * cooling_rate_eq, color='black', alpha=0.7, linestyle="--", linewidth=1.5) axes.loglog(my_T, -1 * cooling_rate_g, color='black', alpha=0.7, linestyle="-", linewidth=1) axes.xaxis.set_label_text('T [K]', fontsize=fontsize) axes.yaxis.set_label_text( r'$-\Lambda$ / n${_{\rm H}}^{2}$ [erg s$^{-1}$ cm$^{3}$]', fontsize=fontsize) axes.set_xlim(1e4, 1e9) axes.set_ylim(1e-26, 2e-22) tick_labels = axes.xaxis.get_ticklabels() + \ axes.yaxis.get_ticklabels() for tick_label in tick_labels: tick_label.set_size(fontsize) pyplot.savefig('cooling.png') pyplot.clf() # Make an ionization balance figure nH_eq = nHI(my_T, my_nH) + nHII(my_T, my_nH) nH_g = fc["HI"] + fc["HII"] fHI_eq = nHI(my_T, my_nH) / nH_eq fHI_g = fc["HI"] / nH_g fHII_eq = nHII(my_T, my_nH) / nH_eq fHII_g = fc["HII"] / nH_g nHe_eq = nHeI(my_T, my_nH) + nHeII(my_T, my_nH) + nHeIII(my_T, my_nH) nHe_g = fc["HeI"] + fc["HeII"] + fc["HeIII"] fHeI_eq = nHeI(my_T, my_nH) / nHe_eq fHeI_g = fc["HeI"] / nHe_g fHeII_eq = nHeII(my_T, my_nH) / nHe_eq fHeII_g = fc["HeII"] / nHe_g fHeIII_eq = nHeIII(my_T, my_nH) / nHe_eq fHeIII_g = fc["HeIII"] / nHe_g # Plot H ions axes = pyplot.axes() axes.loglog(my_T, fHI_eq, color="#B82E00", alpha=0.7, linestyle="--", linewidth=1.5) axes.loglog(my_T, fHII_eq, color="#B88A00", alpha=0.7, linestyle="--", linewidth=1.5) axes.loglog(my_T, fHI_g, label="HI", color="#B82E00", alpha=0.7, linestyle="-", linewidth=1.) axes.loglog(my_T, fHII_g, label="HII", color="#B88A00", alpha=0.7, linestyle="-", linewidth=1.) # Plot He ions axes.loglog(my_T, fHeI_eq, color="#002EB8", alpha=0.7, linestyle="--", linewidth=1.5) axes.loglog(my_T, fHeII_eq, color="#008AB8", alpha=0.7, linestyle="--", linewidth=1.5) axes.loglog(my_T, fHeIII_eq, color="#00B88A", alpha=0.7, linestyle="--", linewidth=1.5) axes.loglog(my_T, fHeI_g, label="HeI", color="#002EB8", alpha=0.7, linestyle="-", linewidth=1.) axes.loglog(my_T, fHeII_g, label="HeII", color="#008AB8", alpha=0.7, linestyle="-", linewidth=1.) axes.loglog(my_T, fHeIII_g, label="HeIII", color="#00B88A", alpha=0.7, linestyle="-", linewidth=1.) axes.xaxis.set_label_text('T [K]', fontsize=fontsize) axes.yaxis.set_label_text('fraction', fontsize=fontsize) axes.set_xlim(1e4, 1e9) axes.set_ylim(1e-10, 1) tick_labels = axes.xaxis.get_ticklabels() + \ axes.yaxis.get_ticklabels() for tick_label in tick_labels: tick_label.set_size(fontsize) axes.legend(loc='best', prop=dict(size=fontsize)) pyplot.savefig('fractions.png') test_precision = 1 # test the cooling rates cool_ratio = cooling_rate_eq / cooling_rate_g assert_rel_equal( cooling_rate_eq, cooling_rate_g, test_precision, "Equilibrium cooling rates disagree with min/max = %f/%f." % (cool_ratio.min(), cool_ratio.max())) # test the ionization balance assert_rel_equal( fHI_eq, fHI_g, test_precision, "HI fractions disagree with min/max = %f/%f." % ((fHI_eq / fHI_g).min(), (fHI_eq / fHI_g).max())) assert_rel_equal( fHII_eq, fHII_g, test_precision, "HII fractions disagree with min/max = %f/%f." % ((fHII_eq / fHII_g).min(), (fHII_eq / fHII_g).max())) assert_rel_equal( fHeI_eq, fHeI_g, test_precision, "HeI fractions disagree with min/max = %f/%f." % ((fHeI_eq / fHeI_g).min(), (fHeI_eq / fHeI_g).max())) assert_rel_equal( fHeII_eq, fHeII_g, test_precision, "HeII fractions disagree with min/max = %f/%f." % ((fHeII_eq / fHeII_g).min(), (fHeII_eq / fHeII_g).max())) assert_rel_equal( fHeIII_eq, fHeIII_g, test_precision, "HeIII fractions disagree with min/max = %f/%f." % ((fHeIII_eq / fHeIII_g).min(), (fHeIII_eq / fHeIII_g).max()))