-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathgenerate_nbodykit_power.py
191 lines (163 loc) · 5.12 KB
/
generate_nbodykit_power.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import numpy as np
from nbodykit.lab import ArrayCatalog, FFTPower
def CompensateTSC(w, v):
"""
Return the Fourier-space kernel that accounts for the convolution of
the gridded field with the TSC window function in configuration space
.. note::
see equations in
`Jing et al 2005 <https://arxiv.org/abs/astro-ph/0409240>`_
Parameters
----------
w : list of arrays
the list of "circular" coordinate arrays, ranging from
:math:`[-\pi, \pi)`.
v : array_like
the field array
"""
for i in range(3):
wi = w[i]
tmp = (np.sinc(0.5 * wi / np.pi)) ** 3
v = v / tmp
return v
def CompensateCIC(w, v):
"""
Return the Fourier-space kernel that accounts for the convolution of
the gridded field with the CIC window function in configuration space
.. note::
see equations in
`Jing et al 2005 <https://arxiv.org/abs/astro-ph/0409240>`_
Parameters
----------
w : list of arrays
the list of "circular" coordinate arrays, ranging from
:math:`[-\pi, \pi)`.
v : array_like
the field array
"""
for i in range(3):
wi = w[i]
tmp = (np.sinc(0.5 * wi / np.pi)) ** 2
v = v / tmp
return v
def CompensateTSCShotnoise(w, v):
"""
Return the Fourier-space kernel that accounts for the convolution of
the gridded field with the TSC window function in configuration space,
as well as the approximate aliasing correction to the first order
.. note::
see equations in
`Jing et al 2005 <https://arxiv.org/abs/astro-ph/0409240>`_
Parameters
----------
w : list of arrays
the list of "circular" coordinate arrays, ranging from
:math:`[-\pi, \pi)`.
v : array_like
the field array
"""
for i in range(3):
wi = w[i]
s = np.sin(0.5 * wi) ** 2
v = v / (1 - s + 2.0 / 15 * s**2) ** 0.5
return v
def CompensateCICShotnoise(w, v):
"""
Return the Fourier-space kernel that accounts for the convolution of
the gridded field with the CIC window function in configuration space,
as well as the approximate aliasing correction to the first order
.. note::
see equations in
`Jing et al 2005 <https://arxiv.org/abs/astro-ph/0409240>`_
Parameters
----------
w : list of arrays
the list of "circular" coordinate arrays, ranging from
:math:`[-\pi, \pi)`.
v : array_like
the field array
"""
for i in range(3):
wi = w[i]
s = np.sin(0.5 * wi) ** 2
v = v / (1 - 2.0 / 3.0 * s) ** 0.5
return v
def power_test_data():
return dict(
Lbox=1000.0,
**np.load('tests/data_power/test_pos.npz'),
)
def generate_nbody(power_test_data, interlaced=False, compensated=False, paste='CIC'):
# load data
power_test_data = power_test_data()
Lbox = power_test_data['Lbox']
pos = power_test_data['pos']
# specifications of the power spectrum computation
nmesh = 72
nbins_mu = 4
kmin = 0.0
dk = 2.0 * np.pi / Lbox
kmax = np.pi * nmesh / Lbox
poles = [0, 2, 4]
# file to save to
comp_str = '_compensated' if compensated else ''
int_str = '_interlaced' if interlaced else ''
fn = f'tests/data_power/nbody_{paste}{comp_str}{int_str}.npz'
# create mesh object
cat = ArrayCatalog({'Position': pos.T})
# convert to a MeshSource, apply compensation (same as nbodykit, but need to apply manually, as it fails on some nbodykit versions)
mesh = cat.to_mesh(
window=paste.lower(),
Nmesh=nmesh,
BoxSize=Lbox,
interlaced=interlaced,
compensated=False,
position='Position',
)
if compensated and interlaced:
if paste == 'TSC':
compensation = CompensateTSC
elif paste == 'CIC':
compensation = CompensateCIC
elif compensated and not interlaced:
if paste == 'TSC':
compensation = CompensateTSCShotnoise
elif paste == 'CIC':
compensation = CompensateCICShotnoise
if compensated:
mesh = mesh.apply(compensation, kind='circular', mode='complex')
# compute the 2D power
r = FFTPower(
mesh,
mode='2d',
kmin=kmin,
dk=dk,
kmax=kmax,
Nmu=nbins_mu,
los=[0, 0, 1],
poles=poles,
)
p_ell = r.poles
k = p_ell['k']
modes = p_ell['modes']
P_ell = []
for pole in poles:
P_ell.append(p_ell[f'power_{pole:d}'])
P_ell = np.array(P_ell)
Pkmu = r.power
# k = Pkmu['k']
k = r.power.coords['k'] # bin centers (matches abacusutils preference)
modes = Pkmu['modes']
Pkmu = Pkmu['power']
# save arrays
np.savez(fn, k=k, power=Pkmu, modes=modes, power_ell=P_ell)
if __name__ == '__main__':
for compensated in [True, False]:
for interlaced in [True, False]:
for paste in ['TSC', 'CIC']:
generate_nbody(
power_test_data,
interlaced=interlaced,
compensated=compensated,
paste=paste,
)