def xi(self, rin, **keys): """ Name: xi Calling Sequence: xi(r, nplk=) Purpose: Calculate the 3d linear correlation function by integrating over the power spectrum. Inputs: r: radius in Mpc nplk=: The number of points in P(k) per log k. See pkgen() for the default. """ r = numpy.array(rin, dtype='f8', copy=False, ndmin=1) # first get P(k) on a log spaced grid log_kmin = -5.0 log_kmax = 6.0 k,Pk = self.pkgen(log_kmin, log_kmax, **keys) rmax=2000.0 if r.max() > rmax: raise ValueError("Some rmax greater than %s" % rmax) xi = numpy.zeros(r.size, dtype='f8') for i in xrange(r.size): #xi[i] = self.xi_int_pk(k,Pk,r[i]) xi[i] = self.xi_int_pk_slow(k,Pk,r[i]) w=where1(r < 25.0) rr,ss = self.xi2sigmavar(r[w], xi[w]) s8=exp(interplin(log(ss),log(rr),log(8.0))) xi=xi*(self.sigma_8/s8)**2 return xi
def xi2sigmavar(self,r,xi): """ Compute sigma variance from xi where xi is the 3d correlation function. returns rr and sig, rr is not exactly the same as r You can calculate sigma8 from the results rr,ss = self.xi2sigmavar(r, xi) s8=exp(interplin(log(ss),log(rr),log(8.0))) """ w = where1( xi <= 0 ) if w.size > 0: raise ValueError("xi must be positive to perform powerlawe interp") # choose a new set of points, logarithmically spaced such that a # whole number of points (nper2) correspond to a factor of two nper2 = 100 rmax = r.max() rmin = r.min() tmp = int32( ceil(log(rmax/rmin)/log(2)) ) num = 1+nper2*tmp tmp = arange(num,dtype='f8')/nper2 rr = rmin*2.0**tmp log_r = log(r) log_xi = log(xi) log_rr = log(rr) lxx = interplin(log_xi,log_r,log_rr) xxi = exp(lxx) # roll is same as shift in IDL al=(roll(lxx,-1)-lxx)/(roll(log_rr,-1)-log_rr) al[num-1]=al[num-2] A=xxi/rr**(al) Ra=rr.copy() Ra[0]=0.0 # first one , integrate to zero Rb=roll(rr,-1) # 3 integrals to do beta=0.0 ex=3.0+al+beta int0=A*(1.0/ex) *(Rb**ex -Ra**ex) beta=1.0 ex=3.0+al+beta int1=A*(1.0/ex) *(Rb**ex -Ra**ex) beta=3.0 ex=3.0+al+beta int2=A*(1.0/ex) *(Rb**ex -Ra**ex) # array of sub integrals, last one to be ignored # Now add up the sub integrals with 0 to rmin integral T0=roll(int0.cumsum(),-nper2) T1=roll(int1.cumsum(),-nper2) T2=roll(int2.cumsum(),-nper2) sig2=3.0*T0/(rr**3) + (-9.0/4)*T1/(rr**4) + (3.0/16)*T2/(rr**6) # now trim off last bunch rr=rr[0:num-nper2-2] log_rr=log_rr[0:num-nper2-2] sig2=sig2[0:num-nper2-2] sig=sqrt(sig2) # now interpolate back onto original points ss=exp(interplin(log(sig),log_rr,log_r)) wcut=where1(r*2 < rmax) rr=r[wcut] sig=ss sig=sig[wcut] return rr, sig
def xi_int_pk(self, k, Pk, r): """ get xi at position r by integrating P(k). r should be a scalar the integral is done in two parts """ import scipy.integrate # some of this could be pre-computed, but it might # not matter NumPerPer = 30.0 # Number of samples per period, should always be > 5 at least npd = 100 # depends on cosmology but this is ballpark L_wiggle=170.0 Pref=1.0 /(2.0 * PI**2 * r) dk1=2.0 *PI/(NumPerPer*L_wiggle) dk2=2.0 *PI/(NumPerPer*r) dktry=min([dk1,dk2]) # first section kmin=0.0 kmax=2.0 numk=int32((kmax-kmin)/dktry) dk=(kmax-kmin)/(1.0*numk-1) kk=arange(numk,dtype='f8')*dk+kmin # Dave used cubic spline interpolation Pkk=interplin(Pk,k,kk) tab=Pkk*kk*sin(kk*r) integ = scipy.integrate.simps(tab,kk) xi_1=Pref*integ # next section/method # now need integral \int_xmax^infinity x P(x/r) sin(x) Pref2=Pref/(r**2) xmax=r*kmax num_dec=5 num_per_dec=npd numx=num_dec*num_per_dec x=xmax*10.0**(arange(numx,dtype='f8')/num_per_dec) Px=interplin(Pk,k,x/r) y=x*Px ly=log(y) n=numx al=(roll(ly,-1)-ly)/(roll(x,-1)-x) al[n-1]=al[n-2] Amp=y/exp(al*x) # integral boundaries a=x b=roll(x,-1) norm=y/(1+al**2) Ta=al*sin(a)-cos(a) Tb=al*sin(b)-cos(b) dif=exp(al*(b-a))*Tb-Ta d=norm*dif d=d[0:n-2] integ=d.sum() xi_2=integ*Pref2 xi=xi_1+xi_2 return xi
def xi_int_pk_slow(self, k, Pk, r, debug=False, doplot=False): """ Maybe try a slow but more accurate version here get xi at position r by integrating P(k). r should be a scalar the integral is done in two parts """ import scipy.integrate # some of this could be pre-computed, but it might # not matter NumPerPer = 30.0 # Number of samples per period, should always be > 5 at least npd = 100 # depends on cosmology but this is ballpark L_wiggle=170.0 Pref=1.0 /(2.0 * PI**2 * r) dk1=2.0 *PI/(NumPerPer*L_wiggle) dk2=2.0 *PI/(NumPerPer*r) dktry=min([dk1,dk2]) # first section kmin=0.0 kmax=2.0 numk=int32((kmax-kmin)/dktry) dk=(kmax-kmin)/(1.0*numk-1) kk=arange(numk,dtype='f8')*dk+kmin # Dave used *local* cubic spline interpolation (the /spline) # keyword for interpol. This seems to give radically different # results! Using interpsp2 above gets us within about 6% # of dave's answer. Which is right? I think the right thing # to do is use more values for Pk,k and do linear interpolation Pkk=interplin(Pk,k,kk) #Pkk=interp(kk,k,Pk) tab=Pkk*kk*sin(kk*r) integ = scipy.integrate.simps(tab,x=kk) xi_1=Pref*integ if debug: print 'r=',r if dk1 < dk2: print 'Baryon wiggle limited' else: print 'Sin(k*r) limited' print 'Numk=',numk print 'dk=',dk integ_trap = scipy.integrate.trapz(tab,x=kk) integ_qg1000 = self.qg1000.integrate(kk,tab) print 'integ=',integ print 'integ_trap=',integ_trap print 'integ_qg1000=',integ_qg1000 nprint=20 if doplot: wk=where1(k < kmax) wkk=where1(kk > 1.e-8) ptab=Table(2,1) lplt=FramedPlot() lplt.add( Points(k[wk],Pk[wk],type='filled circle',size=1) ) lplt.add( Points(kk[wkk],Pkk[wkk], color='red', type='filled circle', size=0.7)) lplt.add( Curve(kk[wkk],Pkk[wkk], color='blue')) lplt.xlog=True ptab[0,0] = lplt splt = FramedPlot() splt.add(Points(k[wk],Pk[wk]*k[wk]*sin(k[wk]*r), type='filled circle',size=1)) splt.add(Points(kk[wkk],tab[wkk], color='red',type='filled circle',size=0.7)) splt.add(Curve(kk[wkk],tab[wkk], color='blue')) splt.xlog=True ptab[1,0] = splt ptab.show() # next section/method # now need integral \int_xmax^infinity x P(x/r) sin(x) Pref2=Pref/(r**2) xmax=r*kmax num_dec=5 num_per_dec=npd numx=num_dec*num_per_dec x=xmax*10.0**(arange(numx,dtype='f8')/num_per_dec) Px=interplin(Pk,k,x/r) y=x*Px ly=log(y) n=numx al=(roll(ly,-1)-ly)/(roll(x,-1)-x) al[n-1]=al[n-2] Amp=y/exp(al*x) # integral boundaries a=x b=roll(x,-1) norm=y/(1+al**2) Ta=al*sin(a)-cos(a) Tb=al*sin(b)-cos(b) dif=exp(al*(b-a))*Tb-Ta d=norm*dif d=d[0:n-2] integ=d.sum() xi_2=integ*Pref2 xi=xi_1+xi_2 if debug: print 'xi_1:',xi_1 print 'xi_2:',xi_2 return xi