-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwindow.py
More file actions
259 lines (219 loc) · 7.55 KB
/
window.py
File metadata and controls
259 lines (219 loc) · 7.55 KB
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
import numpy as np
import matplotlib.pyplot as plt
import astropy.constants as constants
from cosmology import Cosmology
class Window(object):
"""
Class that calculates the window function
and all related quantities. Supported window
function types are: spherical top hat (default),
Gaussian or sharp-k.
Parameters
----------
cosmo : Cosmology object
k : np.ndarray
M : float or np.ndarray, optional
Mass in units of M_sun / h
R : float or np.ndarray, optional
Scale in Mpc / h
window_fnc_type : int, optional
0 -> spherical top hat (default)
1 -> Gaussian
2 -> Sharp-k
Attributes
----------
mass_to_radius : function
Convert Mass in M_sun / h to Radius in Mpc / h
radius_to_mass : function
Convert Radius in Mpc / h to Mass in M_sun / h
V_W : function
Calculate window function volume in (Mpc / h) ^ 3
W_k : function
Calculate window function
dW_k_dR : function
Calculate derivative of window function wrt R
dW_k / dR
dV_W_dR : function
Calculate derivative of volume wrt R
dV_W / dR
dM_dR : function
Calculate derivative of Mass wrt R
dM / dR
"""
def __init__(self,
cosmo : object,
k : np.ndarray,
M : float = None,
R : float = None,
window_fnc_type : str = 'spherical'):
# Create Cosmology class object
self.cosmo = cosmo
self.k = k
if window_fnc_type.lower() == 'spherical':
self.mass_to_radius = self.mass_to_radius_spherical
self.radius_to_mass = self.radius_to_mass_spherical
self.V_W = self.V_W_spherical
self.W_k = self.W_k_spherical
self.dW_k_dR = self.dW_k_dR_spherical
self.dV_W_dR = self.dV_W_dR_spherical
self.dM_dR = self.dM_dR_spherical
elif window_fnc_type.lower() == 'gaussian':
self.mass_to_radius = self.mass_to_radius_Gaussian
self.radius_to_mass = self.radius_to_mass_Gaussian
self.V_W = self.V_W_Gaussian
self.W_k = self.W_k_Gaussian
self.dW_k_dR = self.dW_k_dR_Gaussian
self.dV_W_dR = self.dV_W_dR_Gaussian
self.dM_dR = self.dM_dR_Gaussian
elif window_fnc_type.lower() == 'sharpk':
self.mass_to_radius = self.mass_to_radius_sharpk
self.radius_to_mass = self.radius_to_mass_sharpk
self.V_W = self.V_W_sharpk
self.W_k = self.W_k_sharpk
self.dW_k_dR = self.dW_k_dR_sharpk
self.dV_W_dR = self.dV_W_dR_sharpk
self.dM_dR = self.dM_dR_sharpk
else:
raise ValueError('Invalid Window function name. The only options for the window function are Spherical, Gaussian, or sharpk.')
if R is None and M is not None:
self.M = M
self.R = self.mass_to_radius()
elif R is not None:
self.R = R
self.M = self.radius_to_mass()
else:
raise ValueError('Provide either the Mass or the Radius.')
def V_W_spherical(self, R = None):
if R is None:
R = self.R
return 4. * np.pi * R ** 3 / 3.
def W_k_spherical(self, k = None, R = None):
if R is None:
R = self.R
if k is None:
k = self.k
# Eq 106 in notes
if type(R) == np.ndarray:
vol = self.V_W_spherical(R)[:, np.newaxis]
kR = R[:, np.newaxis] * k
else:
vol = self.V_W_spherical(R)
kR = R * k
return 3. * ( np.sin(kR) / (kR** 3) - np.cos(kR) / (kR** 2))
def dW_k_dR_spherical(self, k = None, R = None):
if R is None:
R = self.R
if k is None:
k = self.k
if type(R) == np.ndarray:
kR = R[:, np.newaxis] * k
k3R4 = (R ** 4)[:, np.newaxis] * k ** 3
else:
kR = R * k
k3R4 = R ** 4 * k ** 3
return 3. * ((kR ** 2 - 3.) * np.sin(kR) + 3. * kR * np.cos(kR)) / (k3R4)
def dV_W_dR_spherical(self, R = None):
if R is None:
R = self.R
return 4. * np.pi * R ** 2.
def radius_to_mass_spherical(self, R = None):
if R is None:
R = self.R
return self.V_W_spherical(R) * self.cosmo.mean_density()
def dM_dR_spherical(self, R = None):
if R is None:
R = self.R
return self.cosmo.mean_density() * self.dV_W_dR_spherical(R)
def mass_to_radius_spherical(self, M = None):
# Mass in M_sun/h
if M is None:
M = self.M
return ( 3. * M / (4. * np.pi * self.cosmo.mean_density()) ) ** (1./3.)
def V_W_sharpk(self, R = None):
if R is None:
R = self.R
# Eq 107 from notes
return 6. * np.pi ** 2 * R ** 3
def W_k_sharpk(self, k = None, R = None):
if R is None:
R = self.R
if k is None:
k = self.k
# Eq 107 from notes
if type(R) == np.ndarray:
kR = R[:, np.newaxis] * k
else:
kR = R * k
arr = abs(kR)
cdn = arr <= 1.
return cdn.astype(float)
def dW_k_dR_sharpk(self, k = None, R = None):
if R is None:
R = self.R
if k is None:
k = self.k
if type(R) == np.ndarray:
kR = R[:, np.newaxis] * k
else:
kR = R * k
cdn = kR == 1
return cdn.astype(float)
def mass_to_radius_sharpk(self, M = None):
# Mass in M_sun/h
if M is None:
M = self.M
return ( M / (6. * np.pi ** 2 * self.cosmo.mean_density()) ) ** (1./3.)
def radius_to_mass_sharpk(self, R = None):
if R is None:
R = self.R
return self.V_W_sharpk(R) * self.cosmo.mean_density()
def dV_W_dR_sharpk(self, R = None):
if R is None:
R = self.R
return 18. * np.pi ** 2 * R **2
def dM_dR_sharpk(self, R = None):
if R is None:
R = self.R
return self.cosmo.mean_density() * self.dV_W_dR_sharpk(R)
def V_W_Gaussian(self, R = None):
if R is None:
R = self.R
# Eq 108 in notes
return (2 * np.pi) ** (3./2.) * R ** 3
def W_k_Gaussian(self, k = None, R = None):
if R is None:
R = self.R
if k is None:
k = self.k
# Eq 108 in notes
if type(R) == np.ndarray:
kR = R[:, np.newaxis] * k
else:
kR = R * k
return np.exp(- kR ** 2 / 2.)
def radius_to_mass_Gaussian(self, R = None):
if R is None:
R = self.R
return self.V_W_Gaussian(R) * self.cosmo.mean_density()
def mass_to_radius_Gaussian(self, M = None):
if M is None:
M = self.M
return ( M / ((2. * np.pi) ** (3./2.) * self.cosmo.mean_density()) ) ** (1./3.)
def dW_k_dR_Gaussian(self, k = None, R = None):
if R is None:
R = self.R
if k is None:
k = self.k
if type(R) == np.ndarray:
k2R = R[:, np.newaxis] * k ** 2
else:
k2R = R * k ** 2
return - k2R * self.W_k_Gaussian(k = k, R = R)
def dV_W_dR_Gaussian(self, R = None):
if R is None:
R = self.R
return 3. * (2. * np.pi) ** (3./2.) * R ** 2.
def dM_dR_Gaussian(self, R = None):
if R is None:
R = self.R
return self.cosmo.mean_density() * self.dV_W_dR_gaussian(R)