def optical_depth(self, use_recomb=True, store=True): """Calculate Thompson electron scattering optical depth.""" # First calculate the optical depth from the fully-ionized # epoch up to our minimum redshift. tau_z0 = cr.optical_depth_instant(self.z[-1], **self.cosmo) # Then the contribution from the partially-ionized epoch. if use_recomb: xPhys = self.xr.copy() else: xPhys = self.xEsc.copy() xPhys[xPhys > 1.0] = 1.0 tau_later = (tau_z0 + cr.integrate_optical_depth(xPhys[...,::-1], xPhys[...,::-1], self.z[::-1], **self.cosmo)) tau = tau_later[...,::-1] if store: if use_recomb: self.tau = tau else: self.tauEsc = tau return tau
def test_GBL_tau_inst(): """Test match between analytical and numerical tau with instant reionization. Also makes a plot reproducing figure 1 of arXiv:astro-ph/9812125v3. """ dz = 0.05 z = numpy.arange(0., 80. + 1.5 * dz, dz) # Fully ionized H and He x_ionH = 1.0 x_ionHe = 2.0 cosmo = {} cosmo['omega_M_0'] = numpy.array([[0.3], [0.6], [1.0]]) cosmo['omega_lambda_0'] = 1. - cosmo['omega_M_0'] cosmo['h'] = 0.65 cosmo['omega_b_0'] = 0.02 / cosmo['h']**2. cosmo['Y_He'] = 0.24 cd.set_omega_k_0(cosmo) tau_inst = cr.optical_depth_instant(z, x_ionH=x_ionH, x_ionHe=x_ionHe, **cosmo) tau_int = cr.integrate_optical_depth(x_ionH, x_ionHe, z, **cosmo) linestyle = ['-', ':', '--'] pylab.figure() pylab.subplot(2, 1, 1) pylab.title("Compare to GB&L fig. 1 (astro-ph/9812125v3.)") for i in range(len(linestyle)): pylab.plot(z, tau_inst[i], ls=linestyle[i], color='b') pylab.plot(z, tau_int[i], ls=linestyle[i], color='r') pylab.xlim(0, 80) pylab.ylim(0, 1) pylab.xlabel(r"$\mathrm{z_{ion}}$") pylab.ylabel(r"$\tau$") pylab.subplot(2, 1, 2) for i in range(len(linestyle)): pylab.plot(z, 1.e4 * (tau_int[i] - tau_inst[i]) / tau_inst[i], ls=linestyle[i], color='k') diff = (tau_int[i] - tau_inst[i]) / tau_inst[i] diff[numpy.isnan(diff)] = 0.0 print("max fractional error in num. int. = %.3g" % numpy.max(numpy.abs(diff))) ntest.assert_array_less(numpy.abs(diff), numpy.zeros(diff.shape) + 2.e-4) pylab.xlim(0, 40) pylab.xlabel(r"$\mathrm{z_{ion}}$") pylab.ylabel(r"$\mathrm{10^4 \times (num.\tau - ana.\tau)/ana.\tau}$")
def test_GBL_tau_inst(): """Test match between analytical and numerical tau with instant reionization. Also makes a plot reproducing figure 1 of arXiv:astro-ph/9812125v3. """ dz = 0.05 z = numpy.arange(0., 80. + 1.5*dz, dz) # Fully ionized H and He x_ionH = 1.0 x_ionHe = 2.0 cosmo = {} cosmo['omega_M_0'] = numpy.array([[0.3],[0.6],[1.0]]) cosmo['omega_lambda_0'] = 1. - cosmo['omega_M_0'] cosmo['h'] = 0.65 cosmo['omega_b_0'] = 0.02 / cosmo['h']**2. cosmo['Y_He'] = 0.24 cd.set_omega_k_0(cosmo) tau_inst = cr.optical_depth_instant(z, x_ionH=x_ionH, x_ionHe=x_ionHe, **cosmo) tau_int = cr.integrate_optical_depth(x_ionH, x_ionHe, z, **cosmo) linestyle = ['-', ':', '--'] pylab.figure() pylab.subplot(2,1,1) pylab.title("Compare to GB&L fig. 1 (astro-ph/9812125v3.)") for i in range(len(linestyle)): pylab.plot(z, tau_inst[i], ls=linestyle[i], color='b') pylab.plot(z, tau_int[i], ls=linestyle[i], color='r') pylab.xlim(0,80) pylab.ylim(0,1) pylab.xlabel(r"$\mathrm{z_{ion}}$") pylab.ylabel(r"$\tau$") pylab.subplot(2,1,2) for i in range(len(linestyle)): pylab.plot(z, 1.e4 * (tau_int[i] - tau_inst[i])/tau_inst[i], ls=linestyle[i], color='k') diff = (tau_int[i] - tau_inst[i]) / tau_inst[i] diff[numpy.isnan(diff)] = 0.0 print ("max fractional error in num. int. = %.3g" % numpy.max(numpy.abs(diff)) ) ntest.assert_array_less(numpy.abs(diff), numpy.zeros(diff.shape) + 2.e-4) pylab.xlim(0,40) pylab.xlabel(r"$\mathrm{z_{ion}}$") pylab.ylabel(r"$\mathrm{10^4 \times (num.\tau - ana.\tau)/ana.\tau}$")
def test_tau_instant(): """Check the optical depth we get using the WMAP z_reion. """ dz = 0.1 z = numpy.arange(80., 0. - 1.5 * dz, -1. * dz) # Can't match WMAP7 optical depths exactly. Need to look into new # treatment in CAMB as mentioned in the WMAP7 paper (see # parameters.py). cosmos = [ cparam.WMAP7_BAO_H0_mean(flat=True), cparam.WMAP7_ML(flat=True), cparam.WMAP5_BAO_SN_mean(flat=True), cparam.WMAP5_ML(flat=True), cparam.WMAP5_mean(flat=True) ] # The WMAP5 numbers apparently assume He is neutral, while WMAP7 # includes simultaneous singly ionized He plus Helium (double) # reionization at z=3.5. x_ionHe_list = [1.0, 1.0, 0, 0, 0] z_rHe_list = [3.5, 3.5, None, None, None] #[3.5, None, None, None] for cosmo in cosmos: # Fully ionized H x_ionH = 1.0 # He ionization with H? x_ionHe = x_ionHe_list.pop(0) # Redshift for Helium double reionization? z_rHe = z_rHe_list.pop(0) zr = cosmo['z_reion'] tau_zr = cosmo['tau'] tau_calc = cr.optical_depth_instant(zr, x_ionH=x_ionH, x_ionHe=x_ionHe, z_rHe=z_rHe, verbose=1, **cosmo) print "z_r = %f, testing tau:" % zr, print tu.fractional_diff_string(tau_zr, tau_calc, 3) ntest.assert_approx_equal(tau_calc, tau_zr, significant=2, err_msg="Optical depth doesn't match WMAP")
def test_GBL_tau_star(): """Test tau_* against GB&L astro-ph/9812125v3. tau_* is a quantity used in optical_depth_instant. """ z = 1.0 # Fully ionized H and He x_ionH = 1.0 x_ionHe = 2.0 cosmo = {} cosmo['omega_M_0'] = numpy.array([[0.3],[0.6],[1.0]]) cosmo['omega_lambda_0'] = 1. - cosmo['omega_M_0'] cosmo['h'] = 0.65 cosmo['omega_b_0'] = 0.02 / cosmo['h']**2. cosmo['Y_He'] = 0.24 cd.set_omega_k_0(cosmo) tau_inst, tau_star = cr.optical_depth_instant(z, x_ionH=x_ionH, x_ionHe=x_ionHe, return_tau_star=True, **cosmo) print "tau_star = %.7f" % tau_star print ("tau_star/(h Omega_b) = %.7f =? 0.061" % (tau_star / (cosmo['h'] * cosmo['omega_b_0']))) ntest.assert_approx_equal(tau_star / (cosmo['h'] * cosmo['omega_b_0']), 0.061, 2) print "(1 - Y_He/2) = %.3f =? 0.88" % (1. - (cosmo['Y_He']/2.)) ntest.assert_approx_equal((1. - (cosmo['Y_He']/2.)), 0.88, 7) H_0 = cc.H100_s * cosmo['h'] # s^-1 * Mpc s^-1 * Mpc^2 / Mpc^3 msun^-1 s^-2 / Msun -> tau_star_explicit = ((1. - (cosmo['Y_He']/2.)) * ((3. * H_0 * cosmo['omega_b_0'] * cc.c_light_Mpc_s * cc.sigma_T_Mpc) / (8. * math.pi * cc.G_const_Mpc_Msun_s * (cc.m_p_g/cc.M_sun_g)))) print "tau_star_explicit = %.7f =? tau_star" % tau_star_explicit ntest.assert_approx_equal(tau_star, tau_star_explicit, 3)
def test_tau_instant(): """Check the optical depth we get using the WMAP z_reion. """ dz = 0.1 z = numpy.arange(80., 0. - 1.5 * dz, -1. * dz) # Can't match WMAP7 optical depths exactly. Need to look into new # treatment in CAMB as mentioned in the WMAP7 paper (see # parameters.py). cosmos = [cparam.WMAP7_BAO_H0_mean(flat=True), cparam.WMAP7_ML(flat=True), cparam.WMAP5_BAO_SN_mean(flat=True), cparam.WMAP5_ML(flat=True), cparam.WMAP5_mean(flat=True)] # The WMAP5 numbers apparently assume He is neutral, while WMAP7 # includes simultaneous singly ionized He plus Helium (double) # reionization at z=3.5. x_ionHe_list = [1.0, 1.0, 0, 0, 0] z_rHe_list = [3.5, 3.5, None, None, None] #[3.5, None, None, None] for cosmo in cosmos: # Fully ionized H x_ionH = 1.0 # He ionization with H? x_ionHe = x_ionHe_list.pop(0) # Redshift for Helium double reionization? z_rHe = z_rHe_list.pop(0) zr = cosmo['z_reion'] tau_zr = cosmo['tau'] tau_calc = cr.optical_depth_instant(zr, x_ionH=x_ionH, x_ionHe=x_ionHe, z_rHe=z_rHe, verbose = 1, **cosmo) print "z_r = %f, testing tau:" % zr, print tu.fractional_diff_string(tau_zr, tau_calc, 3) ntest.assert_approx_equal(tau_calc, tau_zr, significant=2, err_msg="Optical depth doesn't match WMAP")
def test_GBL_tau_star(): """Test tau_* against GB&L astro-ph/9812125v3. tau_* is a quantity used in optical_depth_instant. """ z = 1.0 # Fully ionized H and He x_ionH = 1.0 x_ionHe = 2.0 cosmo = {} cosmo['omega_M_0'] = numpy.array([[0.3], [0.6], [1.0]]) cosmo['omega_lambda_0'] = 1. - cosmo['omega_M_0'] cosmo['h'] = 0.65 cosmo['omega_b_0'] = 0.02 / cosmo['h']**2. cosmo['Y_He'] = 0.24 cd.set_omega_k_0(cosmo) tau_inst, tau_star = cr.optical_depth_instant(z, x_ionH=x_ionH, x_ionHe=x_ionHe, return_tau_star=True, **cosmo) print("tau_star = %.7f" % (tau_star)) print("tau_star/(h Omega_b) = %.7f =? 0.061" % (tau_star / (cosmo['h'] * cosmo['omega_b_0']))) ntest.assert_approx_equal(tau_star / (cosmo['h'] * cosmo['omega_b_0']), 0.061, 2) print("(1 - Y_He/2) = %.3f =? 0.88" % (1. - (cosmo['Y_He'] / 2.))) ntest.assert_approx_equal((1. - (cosmo['Y_He'] / 2.)), 0.88, 7) H_0 = cc.H100_s * cosmo['h'] # s^-1 * Mpc s^-1 * Mpc^2 / Mpc^3 msun^-1 s^-2 / Msun -> tau_star_explicit = ((1. - (cosmo['Y_He'] / 2.)) * ( (3. * H_0 * cosmo['omega_b_0'] * cc.c_light_Mpc_s * cc.sigma_T_Mpc) / (8. * math.pi * cc.G_const_Mpc_Msun_s * (cc.m_p_g / cc.M_sun_g)))) print("tau_star_explicit = %.7f =? tau_star" % (tau_star_explicit)) ntest.assert_approx_equal(tau_star, tau_star_explicit, 3)
def test_tau_BKP(): """Reionization consistency check with BK&P 2009MNRAS.397..971B Bagla J.~S., Kulkarni G., Padmanabhan T., 2009 (2009MNRAS.397..971B). Take their cannonical set of cosmological parameters and ionization coefficients and make sure I get the same optical depth value. The first figure demonstrates the calculation of the ionization fraction and the optical depth (not shown in the paper). The second figure shows dependence of the f_* f_esc,gamma values on tau (actually calculated the other way around, f_* f_esc,gamma -> tau). The plotted point (x) marks the value from the paper. The agreement between the calculated optical depth and the WMAP tau value is printed in the text output. """ N_gamma = 6804. # f_* f_esc N_gamma f_ion = numpy.transpose(numpy.atleast_2d(numpy.arange(10., 200., 10.))) alpha_B = 1e-13 # cm^3 s^-1 m_min = 1e8 # M_sun x_ionHe = 2.0 dz = 0.1 z = numpy.arange(20., 6. - 1.5 * dz, -1. * dz) #z = numpy.arange(6., 20. + 1.5 * dz, dz) cosmos = [cparam.WMAP5_ML(flat=True), cparam.WMAP5_mean(flat=True)] pylab.figure(figsize=(8,8)) colors=['r', 'k'] names = ["WMAP5 ML", "WMAP5 mean"] i = -1 for cosmo in cosmos: i += 1 print("\n%s" % (names[i])) # calculate ionized fraction, including recombinations x_rec, w_rec, t = cr.integrate_ion_recomb_collapse(z, f_ion, m_min, passed_min_mass=True, alpha_B=alpha_B, **cosmo) # calculate the optical depth in this scenario tau_z0 = cr.optical_depth_instant(z[-1], x_ionH=1.0, x_ionHe=2.0, **cosmo) tau_later = cr.integrate_optical_depth(x_rec, x_ionHe * x_rec, z, **cosmo) tau_0 = tau_later[:, -1] + tau_z0 tau = tau_later print("tau(WMAP) = %.3f" % (cosmo['tau'])) for j in range(len(f_ion.flat)): if round(f_ion[j],1) != 50.0: continue print("with f_* f_esc_gamma N_gamma = %.1f:" % (f_ion[j])) pylab.plot(z, x_rec[j], ls='-', color=colors[i]) pylab.plot(z, w_rec[j], ls=':', color=colors[i]) #pylab.plot(z, 10. * tau[j], ls='--', color=colors[i]) pylab.plot(z, 10. * (tau_0[j] - tau[j]), ls='--', color=colors[i]) pylab.axhline(y=10. * tau_0[j], ls='--', color=colors[i]) print("tau(z=0) = %.4f" % (tau_0[j])) print("fractional diff. = %.3g" % ((tau_0[j] - cosmo['tau']) / cosmo['tau'])) if i==1: # Make sure we recover the WMAP value. ntest.assert_approx_equal(tau_0[j], cosmo['tau'], 2) pylab.ylim(0,1.01) pylab.xlabel("redshift z") pylab.ylabel(r"ionized fraction or optical depth $\tau \times 10$") pylab.figure(figsize=(8,8)) pylab.plot(tau_0, f_ion / N_gamma, '-', color='k') pylab.plot([cosmo['tau']], [50.0 / N_gamma], 'x', color='b') pylab.xlim(0.06, 0.12) pylab.ylim(0., 0.022) pylab.xlabel(r'$\tau$') pylab.ylabel(r'$f_* f_{esc,\gamma}$')
def test_tau_BKP(): """Reionization consistency check with BK&P 2009MNRAS.397..971B Bagla J.~S., Kulkarni G., Padmanabhan T., 2009 (2009MNRAS.397..971B). Take their cannonical set of cosmological parameters and ionization coefficients and make sure I get the same optical depth value. The first figure demonstrates the calculation of the ionization fraction and the optical depth (not shown in the paper). The second figure shows dependence of the f_* f_esc,gamma values on tau (actually calculated the other way around, f_* f_esc,gamma -> tau). The plotted point (x) marks the value from the paper. The agreement between the calculated optical depth and the WMAP tau value is printed in the text output. """ N_gamma = 6804. # f_* f_esc N_gamma f_ion = numpy.transpose(numpy.atleast_2d(numpy.arange(10., 200., 10.))) alpha_B = 1e-13 # cm^3 s^-1 m_min = 1e8 # M_sun x_ionHe = 2.0 dz = 0.1 z = numpy.arange(20., 6. - 1.5 * dz, -1. * dz) #z = numpy.arange(6., 20. + 1.5 * dz, dz) cosmos = [cparam.WMAP5_ML(flat=True), cparam.WMAP5_mean(flat=True)] pylab.figure(figsize=(8,8)) colors=['r', 'k'] names = ["WMAP5 ML", "WMAP5 mean"] i = -1 for cosmo in cosmos: i += 1 print print names[i] # calculate ionized fraction, including recombinations x_rec, w_rec, t = cr.integrate_ion_recomb_collapse(z, f_ion, m_min, passed_min_mass=True, alpha_B=alpha_B, **cosmo) # calculate the optical depth in this scenario tau_z0 = cr.optical_depth_instant(z[-1], x_ionH=1.0, x_ionHe=2.0, **cosmo) tau_later = cr.integrate_optical_depth(x_rec, x_ionHe * x_rec, z, **cosmo) tau_0 = tau_later[:, -1] + tau_z0 tau = tau_later print "tau(WMAP) = %.3f" % cosmo['tau'] for j in range(len(f_ion.flat)): if round(f_ion[j],1) != 50.0: continue print "with f_* f_esc_gamma N_gamma = %.1f:" % f_ion[j] pylab.plot(z, x_rec[j], ls='-', color=colors[i]) pylab.plot(z, w_rec[j], ls=':', color=colors[i]) #pylab.plot(z, 10. * tau[j], ls='--', color=colors[i]) pylab.plot(z, 10. * (tau_0[j] - tau[j]), ls='--', color=colors[i]) pylab.axhline(y=10. * tau_0[j], ls='--', color=colors[i]) print "tau(z=0) = %.4f" % tau_0[j] print " fractional diff. = %.3g" % ((tau_0[j] - cosmo['tau']) / cosmo['tau']) if i==1: # Make sure we recover the WMAP value. ntest.assert_approx_equal(tau_0[j], cosmo['tau'], 2) pylab.ylim(0,1.01) pylab.xlabel("redshift z") pylab.ylabel(r"ionized fraction or optical depth $\tau \times 10$") pylab.figure(figsize=(8,8)) pylab.plot(tau_0, f_ion / N_gamma, '-', color='k') pylab.plot([cosmo['tau']], [50.0 / N_gamma], 'x', color='b') pylab.xlim(0.06, 0.12) pylab.ylim(0., 0.022) pylab.xlabel(r'$\tau$') pylab.ylabel(r'$f_* f_{esc,\gamma}$')