def scale_radius(conc, z_halo,Om=0.3, Ol=0.7, Or=0.0, A_200=5.71, B_200=-0.084, C_200=-0.47, h_scale=0.7): ''' purpose: compute the scale radius given the concentration parameter default parameters based on full profiles of Duffy et al. 2008 input: conc = concentration parameter at r200 z_halo = redshift of that halo Om, Ol, Or = cosmological paramters A200 = duffy et al parameter for concentration radius relationship B200 = " C200 = " h_scale = reduced hubble parameter output: scale radius in Mpc ''' #unit conversion values minMpc = 3.08568025*10**22 #m in a Megaparsec kginMsun = 1.988e30 #kg rho_cr = cosmo.rhoCrit(z_halo,h_scale,Om,Ol,Or) #in kg/m**3 #the h_scale is multiplied because the pivotal mass #m_pivotal = 2e12 is in unit of M_sun h_scale^(-1) m_200 = profiles.nfwM200(conc,z_halo, A_200,B_200,C_200,h_scale)*\ kginMsun r_200 = (m_200/(4*np.pi/3*200*rho_cr))**(1/3.) #in m r_s = r_200 / conc / minMpc return r_s
def nfwparam_extended(M_200, z, h_scale=0.7, Om=0.3, Ol=0.7, Or=0.0): ''' This is the same as nfwparam except that it offers extended output. Inputs: M_200 = [array of floats; units=e14 M_sun] Outputs: del_c, r_s = characteristic overdensity of the CDM halo, scale radius of the halo (Mpc) r_200 (Mpc) c = concentration rho_s (M_sun/Mpc^3) Assumes Duffy et al. 2008 M_200 vs. c relationship. ''' # calculate the concentration parameter based on Duffy et al. 2008 # for full samples profile A200 = 5.71 B200 = -0.084 C200 = -0.47 rho_cr = cosmo.rhoCrit(z, h_scale, Om, Ol, Or) / kginMsun * minMpc ** 3 # calculate the r_200 radius r_200 = (M_200 * 1e14 * 3 / (4 * numpy.pi * 200 * rho_cr)) ** (1 / 3.) c = A200 / (1 + z) ** numpy.abs(C200) * (M_200 * h_scale / 2e-2) ** (B200) #c = 5.71/(1+z)**0.47*(M_200*h_scale/2e12)**(-0.084) del_c = 200 / 3. * c ** 3 / (numpy.log(1 + c) - c / (1 + c)) r_s = r_200 / c rho_s = del_c * rho_cr return del_c, r_s, r_200, c, rho_s
def nfwparam(M_200, z, A200=5.71, B200=-0.084, C200=-0.47, h_scale=0.7, Om=0.3, Ol=0.7, Or=0.0, debug=False): ''' Inputs: M_200 = [array of floats; units=1e14 M_sun] Outputs: del_c, r_s = characteristic overdensity of the CDM halo, scale radius of the halo (Mpc) Assumes Duffy et al. 2008 M_200 vs. c relationship. ''' assert numpy.sum(M_200 < 5e2) / M_200.size, "M_200 has to be in units of \ 1e14 M_sun check your input M_200" # calculate the concentration parameter based on Duffy et al. 2008 # for full samples profile rho_cr = cosmo.rhoCrit(z, h_scale, Om, Ol, Or) / kginMsun * minMpc ** 3 # calculate the r_200 radius r_200 = (M_200 * 1e14 * 3 / (4 * numpy.pi * 200 * rho_cr)) ** (1 / 3.) # the h_scale is multiplied because the scaling relationship uses # 2e-2 h_scale^{-1} using 1e14 Msun as unit c = A200 * ((1 + z) ** C200) * (M_200 * h_scale / 2e-2) ** (B200) del_c = 200 / 3. * c ** 3 / (numpy.log(1 + c) - c / (1 + c)) r_s = r_200 / c if debug is True: print "c = {0}".format(c) print "r_200 = {0}".format(r_200) return del_c, r_s
def nfw_den(del_c, r_s, r, z, h=0.7, Om=0.3, Ol=0.7, Or=0): ''' NFW density at radius r [kg/m^3]. Note that this function accepts a single number or list for r. del_c = characteristic overdensity of the CDM halo r_s = scale radius of the halo r = radius of interest [same units as r_s] z = halo redshift ''' rho_crit = cosmo.rhoCrit(z, h, Om, Ol, Or) return rho_crit * del_c / (r / r_s * (1. + r / r_s) ** 2)
def NFWprop(M_200,z,c): ''' Determines the NFW halo related properties. Added this for the case of user specified concentration. Input: M_200 = [float; units:M_sun] mass of the halo. Assumes M_200 with respect to the critical density at the halo redshift. z = [float; unitless] redshift of the halo. c = [float; unitless] concentration of the NFW halo. ''' # CONSTANTS rho_cr = cosmo.rhoCrit(z)/kginMsun*minMpc**3 #calculate the r_200 radius r_200 = (M_200*3/(4*numpy.pi*200*rho_cr))**(1/3.) del_c = 200/3.*c**3/(numpy.log(1+c)-c/(1+c)) r_s = r_200/c rho_s = del_c*rho_cr return del_c, r_s, r_200, c, rho_s
def nfw_Sigmabar(del_c,r_s,r,z,h=0.7,Om=0.3,Ol=0.7,Or=0): ''' NFW average surface mass density within radius r [kg/m^2]. Note that this function accepts a single number or list for r. del_c = characteristic overdensity of the CDM halo r_s = scale radius of the halo [Mpc] r = radius of interest [Mpc] z = halo redshift compare expressions in Umetsu 2010 table 1 and equations in discussion on p.21 to get this expression ''' rho_crit = cosmo.rhoCrit(z,h,Om,Ol,Or) #convert r to an array so that the function will work for ints and arrays r = r*numpy.ones(numpy.shape(r)) x = r/r_s if numpy.sum(x==0)!=0 or r_s==0: print 'profiles.nfw_Sigmabar: r or r_s = 0 leads to infinity, exiting' sys.exit() mask_lt = x<1 mask_eq = x==1 mask_gt = x>1 g = numpy.zeros(numpy.shape(x)) #if x<1 if numpy.sum(mask_lt) !=0: g[mask_lt] = numpy.log(x[mask_lt]/2.)+\ 2/numpy.sqrt(1-x[mask_lt]**2)*\ numpy.arctanh(numpy.sqrt((1-x[mask_lt])/(1+x[mask_lt]))) #elif x==1 if numpy.sum(mask_eq) !=0: g[mask_eq] = numpy.log(x[mask_eq]/2.) + 1 #elif x > 1: if numpy.sum(mask_gt) !=0: g[mask_gt] = numpy.log(x[mask_gt]/2.)+\ 2/numpy.sqrt(x[mask_gt]**2-1)*\ numpy.arctan(numpy.sqrt((x[mask_gt]-1)/(x[mask_gt]+1.))) #if only single value of r was input then make the g array into a float if numpy.size(g) == 1: g = g[0] return 4*del_c*rho_crit*r_s*g/x**2*minMpc
def nfw_Sigma(del_c,r_s,r,z,h=0.7,Om=0.3,Ol=0.7,Or=0): ''' NFW surface mass density at radius theta [kg/m^2]. Note that this function accepts a single number or list for r. del_c = characteristic overdensity of the CDM halo r_s = scale radius of the halo (Mpc) r = radius of interest (Mpc) z = halo redshift compare expressions in Umetsu 2010 table 1 and equations in discussion on p.21 to get this expression ''' rho_crit = cosmo.rhoCrit(z,h,Om,Ol,Or) #convert r to an array so that the function will work for ints and arrays r = r*numpy.ones(numpy.shape(r)) x = r/r_s if numpy.sum(r_s==0)!=0: print 'profiles.nfw_Sigma: r_s = 0 leads to infinity, exiting' sys.exit() mask_lt = x<1 mask_eq = x==1 mask_gt = x>1 f = numpy.zeros(numpy.shape(x)) #if x<1 if numpy.sum(mask_lt) !=0: f[mask_lt] = 1/(1.-x[mask_lt]**2)*\ (-1+2/numpy.sqrt(1-x[mask_lt]**2)*\ numpy.arctanh(numpy.sqrt((1-x[mask_lt])/(1.+x[mask_lt])))) #elif x==1 if numpy.sum(mask_eq) !=0: f[mask_eq] = 1/3. #elif x > 1 if numpy.sum(mask_gt) !=0: f[mask_gt] = 1/(x[mask_gt]**2-1.)*\ (1-2/numpy.sqrt(x[mask_gt]**2-1)*\ numpy.arctan(numpy.sqrt((x[mask_gt]-1)/(x[mask_gt]+1.)))) #if only single value of r was input then make the f array into a float if numpy.size(f) == 1: f = f[0] return 2*del_c*rho_crit*r_s*f*minMpc
def nfwparam(M_200,z,h_scale=0.7,Om=0.3,Ol=0.7,Or=0.0): ''' Inputs: M_200 = [array of floats; units=1e14 M_sun] Outputs: del_c, r_s = characteristic overdensity of the CDM halo, scale radius of the halo (Mpc) Assumes Duffy et al. 2008 M_200 vs. c relationship. ''' #calculate the concentration parameter based on Duffy et al. 2008 #for full samples profile A200 = 5.71 B200 = -0.084 C200 = -0.47 rho_cr = cosmo.rhoCrit(z,h_scale,Om,Ol,Or)/kginMsun*minMpc**3 #calculate the r_200 radius r_200 = (M_200*1e14*3/(4*numpy.pi*200*rho_cr))**(1/3.) #the h_scale is multiplied because the scaling relationship uses # 2e-2 h_scale^{-1} using 1e14 Msun as unit c = A200/(1+z)**numpy.abs(C200)*(M_200*h_scale/2e-2)**(B200) del_c = 200/3.*c**3/(numpy.log(1+c)-c/(1+c)) r_s = r_200/c return del_c, r_s
def ext_1D_reduced_shear(theta, conc, r_s): ''' function for calculating the tangential shear given by a NFW profile for fitting the concentration parameter and the scale radius r_s This is written by adopting the expression in Umetsu theta = range of radius of the halo that we 're considering, unit in arcsec conc = concentration parameter at the given radius r_s = scale radius of the NFW profile (Mpc) z_halo = halo redshift ### WARNING ### cosmological parameters are written within the function h_scale = hubble scale H = h*100 km/s / Mpc Om = matter energy density Ol = dark energy density Or radiation energy density halo coord 1 halo coord 2 z_halo = redshift of the lens z_source = redshift of the source galaxies beta = ratio of D_LS and D_S see James Jee 's paper for exact def ''' ##latest parameters for El Gordo z_halo = 0.87 z_source = 1.318 beta = 0.258 #old parameters #z_halo =0.89 #z_source = 1.22 #beta = 0.216 #Cosmological parameters #print "profile_1D.tan_1D_reduced_shear: this func uses its own " #print "cosmological parameters" Om = 0.3 Ol = 0.7 Or = 0.0 c = 3e5 #speed of light units km/s G = 6.673*10**(-11) # m^3/kg/s^2 h_scale=0.7 kminMpc = 3.08568025*10**19 # km in a Megaparsec minMpc = 3.08568025*10**22 #m in a Megaparsec kginMsun = 1.988e30 #kg #angular diameter distance to the lens dl = cosmo.Da(z_halo,h_scale,Om,Ol) #in Mpc del_c = 200/3.*conc**3/(np.log(1+conc)-conc/(1+conc)) #unitless nfwSigmacr = c**2/(4*np.pi*G*dl*beta)*1000/kminMpc #in units of kg/m^2 #print 'nfwSigmacr in units of M_sun /pc^2 is ', nfwSigmacr/kginMsun*(3.086*10**16)**2 # in units of kg/m^3 rho_cr = cosmo.rhoCrit(z_halo,h_scale,Om,Ol,Or)#/kginMsun*minMpc**3 #if scale radius is not given then infer from Duffy et al. #assuming full halo #if r_s == np.nan: #r_s = scale_radius(conc,z_halo,Om,Ol,Or) kappa_s = 2*del_c*rho_cr*(r_s*minMpc)/nfwSigmacr #just do a simple conversion from arcsec to physical distance using #angular diameter distance #make sure that the units is in arcsec theta_s = r_s /dl*180.0/np.pi*60.*60. x = theta / theta_s #write an array with finer bins than x fx = x #np.arange(np.min(x),np.max(x),(x[1]-x[0])/10.) #code the expression for kappa as a function of x #print kappa_s func_kappa0 = lambda fx: kappa_s/(1-fx**2.)*\ (-1.+2./np.sqrt(1.-fx**2.)*\ np.arctanh(np.sqrt(1.-fx)/np.sqrt(1.+fx))) func_kappa1 = lambda fx: kappa_s*1./3. func_kappa2 = lambda fx: kappa_s/(fx**2.-1)*\ (1.-2./np.sqrt(fx**2.-1.)*\ np.arctan(np.sqrt(fx-1.)/np.sqrt(fx+1.))) kappa = np.piecewise(fx,[fx<1.0, fx==1.0, fx>1.0], [func_kappa0,func_kappa1,func_kappa2]) g_theta = np.piecewise(x, [x<1.0, x==1.0, x>1.0], [lambda x: np.log(x/2.)+2./np.sqrt(1-x**2)*\ np.arctanh(np.sqrt(1-x)/np.sqrt(1+x)), lambda x: np.log(x/2.)+1., lambda x: np.log(x/2.)+2./np.sqrt(x**2.-1.)*\ np.arctan(np.sqrt(x-1.)/np.sqrt(x+1.))]) kappa_bar = 2.*kappa_s/x**2.*g_theta azim_kappa = kappa #no need to azimuthally smooth function since #the function did n't contain azimuthal angular info to begin with #, azim_bins = azimuthal_avg_shear_in_bins(kappa, fx, np.min(x), np.max(x)+x[1]-x[0], x[1]-x[0]) #print 'bins are ', x #print 'azim_bins are ', azim_bins #print 'size of kappa_bar is ', kappa_bar.size #print 'size of azim_kappa is ', azim_kappa.size #print 'kappa_bar is ', kappa_bar #print 'azim_kappa is ', azim_kappa red_shear= (kappa_bar-azim_kappa)/(1-azim_kappa) return red_shear