Integrated Effects
Integrated contributions arise from line-of-sight integrals between the observer and source, including lensing convergence, the integrated Sachs-Wolfe (ISW) effect, and time delay. These are important for unbiased \(f_\mathrm{NL}\) constraints – neglecting them can bias \(f_\mathrm{NL}\) by several sigma.
Integration Methods
CosmoWAP provides two underlying integration routines (in integrated.BaseInt) for evaluating line-of-sight integrals:
- BaseInt.single_int(func, \*args, n=128, remove_div=True, source_func=None)
Gauss-Legendre quadrature over a single line-of-sight integral \(\int_0^{1} f(y)\, dy\), where \(y = \chi/d\) is the normalised radial distance. Used for RSD x Integrated terms.
- Parameters:
n (int) – Number of quadrature nodes
remove_div (bool) – Excise numerical divergence near the source (default: True)
source_func – Optional function returning the integrand value at the source, used for interpolation near the divergence
- BaseInt.double_int(func, \*args, n=128, n2=None, fast=True)
Gauss-Legendre quadrature over a double line-of-sight integral \(\int_0^{1}\!\int_0^{1} f(y_1, y_2)\, dy_1\, dy_2\), where \(y_i = \chi_i/d\). Used for Integrated x Integrated terms. Exploits symmetry \(f(y_1, y_2) = f(y_2, y_1)\) when
fast=Trueto reduce memory and computation.- Parameters:
n (int) – Number of quadrature nodes for first integral
n2 (int) – Nodes for second integral (default: same as
n)fast (bool) – Sum directly rather than building the full 2D grid (default: True)
Numerical \(\mu\) Pipeline
pk_int.get_multipole provides an alternative numerical approach for computing power spectrum multipoles. Rather than using the analytically-derived multipole expressions (e.g. pk.NPP.l0), it constructs the full \(P(k,\mu)\) from first-order field kernels (defined in lib/kernels.py) and numerically projects onto Legendre multipoles. This handles any combination of standard and integrated kernels with a single interface.
- pk_int.get_multipole(kernel1, kernel2, l, cosmo_funcs, kk, zz, sigma=None, n=32, n_mu=256, nr=2000, deg=8, delta=0.1, GL=False)
Compute the l-th multipole of the power spectrum for a given pair of kernels.
- Parameters:
kernel1 (list) – Kernel(s) for field 1 (e.g.
['N'],['N', 'LP'],['I'])kernel2 (list) – Kernel(s) for field 2
l (int) – Multipole order
cosmo_funcs –
ClassWAPinstancekk (array) – Wavevectors [h/Mpc]
zz (float) – Redshift
sigma (float) – FoG damping
n (int) – Number of Gauss-Legendre nodes for the line-of-sight integral
n_mu (int) – Number of \(\mu\) integration points
nr (int) – Number of radial points for the kernel integration
deg (int) – Polynomial degree for Filon integration
delta (float) – Width of the central region for non-uniform \(\mu\) grid
GL (bool) – Use Gauss-Legendre for \(\mu\) integration (default: non-uniform grid)
- Returns:
Power spectrum multipole [(Mpc/h)^3]
Available Kernels
The kernels are defined in lib/kernels.py (class K1). Each kernel represents a first-order field contribution to the observed galaxy overdensity.
Standard (evaluated at source):
'N'– Newtonian (Kaiser RSD): \(D(z)[b_1 + f\mu^2]\)'LP'– Local projection effects (relativistic): \(D(z)[i\mu\,\beta_1/k + \beta_2/k^2]\)
Integrated (line-of-sight):
'I'– All integrated effects combined (L + TD + ISW)'L'– Lensing convergence'TD'– Time delay'ISW'– Integrated Sachs-Wolfe
The power spectrum for any pair of kernels is \(P_\ell(k) = \frac{2\ell+1}{2}\int_{-1}^{1} K_1 K_2^* P(k)\, \mathcal{L}_\ell(\mu)\, d\mu\), where the line-of-sight integrals for integrated kernels are handled internally.
Usage
import numpy as np
import cosmo_wap as cw
from cosmo_wap.pk import pk_int
from cosmo_wap.lib import utils
cosmo = utils.get_cosmo()
survey = cw.SurveyParams.Euclid(cosmo)
cosmo_funcs = cw.ClassWAP(cosmo, survey)
k = np.linspace(0.01, 0.3, 100)
z = 1.0
# Standard Newtonian (Kaiser x Kaiser) -- equivalent to pk.NPP
P0_NPP = pk_int.get_multipole(['N'], ['N'], 0, cosmo_funcs, k, z)
# Newtonian + local projection (Kaiser + GR)
P0_full = pk_int.get_multipole(['N', 'LP'], ['N', 'LP'], 0, cosmo_funcs, k, z)
# Integrated x NPP (lensing + ISW + TD crossed with Kaiser)
P0_IntNPP = pk_int.get_multipole(['I'], ['N'], 0, cosmo_funcs, k, z)
P2_IntNPP = pk_int.get_multipole(['I'], ['N'], 2, cosmo_funcs, k, z)
# Integrated x Integrated
P0_IntInt = pk_int.get_multipole(['I'], ['I'], 0, cosmo_funcs, k, z)
# Individual components (e.g. Lensing x NPP only)
P0_LxNPP = pk_int.get_multipole(['L'], ['N'], 0, cosmo_funcs, k, z)
Analytic Multipole Classes
Analytically-derived multipole expressions are also available in pk.int and pk.int_components. These are computed in Mathematica and exported, with the line-of-sight integrals evaluated via Gauss-Legendre quadrature.
- class pk.int.IntNPP
RSD x Integrated (single line-of-sight integral).
- l0(cosmo_funcs, k1, zz=0, t=0, sigma=None, n=128)
- l1(cosmo_funcs, k1, zz=0, t=0, sigma=None, n=128)
- l2(cosmo_funcs, k1, zz=0, t=0, sigma=None, n=128)
- l3(cosmo_funcs, k1, zz=0, t=0, sigma=None, n=128)
- l4(cosmo_funcs, k1, zz=0, t=0, sigma=None, n=128)
- l(l, cosmo_funcs, k1, zz=0, t=0, sigma=None, n=128, n_mu=16)
Generic l-th multipole via numeric \(\mu\) integration.
- mu(mu, cosmo_funcs, k1, zz=0, t=0, sigma=None, n=128)
Full \(P(k, \mu)\).
- class pk.int.IntInt
Integrated x Integrated (double line-of-sight integral).
- l0(cosmo_funcs, k1, zz=0, t=0.5, sigma=None, n=128, fast=True)
- l1(cosmo_funcs, k1, zz=0, t=0.5, sigma=None, n=128, fast=True)
- l2(cosmo_funcs, k1, zz=0, t=0.5, sigma=None, n=128, fast=True)
- l3(cosmo_funcs, k1, zz=0, t=0.5, sigma=None, n=128, fast=True)
- l4(cosmo_funcs, k1, zz=0, t=0.5, sigma=None, n=128, fast=True)
- l(l, cosmo_funcs, k1, zz=0, t=0.5, sigma=None, n=128, n_mu=16)
Generic l-th multipole via numeric \(\mu\) integration.
- mu(mu, cosmo_funcs, k1, zz=0, t=0.5, sigma=None, n=128)
Full \(P(k, \mu)\).
Individual integrated component classes are also available in pk.int_components:
LxL,LxTD,LxISW,TDxTD,ISWxISW,TDxISW
Each provides l0 through l4 multipoles with the same interface as IntInt.