pybhpt 0.9.4__cp311-cp311-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pybhpt might be problematic. Click here for more details.
- cybhpt_full.cpython-311-x86_64-linux-musl.so +0 -0
- pybhpt/__init__.py +0 -0
- pybhpt/flux.py +124 -0
- pybhpt/geo.py +407 -0
- pybhpt/hertz.py +402 -0
- pybhpt/metric.py +327 -0
- pybhpt/radial.py +381 -0
- pybhpt/redshift.py +20 -0
- pybhpt/swsh.py +347 -0
- pybhpt/teuk.py +245 -0
- pybhpt-0.9.4.dist-info/METADATA +135 -0
- pybhpt-0.9.4.dist-info/RECORD +18 -0
- pybhpt-0.9.4.dist-info/WHEEL +5 -0
- pybhpt-0.9.4.dist-info/licenses/LICENSE +674 -0
- pybhpt.libs/libgcc_s-0cd532bd.so.1 +0 -0
- pybhpt.libs/libgsl-6bd0117f.so.28.0.0 +0 -0
- pybhpt.libs/libgslcblas-55a77d35.so.0.0.0 +0 -0
- pybhpt.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
pybhpt/metric.py
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
from cybhpt_full import metric_coefficients_cython_S4dagger, metric_coefficients_cython_S0dagger
|
|
2
|
+
import numpy as np
|
|
3
|
+
from pybhpt.hertz import available_gauges
|
|
4
|
+
from pybhpt.swsh import Yslm, spin_operator_normalization
|
|
5
|
+
|
|
6
|
+
def gauge_check(gauge):
|
|
7
|
+
if gauge not in available_gauges:
|
|
8
|
+
TypeError("{} is not a supported gauge.".format(gauge))
|
|
9
|
+
|
|
10
|
+
S0_gauges = ["IRG", "ARG0", "SRG0"]
|
|
11
|
+
S4_gauges = ["ORG", "ARG4", "SRG4"]
|
|
12
|
+
|
|
13
|
+
def metric_coefficients_S4dagger_ab(ai, bi, nt, nr, nz, nph, a, r, z):
|
|
14
|
+
"""Compute the metric coefficients for the reconstructed perturbation associated with the
|
|
15
|
+
S4dagger reconstruction operator.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
ai, bi : int
|
|
20
|
+
The indices of the tetrad-projected components of the metric perturbation.
|
|
21
|
+
nt, nr, nz, nph : int
|
|
22
|
+
The indices associated with the time, radial, spin, and azimuthal derivative operators.
|
|
23
|
+
a : float
|
|
24
|
+
The black hole spin parameter.
|
|
25
|
+
r : float
|
|
26
|
+
The radial coordinate.
|
|
27
|
+
z : float
|
|
28
|
+
The polar coordinate (cosine of the polar angle).
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
float
|
|
33
|
+
The computed metric coefficient."""
|
|
34
|
+
return metric_coefficients_cython_S4dagger(ai, bi, nt, nr, nz, nph, a, r, z)
|
|
35
|
+
|
|
36
|
+
def metric_coefficients_S0dagger_ab(ai, bi, nt, nr, nz, nph, a, r, z):
|
|
37
|
+
"""Compute the metric coefficients for the reconstructed perturbation associated with the
|
|
38
|
+
S0dagger reconstruction operator.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
ai, bi : int
|
|
43
|
+
The indices of the tetrad-projected components of the metric perturbation.
|
|
44
|
+
nt, nr, nz, nph : int
|
|
45
|
+
The indices associated with the time, radial, spin, and azimuthal derivative operators.
|
|
46
|
+
a : float
|
|
47
|
+
The black hole spin parameter.
|
|
48
|
+
r : float
|
|
49
|
+
The radial coordinate.
|
|
50
|
+
z : float
|
|
51
|
+
The polar coordinate (cosine of the polar angle).
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
float
|
|
56
|
+
The computed metric coefficient."""
|
|
57
|
+
return metric_coefficients_cython_S0dagger(ai, bi, nt, nr, nz, nph, a, r, z)
|
|
58
|
+
|
|
59
|
+
def metric_coefficients_S0dagger(a, b, c, d, q, rvals, zvals):
|
|
60
|
+
"""Compute the metric coefficients for the reconstructed perturbation associated with the
|
|
61
|
+
S0dagger reconstruction operator.
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
a, b, c, d : int
|
|
66
|
+
The indices associated with the time, radial, spin, and azimuthal derivative operators.
|
|
67
|
+
q : float
|
|
68
|
+
The black hole spin parameter.
|
|
69
|
+
rvals : numpy.ndarray
|
|
70
|
+
The radial coordinate.
|
|
71
|
+
zvals : np.ndarray
|
|
72
|
+
The polar coordinate (cosine of the polar angle).
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
numpy.ndarray
|
|
77
|
+
A 3D array containing the computed metric coefficients for the S0dagger operator."""
|
|
78
|
+
h22 = np.array([[metric_coefficients_S0dagger_ab(2, 2, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
|
|
79
|
+
h24 = np.array([[metric_coefficients_S0dagger_ab(2, 4, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
|
|
80
|
+
h44 = np.array([[metric_coefficients_S0dagger_ab(4, 4, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
|
|
81
|
+
return np.array([2.*h22, h24, h44])
|
|
82
|
+
|
|
83
|
+
def metric_coefficients_S4dagger(a, b, c, d, q, rvals, zvals):
|
|
84
|
+
"""Compute the metric coefficients for the reconstructed perturbation associated with the
|
|
85
|
+
S4dagger reconstruction operator.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
a, b, c, d : int
|
|
90
|
+
The indices associated with the time, radial, spin, and azimuthal derivative operators.
|
|
91
|
+
q : float
|
|
92
|
+
The black hole spin parameter.
|
|
93
|
+
rvals : numpy.ndarray
|
|
94
|
+
The radial coordinate.
|
|
95
|
+
zvals : np.ndarray
|
|
96
|
+
The polar coordinate (cosine of the polar angle).
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
numpy.ndarray
|
|
101
|
+
A 3D array containing the computed metric coefficients for the S0dagger operator."""
|
|
102
|
+
h11 = np.array([[metric_coefficients_S4dagger_ab(1, 1, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
|
|
103
|
+
h13 = np.array([[metric_coefficients_S4dagger_ab(1, 3, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
|
|
104
|
+
h33 = np.array([[metric_coefficients_S4dagger_ab(3, 3, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
|
|
105
|
+
return np.array([2.*h11, h13, h33])
|
|
106
|
+
|
|
107
|
+
def metric_coefficients(gauge, a, b, c, d, q, rvals, zvals):
|
|
108
|
+
"""Compute the metric coefficients for the reconstructed perturbation associated with the
|
|
109
|
+
specified gauge.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
gauge : str
|
|
114
|
+
The gauge to use for the reconstruction. Must be one of the available gauges.
|
|
115
|
+
a, b, c, d : int
|
|
116
|
+
The indices associated with the time, radial, spin, and azimuthal derivative operators.
|
|
117
|
+
q : float
|
|
118
|
+
The black hole spin parameter.
|
|
119
|
+
rvals : numpy.ndarray
|
|
120
|
+
The radial coordinate.
|
|
121
|
+
zvals : np.ndarray
|
|
122
|
+
The polar coordinate (cosine of the polar angle).
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
numpy.ndarray
|
|
127
|
+
A 3D array containing the computed metric coefficients for the specified gauge.
|
|
128
|
+
"""
|
|
129
|
+
gauge_check(gauge)
|
|
130
|
+
if gauge in S0_gauges:
|
|
131
|
+
return metric_coefficients_S0dagger(a, b, c, d, q, rvals, zvals)
|
|
132
|
+
else:
|
|
133
|
+
return metric_coefficients_S4dagger(a, b, c, d, q, rvals, zvals)
|
|
134
|
+
|
|
135
|
+
class MetricCoefficients:
|
|
136
|
+
"""
|
|
137
|
+
A class for computing the metric coefficients of the reconstructed perturbation
|
|
138
|
+
associated with the S0dagger or S4dagger reconstruction operator based on the specified gauge.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
gauge : str
|
|
143
|
+
The gauge to use for the reconstruction. Must be one of the available gauges.
|
|
144
|
+
q : float
|
|
145
|
+
The black hole spin parameter.
|
|
146
|
+
r : numpy.ndarray
|
|
147
|
+
The radial coordinate values.
|
|
148
|
+
th : numpy.ndarray
|
|
149
|
+
The polar coordinate values (cosine of the polar angle).
|
|
150
|
+
|
|
151
|
+
Attributes
|
|
152
|
+
----------
|
|
153
|
+
gauge : str
|
|
154
|
+
The gauge used for the reconstruction.
|
|
155
|
+
blackholespin : float
|
|
156
|
+
The black hole spin parameter.
|
|
157
|
+
radialpoints : numpy.ndarray
|
|
158
|
+
The radial coordinate values.
|
|
159
|
+
polarpoints : numpy.ndarray
|
|
160
|
+
The polar coordinate values (cosine of the polar angle).
|
|
161
|
+
storedcomponents : dict
|
|
162
|
+
A dictionary mapping pairs of indices (a, b) to the index of the stored component
|
|
163
|
+
in the coefficients array.
|
|
164
|
+
conjugatecomponents : dict
|
|
165
|
+
A dictionary mapping pairs of indices (a, b) to the index of the conjugate component
|
|
166
|
+
in the coefficients array.
|
|
167
|
+
coeffs : numpy.ndarray
|
|
168
|
+
A 7D array containing the computed metric coefficients for the specified gauge.
|
|
169
|
+
zeros : numpy.ndarray
|
|
170
|
+
A 2D array of zeros with the same shape as the radial and polar coordinate arrays.
|
|
171
|
+
|
|
172
|
+
Methods
|
|
173
|
+
-------
|
|
174
|
+
hab(a, b, nt, nr, ns, nphi):
|
|
175
|
+
Returns the metric coefficient for the specified indices (a, b) and derivative orders
|
|
176
|
+
(nt, nr, ns, nphi). If the indices are not found in the stored or conjugate components,
|
|
177
|
+
it returns a zero array.
|
|
178
|
+
__call__(a, b, nt, nr, ns, nphi):
|
|
179
|
+
Calls the `hab` method to retrieve the metric coefficient for the specified indices
|
|
180
|
+
and derivative orders.
|
|
181
|
+
"""
|
|
182
|
+
def __init__(self, gauge, q, r, th):
|
|
183
|
+
gauge_check(gauge)
|
|
184
|
+
self.gauge = gauge
|
|
185
|
+
rsamples = r.shape[0]
|
|
186
|
+
zsamples = th.shape[0]
|
|
187
|
+
self.blackholespin = q
|
|
188
|
+
self.radialpoints = r
|
|
189
|
+
self.polarpoints = th
|
|
190
|
+
if gauge in S0_gauges:
|
|
191
|
+
self.storedcomponents = {(2, 2): 0, (2, 4): 1, (4, 4): 2}
|
|
192
|
+
self.conjugatecomponents = {(2, 3): 1, (3, 3): 2}
|
|
193
|
+
else:
|
|
194
|
+
self.storedcomponents = {(1, 1): 0, (1, 3): 1, (3, 3): 2}
|
|
195
|
+
self.conjugatecomponents = {(1, 4): 1, (4, 4): 2}
|
|
196
|
+
z = np.cos(th)
|
|
197
|
+
z[np.abs(z) < 1.e-15] = 0.
|
|
198
|
+
self.coeffs = np.zeros((3, 3, 3, 3, 3, rsamples, zsamples), dtype=np.complex128)
|
|
199
|
+
self.zeros = np.zeros((rsamples, zsamples), dtype=np.complex128)
|
|
200
|
+
for ai in range(3):
|
|
201
|
+
for bi in range(3):
|
|
202
|
+
for ci in range(3):
|
|
203
|
+
for di in range(3):
|
|
204
|
+
self.coeffs[ai, bi, ci, di] = metric_coefficients(self.gauge, ai, bi, ci, di, q, r, z)
|
|
205
|
+
|
|
206
|
+
def hab(self, a, b, nt, nr, ns, nphi):
|
|
207
|
+
"""
|
|
208
|
+
Returns the metric coefficient for the specified indices (a, b) and derivative orders
|
|
209
|
+
(nt, nr, ns, nphi). If the indices are not found in the stored or conjugate components,
|
|
210
|
+
it returns a zero array.
|
|
211
|
+
|
|
212
|
+
Parameters
|
|
213
|
+
----------
|
|
214
|
+
a, b : int
|
|
215
|
+
The indices of the tetrad-projected components of the metric perturbation.
|
|
216
|
+
nt, nr, ns, nphi : int
|
|
217
|
+
The indices associated with the time, radial, spin, and azimuthal derivative operators.
|
|
218
|
+
|
|
219
|
+
Returns
|
|
220
|
+
-------
|
|
221
|
+
numpy.ndarray
|
|
222
|
+
The computed metric coefficient for the specified indices and derivative orders.
|
|
223
|
+
"""
|
|
224
|
+
if b < a:
|
|
225
|
+
atemp = a
|
|
226
|
+
a = b
|
|
227
|
+
b = atemp
|
|
228
|
+
if (a, b) in self.storedcomponents.keys():
|
|
229
|
+
return self.coeffs[nt, nr, ns, nphi][self.storedcomponents[(a, b)]]
|
|
230
|
+
elif (a, b) in self.conjugatecomponents.keys():
|
|
231
|
+
return np.conj(self.coeffs[nt, nr, ns, nphi][self.conjugatecomponents[(a, b)]])
|
|
232
|
+
else:
|
|
233
|
+
return self.zeros
|
|
234
|
+
|
|
235
|
+
def __call__(self, a, b, nt, nr, ns, nphi):
|
|
236
|
+
""" Calls the `hab` method to retrieve the metric coefficient for the specified indices
|
|
237
|
+
and derivative orders.
|
|
238
|
+
|
|
239
|
+
Parameters
|
|
240
|
+
----------
|
|
241
|
+
a, b : int
|
|
242
|
+
The indices of the tetrad-projected components of the metric perturbation.
|
|
243
|
+
nt, nr, ns, nphi : int
|
|
244
|
+
The indices associated with the time, radial, spin, and azimuthal derivative operators.
|
|
245
|
+
|
|
246
|
+
Returns
|
|
247
|
+
-------
|
|
248
|
+
numpy.ndarray
|
|
249
|
+
The computed metric coefficient for the specified indices and derivative orders.
|
|
250
|
+
"""
|
|
251
|
+
return self.hab(a, b, nt, nr, ns, nphi)
|
|
252
|
+
|
|
253
|
+
def tetrad_project_l(a, r, z, mu):
|
|
254
|
+
if mu == 0:
|
|
255
|
+
return -1
|
|
256
|
+
elif mu == 1:
|
|
257
|
+
sigma = r**2 + a**2*z**2
|
|
258
|
+
delta = r**2 - 2.*r + a**2
|
|
259
|
+
return sigma/delta
|
|
260
|
+
elif mu == 2:
|
|
261
|
+
return 0.
|
|
262
|
+
elif mu == 3:
|
|
263
|
+
return a*(1. - z**2)
|
|
264
|
+
else:
|
|
265
|
+
return 0.
|
|
266
|
+
|
|
267
|
+
def tetrad_project_n(a, r, z, mu):
|
|
268
|
+
sigma = r**2 + a**2*z**2
|
|
269
|
+
delta = r**2 - 2.*r + a**2
|
|
270
|
+
if mu == 0:
|
|
271
|
+
return -0.5*delta/sigma
|
|
272
|
+
elif mu == 1:
|
|
273
|
+
return -0.5
|
|
274
|
+
elif mu == 2:
|
|
275
|
+
return 0.
|
|
276
|
+
elif mu == 3:
|
|
277
|
+
return 0.5*delta/sigma*a*(1. - z**2)
|
|
278
|
+
else:
|
|
279
|
+
return 0.
|
|
280
|
+
|
|
281
|
+
def tetrad_project_m(a, r, z, mu):
|
|
282
|
+
rhobar = -1./(r + 1j*a*z)
|
|
283
|
+
sigma = r**2 + a**2*z**2
|
|
284
|
+
pref = - rhobar*np.sqrt(0.5*(1. - z**2))
|
|
285
|
+
if mu == 0:
|
|
286
|
+
return -1j*pref*a
|
|
287
|
+
elif mu == 1:
|
|
288
|
+
return 0.
|
|
289
|
+
elif mu == 2:
|
|
290
|
+
return -pref*sigma/(1. - z**2)
|
|
291
|
+
elif mu == 3:
|
|
292
|
+
return 1j*pref*(r**2 + a**2)
|
|
293
|
+
else:
|
|
294
|
+
return 0.
|
|
295
|
+
|
|
296
|
+
def kinnersley_tetrad_covector(b, q, r, z, mu):
|
|
297
|
+
if b == 1:
|
|
298
|
+
return tetrad_project_l(q, r, z, mu)
|
|
299
|
+
elif b == 2:
|
|
300
|
+
return tetrad_project_n(q, r, z, mu)
|
|
301
|
+
elif b == 3:
|
|
302
|
+
return tetrad_project_m(q, r, z, mu)
|
|
303
|
+
elif b == 4:
|
|
304
|
+
return np.conj(tetrad_project_m(q, r, z, mu))
|
|
305
|
+
else:
|
|
306
|
+
return 0.
|
|
307
|
+
|
|
308
|
+
def hmunu_BL(gauge, mu, nu, q, r, hab):
|
|
309
|
+
gauge_check(gauge)
|
|
310
|
+
if gauge in S0_gauges:
|
|
311
|
+
e1mu = kinnersley_tetrad_covector(1, q, r, 0, mu)
|
|
312
|
+
e1nu = kinnersley_tetrad_covector(1, q, r, 0, nu)
|
|
313
|
+
e3mu = kinnersley_tetrad_covector(3, q, r, 0, mu)
|
|
314
|
+
e3nu = kinnersley_tetrad_covector(3, q, r, 0, nu)
|
|
315
|
+
h22 = e1mu*e1nu*hab[0]
|
|
316
|
+
h24 = -e1mu*e3nu*hab[1] - e1nu*e3mu*hab[1]
|
|
317
|
+
h44 = e3mu*e3nu*hab[2]
|
|
318
|
+
return (h22.real + 2.*h24.real + 2.*h44.real)
|
|
319
|
+
else:
|
|
320
|
+
e1mu = kinnersley_tetrad_covector(2, q, r, 0, mu)
|
|
321
|
+
e1nu = kinnersley_tetrad_covector(2, q, r, 0, nu)
|
|
322
|
+
e3mu = kinnersley_tetrad_covector(4, q, r, 0, mu)
|
|
323
|
+
e3nu = kinnersley_tetrad_covector(4, q, r, 0, nu)
|
|
324
|
+
h11 = e1mu*e1nu*hab[0]
|
|
325
|
+
h13 = -e1mu*e3nu*hab[1] - e1nu*e3mu*hab[1]
|
|
326
|
+
h33 = e3mu*e3nu*hab[2]
|
|
327
|
+
return (h11.real + 2.*h13.real + 2.*h33.real)
|
pybhpt/radial.py
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
from cybhpt_full import RadialTeukolsky as RadialTeukolskyCython
|
|
2
|
+
from cybhpt_full import available_methods as available_methods_cython
|
|
3
|
+
from cybhpt_full import renormalized_angular_momentum as nu_cython
|
|
4
|
+
from cybhpt_full import renormalized_angular_momentum_monodromy as nu_2_cython
|
|
5
|
+
from cybhpt_full import hypergeo_2F1 as hypergeo_2F1_cython
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
def available_methods():
|
|
9
|
+
"""
|
|
10
|
+
Returns a list of available solution methods.
|
|
11
|
+
"""
|
|
12
|
+
return available_methods_cython()
|
|
13
|
+
|
|
14
|
+
def renormalized_angular_momentum(s, l, m, a, omega):
|
|
15
|
+
return nu_cython(s, l, m, a, omega)
|
|
16
|
+
|
|
17
|
+
def renormalized_angular_momentum_monodromy(s, l, m, a, omega, la):
|
|
18
|
+
return nu_2_cython(s, l, m, a, omega, la)
|
|
19
|
+
|
|
20
|
+
def hypergeo_2F1(a, b, c, x):
|
|
21
|
+
return hypergeo_2F1_cython(a, b, c, x)
|
|
22
|
+
|
|
23
|
+
class RadialTeukolsky:
|
|
24
|
+
"""A class for solving the homogeneous radial Teukolsky equation.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
s : int
|
|
29
|
+
The spin weight of the field
|
|
30
|
+
j : int
|
|
31
|
+
The spheroidal harmonic mode number
|
|
32
|
+
m : int
|
|
33
|
+
The azimuthal harmonic mode number
|
|
34
|
+
a : float
|
|
35
|
+
The black hole spin parameter
|
|
36
|
+
omega : float
|
|
37
|
+
The frequency of the mode
|
|
38
|
+
r : numpy.ndarray
|
|
39
|
+
A numpy array of radial points at which to evaluate the solution
|
|
40
|
+
|
|
41
|
+
Attributes
|
|
42
|
+
----------
|
|
43
|
+
radialpoints : numpy.ndarray
|
|
44
|
+
A numpy array of radial points at which the solution is evaluated.
|
|
45
|
+
base : RadialTeukolskyCython
|
|
46
|
+
The underlying Cython object that performs the computations.
|
|
47
|
+
nsamples : int
|
|
48
|
+
The number of radial points in the radialpoints array.
|
|
49
|
+
|
|
50
|
+
Properties
|
|
51
|
+
----------
|
|
52
|
+
blackholespin : float
|
|
53
|
+
The black hole spin parameter.
|
|
54
|
+
spinweight : int
|
|
55
|
+
The spin weight of the field.
|
|
56
|
+
s : int
|
|
57
|
+
Alias for spinweight.
|
|
58
|
+
spheroidalmode : int
|
|
59
|
+
The spheroidal harmonic mode number.
|
|
60
|
+
j : int
|
|
61
|
+
Alias for spheroidalmode.
|
|
62
|
+
azimuthalmode : int
|
|
63
|
+
The azimuthal harmonic mode number.
|
|
64
|
+
m : int
|
|
65
|
+
Alias for azimuthalmode.
|
|
66
|
+
frequency : float
|
|
67
|
+
The frequency of the mode.
|
|
68
|
+
mode_frequency : float
|
|
69
|
+
Alias for frequency.
|
|
70
|
+
omega : float
|
|
71
|
+
Alias for frequency.
|
|
72
|
+
eigenvalue : float
|
|
73
|
+
The spheroidal eigenvalue of the radial Teukolsky equation.
|
|
74
|
+
|
|
75
|
+
Methods
|
|
76
|
+
-------
|
|
77
|
+
solveboundarycondition(method)
|
|
78
|
+
Solves the boundary condition for the radial Teukolsky equation.
|
|
79
|
+
setboundarycondition(bc, R, Rp, r)
|
|
80
|
+
Sets the boundary condition for the radial Teukolsky equation.
|
|
81
|
+
solve(method="AUTO", bc=None)
|
|
82
|
+
Solves the radial Teukolsky equation.
|
|
83
|
+
flipspinweight()
|
|
84
|
+
Flips the spin weight of the field.
|
|
85
|
+
radialpoint(pos)
|
|
86
|
+
Returns the radial point at the given position.
|
|
87
|
+
boundarypoint(bc)
|
|
88
|
+
Returns the boundary point for the given boundary condition.
|
|
89
|
+
boundarysolution(bc)
|
|
90
|
+
Returns the solution at the boundary for the given boundary condition.
|
|
91
|
+
boundaryderivative(bc)
|
|
92
|
+
Returns the derivative at the boundary for the given boundary condition.
|
|
93
|
+
radialsolution(bc, pos)
|
|
94
|
+
Returns the solution at the radial point for the given boundary condition and position.
|
|
95
|
+
radialderivative(bc, pos)
|
|
96
|
+
Returns the derivative at the radial point for the given boundary condition and position.
|
|
97
|
+
radialderivative2(bc, pos)
|
|
98
|
+
Returns the second derivative at the radial point for the given boundary condition and position.
|
|
99
|
+
radialsolutions(bc)
|
|
100
|
+
Returns the solutions at all radial points for the given boundary condition.
|
|
101
|
+
radialderivatives(bc)
|
|
102
|
+
Returns the derivatives at all radial points for the given boundary condition.
|
|
103
|
+
radialderivatives2(bc)
|
|
104
|
+
Returns the second derivatives at all radial points for the given boundary condition.
|
|
105
|
+
__call__(bc, deriv=0)
|
|
106
|
+
Returns the solutions, first derivatives, or second derivatives at all radial points for the given boundary condition.
|
|
107
|
+
The `deriv` parameter specifies which derivative to return: 0 for solutions,
|
|
108
|
+
1 for first derivatives, and 2 for second derivatives. If `deriv` is not 0, 1, or 2, a ValueError is raised.
|
|
109
|
+
"""
|
|
110
|
+
def __init__(self, s, j, m, a, omega, r):
|
|
111
|
+
if a < 0 or a > 1:
|
|
112
|
+
raise ValueError(f"Black hole spin parameter {a} must be in the range [0, 1].")
|
|
113
|
+
if j < np.abs(m):
|
|
114
|
+
raise ValueError(f"Spheroidal harmonic mode number {j} must be greater than or equal to the absolute value of azimuthal harmonic mode number {m}.")
|
|
115
|
+
if np.any(r <= 1 + np.sqrt(1 - a**2)):
|
|
116
|
+
raise ValueError(f"Radial point {r} must be greater than horizon radius r_+ = {1 + np.sqrt(1 - a**2)}.")
|
|
117
|
+
if isinstance(r, list) or (isinstance(r, np.ndarray) and r.ndim > 0):
|
|
118
|
+
self.radialpoints = np.asarray(r)
|
|
119
|
+
self.nsamples = self.radialpoints.shape[0]
|
|
120
|
+
else:
|
|
121
|
+
raise AttributeError("Radial points must be a list or a numpy array.")
|
|
122
|
+
|
|
123
|
+
if self.nsamples == 0:
|
|
124
|
+
raise ValueError("Radial points array is empty.")
|
|
125
|
+
self.base = RadialTeukolskyCython(a, s, j, m, omega, self.radialpoints)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def blackholespin(self):
|
|
130
|
+
return self.base.blackholespin
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def spinweight(self):
|
|
134
|
+
return self.base.spinweight
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def s(self):
|
|
138
|
+
return self.spinweight
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def spheroidalmode(self):
|
|
142
|
+
return self.base.spheroidalmode
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def j(self):
|
|
146
|
+
return self.spheroidalmode
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def azimuthalmode(self):
|
|
150
|
+
return self.base.azimuthalmode
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def m(self):
|
|
154
|
+
return self.azimuthalmode
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def frequency(self):
|
|
158
|
+
return self.base.frequency
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def mode_frequency(self):
|
|
162
|
+
return self.frequency
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def omega(self):
|
|
166
|
+
return self.frequency
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def eigenvalue(self):
|
|
170
|
+
return self.base.eigenvalue
|
|
171
|
+
|
|
172
|
+
def solveboundarycondition(self, method):
|
|
173
|
+
"""Solves the boundary condition for the radial Teukolsky equation.
|
|
174
|
+
|
|
175
|
+
Parameters
|
|
176
|
+
----------
|
|
177
|
+
method : str
|
|
178
|
+
The method to use for solving the boundary condition. Default is "AUTO".
|
|
179
|
+
"""
|
|
180
|
+
self.base.solve_bc(method)
|
|
181
|
+
|
|
182
|
+
def setboundarycondition(self, bc, R, Rp, r):
|
|
183
|
+
"""Sets the boundary condition for the radial Teukolsky equation.
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
bc : str
|
|
188
|
+
The boundary condition to set. Can be "In" for horizon or "Up" for infinity.
|
|
189
|
+
R : float
|
|
190
|
+
The boundary condition function value at the radial point.
|
|
191
|
+
Rp : float
|
|
192
|
+
The derivative of the boundary condition function at the radial point.
|
|
193
|
+
r : float
|
|
194
|
+
The radial point at which the boundary condition is defined.
|
|
195
|
+
"""
|
|
196
|
+
self.base.set_bc(bc, R, Rp, r)
|
|
197
|
+
|
|
198
|
+
def solve(self, method = "AUTO", bc = None):
|
|
199
|
+
"""Solves the radial Teukolsky equation.
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
method : str, optional
|
|
204
|
+
The method to use for solving the equation. Default is "AUTO".
|
|
205
|
+
bc : str, optional
|
|
206
|
+
Specifies which homogeneous solutions to compute. If None, both "In" (horizon) and "Up" (infinity) solutions are computed.
|
|
207
|
+
If "In", only the horizon solution is computed. If "Up", only the infinity solution is computed.
|
|
208
|
+
"""
|
|
209
|
+
if bc is None:
|
|
210
|
+
self.base.solve(method, "None")
|
|
211
|
+
else:
|
|
212
|
+
self.base.solve(method, bc)
|
|
213
|
+
|
|
214
|
+
def flipspinweight(self):
|
|
215
|
+
"""Flips the sign of the spin weight of the field."""
|
|
216
|
+
self.base.flip_spinweight()
|
|
217
|
+
|
|
218
|
+
def radialpoint(self, pos):
|
|
219
|
+
"""Returns the radial point at the given position.
|
|
220
|
+
Parameters
|
|
221
|
+
----------
|
|
222
|
+
pos : float
|
|
223
|
+
The position at which to evaluate the radial point.
|
|
224
|
+
Returns
|
|
225
|
+
-------
|
|
226
|
+
float
|
|
227
|
+
The radial point at the given position.
|
|
228
|
+
"""
|
|
229
|
+
return self.base.radialpoint(pos)
|
|
230
|
+
|
|
231
|
+
def boundarypoint(self, bc):
|
|
232
|
+
"""
|
|
233
|
+
Returns the boundary point for the given boundary condition.
|
|
234
|
+
Parameters
|
|
235
|
+
----------
|
|
236
|
+
bc : str
|
|
237
|
+
The boundary condition to evaluate. Can be "In" for horizon or "Up" for infinity.
|
|
238
|
+
Returns
|
|
239
|
+
-------
|
|
240
|
+
float
|
|
241
|
+
The boundary point corresponding to the specified boundary condition.
|
|
242
|
+
"""
|
|
243
|
+
return self.base.boundarypoint(bc)
|
|
244
|
+
|
|
245
|
+
def boundarysolution(self, bc):
|
|
246
|
+
"""Returns the solution at the boundary for the given boundary condition.
|
|
247
|
+
Parameters
|
|
248
|
+
----------
|
|
249
|
+
bc : str
|
|
250
|
+
The boundary condition to evaluate. Can be "In" for horizon or "Up" for infinity.
|
|
251
|
+
Returns
|
|
252
|
+
-------
|
|
253
|
+
float
|
|
254
|
+
The solution at the boundary corresponding to the specified boundary condition.
|
|
255
|
+
"""
|
|
256
|
+
return self.base.boundarysolution(bc)
|
|
257
|
+
|
|
258
|
+
def boundaryderivative(self, bc):
|
|
259
|
+
"""Returns the derivative at the boundary for the given boundary condition.
|
|
260
|
+
Parameters
|
|
261
|
+
----------
|
|
262
|
+
bc : str
|
|
263
|
+
The boundary condition to evaluate. Can be "In" for horizon or "Up" for infinity.
|
|
264
|
+
Returns
|
|
265
|
+
-------
|
|
266
|
+
float
|
|
267
|
+
The derivative at the boundary corresponding to the specified boundary condition.
|
|
268
|
+
"""
|
|
269
|
+
return self.base.boundaryderivative(bc)
|
|
270
|
+
|
|
271
|
+
def radialsolution(self, bc, pos):
|
|
272
|
+
"""Returns the solution at the radial point for the given homogeneous solution and position.
|
|
273
|
+
Parameters
|
|
274
|
+
----------
|
|
275
|
+
bc : str
|
|
276
|
+
The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
|
|
277
|
+
pos : float
|
|
278
|
+
The position at which to evaluate the solution.
|
|
279
|
+
Returns
|
|
280
|
+
-------
|
|
281
|
+
float
|
|
282
|
+
The solution at the radial point corresponding to the specified boundary condition and position.
|
|
283
|
+
"""
|
|
284
|
+
return self.base.solution(bc, pos)
|
|
285
|
+
|
|
286
|
+
def radialderivative(self, bc, pos):
|
|
287
|
+
"""Returns the derivative at the radial point for the given homogeneous solution and position.
|
|
288
|
+
Parameters
|
|
289
|
+
----------
|
|
290
|
+
bc : str
|
|
291
|
+
The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
|
|
292
|
+
pos : float
|
|
293
|
+
The position at which to evaluate the solution.
|
|
294
|
+
Returns
|
|
295
|
+
-------
|
|
296
|
+
float
|
|
297
|
+
The solution at the radial point corresponding to the specified boundary condition and position.
|
|
298
|
+
"""
|
|
299
|
+
return self.base.derivative(bc, pos)
|
|
300
|
+
|
|
301
|
+
def radialderivative2(self, bc, pos):
|
|
302
|
+
"""Returns the second derivative at the radial point for the given homogeneous solution and position.
|
|
303
|
+
Parameters
|
|
304
|
+
----------
|
|
305
|
+
bc : str
|
|
306
|
+
The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
|
|
307
|
+
pos : float
|
|
308
|
+
The position at which to evaluate the solution.
|
|
309
|
+
Returns
|
|
310
|
+
-------
|
|
311
|
+
float
|
|
312
|
+
The solution at the radial point corresponding to the specified boundary condition and position.
|
|
313
|
+
"""
|
|
314
|
+
return self.base.derivative2(bc, pos)
|
|
315
|
+
|
|
316
|
+
def radialsolutions(self, bc):
|
|
317
|
+
"""Returns a homogeneous solution at all radial points.
|
|
318
|
+
Parameters
|
|
319
|
+
----------
|
|
320
|
+
bc : str
|
|
321
|
+
The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
|
|
322
|
+
Returns
|
|
323
|
+
-------
|
|
324
|
+
numpy.ndarray
|
|
325
|
+
A numpy array of solutions at all radial points corresponding to the specified boundary condition.
|
|
326
|
+
"""
|
|
327
|
+
return np.array([self.base.solution(bc, i) for i in range(self.nsamples)])
|
|
328
|
+
|
|
329
|
+
def radialderivatives(self, bc):
|
|
330
|
+
"""Returns the radial derivative at all radial points.
|
|
331
|
+
Parameters
|
|
332
|
+
----------
|
|
333
|
+
bc : str
|
|
334
|
+
The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
|
|
335
|
+
Returns
|
|
336
|
+
-------
|
|
337
|
+
numpy.ndarray
|
|
338
|
+
A numpy array of solutions at all radial points corresponding to the specified boundary condition.
|
|
339
|
+
"""
|
|
340
|
+
return np.array([self.base.derivative(bc, i) for i in range(self.nsamples)])
|
|
341
|
+
|
|
342
|
+
def radialderivatives2(self, bc):
|
|
343
|
+
"""Returns the second radial derivative at all radial points.
|
|
344
|
+
Parameters
|
|
345
|
+
----------
|
|
346
|
+
bc : str
|
|
347
|
+
The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
|
|
348
|
+
Returns
|
|
349
|
+
-------
|
|
350
|
+
numpy.ndarray
|
|
351
|
+
A numpy array of solutions at all radial points corresponding to the specified boundary condition.
|
|
352
|
+
"""
|
|
353
|
+
return np.array([self.base.derivative2(bc, i) for i in range(self.nsamples)])
|
|
354
|
+
|
|
355
|
+
def __call__(self, bc, deriv = 0):
|
|
356
|
+
"""Returns the solutions, first derivatives, or second derivatives at all radial points for the given boundary condition.
|
|
357
|
+
|
|
358
|
+
Parameters
|
|
359
|
+
----------
|
|
360
|
+
bc : str
|
|
361
|
+
The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
|
|
362
|
+
deriv : int, optional
|
|
363
|
+
Specifies which derivative to return: 0 for solutions, 1 for first derivatives, and 2 for second derivatives.
|
|
364
|
+
Default is 0 (solutions).
|
|
365
|
+
Returns
|
|
366
|
+
-------
|
|
367
|
+
numpy.ndarray
|
|
368
|
+
A numpy array of solutions, first derivatives, or second derivatives at all radial points corresponding to the specified boundary condition.
|
|
369
|
+
Raises
|
|
370
|
+
------
|
|
371
|
+
ValueError
|
|
372
|
+
If `deriv` is not 0, 1, or 2.
|
|
373
|
+
"""
|
|
374
|
+
if deriv == 0:
|
|
375
|
+
return self.radialsolutions(bc)
|
|
376
|
+
elif deriv == 1:
|
|
377
|
+
return self.radialderivatives(bc)
|
|
378
|
+
elif deriv == 2:
|
|
379
|
+
return self.radialderivatives2(bc)
|
|
380
|
+
else:
|
|
381
|
+
raise ValueError("RadialTeukolsky only solves up to the second derivative")
|