pybhpt 0.9.10__cp313-cp313-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.
- cybhpt_full.cpython-313-x86_64-linux-musl.so +0 -0
- pybhpt/__init__.py +0 -0
- pybhpt/flux.py +164 -0
- pybhpt/geo.py +910 -0
- pybhpt/hertz.py +402 -0
- pybhpt/metric.py +326 -0
- pybhpt/radial.py +444 -0
- pybhpt/redshift.py +19 -0
- pybhpt/swsh.py +659 -0
- pybhpt/teuk.py +492 -0
- pybhpt-0.9.10.dist-info/METADATA +151 -0
- pybhpt-0.9.10.dist-info/RECORD +18 -0
- pybhpt-0.9.10.dist-info/WHEEL +5 -0
- pybhpt-0.9.10.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/geo.py
ADDED
|
@@ -0,0 +1,910 @@
|
|
|
1
|
+
from cybhpt_full import KerrGeodesic as _KerrGeodesicCython
|
|
2
|
+
from cybhpt_full import _kerr_geo_V01, _kerr_geo_V02, _kerr_geo_V11, _kerr_geo_V22, _kerr_geo_V31, _kerr_geo_V32
|
|
3
|
+
from cybhpt_full import _kerr_mino_frequencies_wrapper, _kerr_orbital_constants_wrapper, _kerr_orbital_constants_array_wrapper, _kerr_kepler_parameters_wrapper, _kerr_kepler_parameters_array_wrapper
|
|
4
|
+
from cybhpt_full import _jacobian_ELQ_to_pex_wrapper, _jacobian_ELQ_to_pex_array_wrapper, _jacobian_pex_to_ELQ_wrapper, _jacobian_pex_to_ELQ_array_wrapper
|
|
5
|
+
import numpy as np
|
|
6
|
+
import numpy.typing as npt
|
|
7
|
+
from typing import Union
|
|
8
|
+
|
|
9
|
+
# Define a type alias for convenience
|
|
10
|
+
NumericArray = npt.NDArray[np.float64]
|
|
11
|
+
ScalarOrArray = Union[float, NumericArray]
|
|
12
|
+
|
|
13
|
+
def kerrgeo_Vt_radial(a: float, En: float, Lz: float, Q: float, r: float) -> float:
|
|
14
|
+
"""
|
|
15
|
+
The radial part of the potential Vt for the geodesic evolution of $t_p$.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
a : float
|
|
20
|
+
The black hole spin parameter.
|
|
21
|
+
En : float
|
|
22
|
+
The orbital energy of the particle.
|
|
23
|
+
Lz : float
|
|
24
|
+
The z-component of the orbital angular momentum of the particle.
|
|
25
|
+
Q : float
|
|
26
|
+
The Carter constant of the particle.
|
|
27
|
+
r : float
|
|
28
|
+
The radial coordinate.
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
float
|
|
33
|
+
The value of the radial potential Vt at the given parameters.
|
|
34
|
+
"""
|
|
35
|
+
return _kerr_geo_V01(a, En, Lz, Q, r)
|
|
36
|
+
|
|
37
|
+
def kerrgeo_Vt_polar(a: float, En: float, Lz: float, Q: float, theta: float) -> float:
|
|
38
|
+
"""
|
|
39
|
+
The polar part of the potential Vt for the geodesic evolution of $t_p$.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
a : float
|
|
44
|
+
The black hole spin parameter.
|
|
45
|
+
En : float
|
|
46
|
+
The orbital energy of the particle.
|
|
47
|
+
Lz : float
|
|
48
|
+
The z-component of the orbital angular momentum of the particle.
|
|
49
|
+
Q : float
|
|
50
|
+
The Carter constant of the particle.
|
|
51
|
+
theta : float
|
|
52
|
+
The polar angle coordinate.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
float
|
|
57
|
+
The value of the polar potential Vt at the given parameters.
|
|
58
|
+
"""
|
|
59
|
+
return _kerr_geo_V02(a, En, Lz, Q, theta)
|
|
60
|
+
|
|
61
|
+
def kerrgeo_Vr(a: float, En: float, Lz: float, Q: float, r: float) -> float:
|
|
62
|
+
"""
|
|
63
|
+
The (squared) radial potential Vr for the geodesic evolution of $r_p$.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
a : float
|
|
68
|
+
The black hole spin parameter.
|
|
69
|
+
En : float
|
|
70
|
+
The orbital energy of the particle.
|
|
71
|
+
Lz : float
|
|
72
|
+
The z-component of the orbital angular momentum of the particle.
|
|
73
|
+
Q : float
|
|
74
|
+
The Carter constant of the particle.
|
|
75
|
+
r : float
|
|
76
|
+
The radial coordinate.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
float
|
|
81
|
+
The value of the radial potential Vr at the given parameters.
|
|
82
|
+
"""
|
|
83
|
+
return _kerr_geo_V11(a, En, Lz, Q, r)
|
|
84
|
+
|
|
85
|
+
def kerrgeo_Vtheta(a: float, En: float, Lz: float, Q: float, theta: float) -> float:
|
|
86
|
+
"""
|
|
87
|
+
The (squared) polar potential Vtheta for the geodesic evolution of $\theta_p$.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
a : float
|
|
92
|
+
The black hole spin parameter.
|
|
93
|
+
En : float
|
|
94
|
+
The orbital energy of the particle.
|
|
95
|
+
Lz : float
|
|
96
|
+
The z-component of the orbital angular momentum of the particle.
|
|
97
|
+
Q : float
|
|
98
|
+
The Carter constant of the particle.
|
|
99
|
+
theta : float
|
|
100
|
+
The polar angle coordinate.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
float
|
|
105
|
+
The value of the polar potential Vtheta at the given parameters.
|
|
106
|
+
"""
|
|
107
|
+
return _kerr_geo_V22(a, En, Lz, Q, theta)
|
|
108
|
+
|
|
109
|
+
def kerrgeo_Vphi_radial(a: float, En: float, Lz: float, Q: float, r: float) -> float:
|
|
110
|
+
"""
|
|
111
|
+
The (squared) radial potential Vphi for the geodesic evolution of $r_p$.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
a : float
|
|
116
|
+
The black hole spin parameter.
|
|
117
|
+
En : float
|
|
118
|
+
The orbital energy of the particle.
|
|
119
|
+
Lz : float
|
|
120
|
+
The z-component of the orbital angular momentum of the particle.
|
|
121
|
+
Q : float
|
|
122
|
+
The Carter constant of the particle.
|
|
123
|
+
r : float
|
|
124
|
+
The radial coordinate.
|
|
125
|
+
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
float
|
|
129
|
+
The value of the radial potential Vphi at the given parameters.
|
|
130
|
+
"""
|
|
131
|
+
return _kerr_geo_V31(a, En, Lz, Q, r)
|
|
132
|
+
|
|
133
|
+
def kerrgeo_Vphi_polar(a: float, En: float, Lz: float, Q: float, theta: float) -> float:
|
|
134
|
+
"""
|
|
135
|
+
The (squared) polar potential Vphi for the geodesic evolution of $r_p$.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
a : float
|
|
140
|
+
The black hole spin parameter.
|
|
141
|
+
En : float
|
|
142
|
+
The orbital energy of the particle.
|
|
143
|
+
Lz : float
|
|
144
|
+
The z-component of the orbital angular momentum of the particle.
|
|
145
|
+
Q : float
|
|
146
|
+
The Carter constant of the particle.
|
|
147
|
+
theta : float
|
|
148
|
+
The polar angle coordinate.
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
float
|
|
153
|
+
The value of the polar potential Vphi at the given parameters.
|
|
154
|
+
"""
|
|
155
|
+
return _kerr_geo_V32(a, En, Lz, Q, theta)
|
|
156
|
+
|
|
157
|
+
def kerr_mino_frequencies(a: float, p: float, e: float, x: float) -> np.ndarray:
|
|
158
|
+
"""
|
|
159
|
+
Returns the Mino frequencies of a Kerr geodesic.
|
|
160
|
+
|
|
161
|
+
Parameters
|
|
162
|
+
----------
|
|
163
|
+
a : float
|
|
164
|
+
The black hole spin parameter.
|
|
165
|
+
p : float
|
|
166
|
+
The semilatus rectum of the orbit.
|
|
167
|
+
e : float
|
|
168
|
+
The eccentricity of the orbit.
|
|
169
|
+
x : float
|
|
170
|
+
The inclination of the orbit.
|
|
171
|
+
|
|
172
|
+
Returns
|
|
173
|
+
-------
|
|
174
|
+
numpy.ndarray
|
|
175
|
+
The Mino time frequencies of the orbit.
|
|
176
|
+
"""
|
|
177
|
+
return _kerr_mino_frequencies_wrapper(a, p, e, x)
|
|
178
|
+
|
|
179
|
+
def kerr_fundamental_frequencies(a: float, p: float, e: float, x: float) -> NumericArray:
|
|
180
|
+
"""
|
|
181
|
+
Returns the fundamental (time) frequencies of a Kerr geodesic.
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
185
|
+
a : float
|
|
186
|
+
The black hole spin parameter.
|
|
187
|
+
p : float
|
|
188
|
+
The semilatus rectum of the orbit.
|
|
189
|
+
e : float
|
|
190
|
+
The eccentricity of the orbit.
|
|
191
|
+
x : float
|
|
192
|
+
The inclination of the orbit.
|
|
193
|
+
|
|
194
|
+
Returns
|
|
195
|
+
-------
|
|
196
|
+
numpy.ndarray
|
|
197
|
+
The fundamental frequencies of the orbit.
|
|
198
|
+
"""
|
|
199
|
+
Ups = _kerr_mino_frequencies_wrapper(a, p, e, x)
|
|
200
|
+
return Ups[1:]/Ups[0]
|
|
201
|
+
|
|
202
|
+
def kerr_orbital_constants(a: ScalarOrArray,
|
|
203
|
+
p: ScalarOrArray,
|
|
204
|
+
e: ScalarOrArray,
|
|
205
|
+
x: ScalarOrArray) -> NumericArray:
|
|
206
|
+
"""
|
|
207
|
+
Returns the orbital constants of a Kerr geodesic (En, Lz, Qc).
|
|
208
|
+
|
|
209
|
+
Parameters
|
|
210
|
+
----------
|
|
211
|
+
a : float or numpy.ndarray
|
|
212
|
+
The black hole spin parameter.
|
|
213
|
+
p : float or numpy.ndarray
|
|
214
|
+
The semilatus rectum of the orbit.
|
|
215
|
+
e : float or numpy.ndarray
|
|
216
|
+
The eccentricity of the orbit.
|
|
217
|
+
x : float or numpy.ndarray
|
|
218
|
+
The inclination of the orbit.
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
numpy.ndarray
|
|
223
|
+
The orbital constants (En, Lz, Qc) of the orbit.
|
|
224
|
+
"""
|
|
225
|
+
if isinstance(p, (np.ndarray, list)):
|
|
226
|
+
assert isinstance(e, (np.ndarray, list)) and isinstance(x, (np.ndarray, list)), "If p is a numpy array, e and x must also be numpy arrays."
|
|
227
|
+
p = np.asarray(p, dtype=np.float64)
|
|
228
|
+
e = np.asarray(e, dtype=np.float64)
|
|
229
|
+
x = np.asarray(x, dtype=np.float64)
|
|
230
|
+
assert p.shape == e.shape == x.shape, "If p, e, and x are numpy arrays, they must have the same shape."
|
|
231
|
+
if isinstance(a, (np.ndarray, list)):
|
|
232
|
+
a = np.asarray(a, dtype=np.float64)
|
|
233
|
+
assert a.shape == p.shape, "If a is a numpy array, it must have the same shape as p, e, and x."
|
|
234
|
+
else:
|
|
235
|
+
a = np.full(p.shape, a)
|
|
236
|
+
return _kerr_orbital_constants_array_wrapper(a, p, e, x)
|
|
237
|
+
else:
|
|
238
|
+
return _kerr_orbital_constants_wrapper(a, p, e, x)
|
|
239
|
+
|
|
240
|
+
def kerr_kepler_parameters(a: ScalarOrArray,
|
|
241
|
+
En: ScalarOrArray,
|
|
242
|
+
Lz: ScalarOrArray,
|
|
243
|
+
Qc: ScalarOrArray) -> NumericArray:
|
|
244
|
+
"""
|
|
245
|
+
Returns the Keplerian parameters of a Kerr geodesic (p, e, x) given the orbital constants (a, En, Lz, Qc).
|
|
246
|
+
|
|
247
|
+
Parameters
|
|
248
|
+
----------
|
|
249
|
+
a : float or numpy.ndarray
|
|
250
|
+
The black hole spin parameter.
|
|
251
|
+
En : float or numpy.ndarray
|
|
252
|
+
The orbital energy of the particle.
|
|
253
|
+
Lz : float or numpy.ndarray
|
|
254
|
+
The z-component of the orbital angular momentum of the particle.
|
|
255
|
+
Qc : float or numpy.ndarray
|
|
256
|
+
The Carter constant of the particle.
|
|
257
|
+
|
|
258
|
+
Returns
|
|
259
|
+
-------
|
|
260
|
+
numpy.ndarray
|
|
261
|
+
The Keplerian parameters (p, e, x) of the orbit.
|
|
262
|
+
"""
|
|
263
|
+
if isinstance(En, (np.ndarray, list)):
|
|
264
|
+
assert isinstance(Lz, (np.ndarray, list)) and isinstance(Qc, (np.ndarray, list)), "If En is a numpy array, Lz and Qc must also be numpy arrays."
|
|
265
|
+
En = np.asarray(En, dtype=np.float64)
|
|
266
|
+
Lz = np.asarray(Lz, dtype=np.float64)
|
|
267
|
+
Qc = np.asarray(Qc, dtype=np.float64)
|
|
268
|
+
assert En.shape == Lz.shape == Qc.shape, "If En, Lz, and Qc are numpy arrays, they must have the same shape."
|
|
269
|
+
if isinstance(a, (np.ndarray, list)):
|
|
270
|
+
a = np.asarray(a, dtype=np.float64)
|
|
271
|
+
assert a.shape == En.shape, "If a is a numpy array, it must have the same shape as En, Lz, and Qc."
|
|
272
|
+
else:
|
|
273
|
+
a = np.full(En.shape, a)
|
|
274
|
+
return _kerr_kepler_parameters_array_wrapper(a, En, Lz, Qc)
|
|
275
|
+
else:
|
|
276
|
+
return _kerr_kepler_parameters_wrapper(a, En, Lz, Qc)
|
|
277
|
+
|
|
278
|
+
def jacobian_ELQ_to_pex(a: ScalarOrArray,
|
|
279
|
+
p: ScalarOrArray,
|
|
280
|
+
e: ScalarOrArray,
|
|
281
|
+
x: ScalarOrArray) -> NumericArray:
|
|
282
|
+
"""
|
|
283
|
+
Returns the Jacobian matrix of the transformation from (E, Lz, Q) to (p, e, x).
|
|
284
|
+
| dp/dE dp/dLz dp/dQ |
|
|
285
|
+
| de/dE de/dLz de/dQ |
|
|
286
|
+
| dx/dE dx/dLz dx/dQ |
|
|
287
|
+
|
|
288
|
+
Parameters
|
|
289
|
+
----------
|
|
290
|
+
a : float or numpy.ndarray
|
|
291
|
+
The black hole spin parameter.
|
|
292
|
+
p : float or numpy.ndarray
|
|
293
|
+
The semilatus rectum of the orbit.
|
|
294
|
+
e : float or numpy.ndarray
|
|
295
|
+
The eccentricity of the orbit.
|
|
296
|
+
x : float or numpy.ndarray
|
|
297
|
+
The inclination of the orbit.
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
numpy.ndarray
|
|
302
|
+
The Jacobian matrix of the transformation from (E, Lz, Q) to (p, e, x).
|
|
303
|
+
"""
|
|
304
|
+
if isinstance(p, (np.ndarray, list)):
|
|
305
|
+
assert isinstance(e, (np.ndarray, list)) and isinstance(x, (np.ndarray, list)), "If p is a numpy array, e and x must also be numpy arrays."
|
|
306
|
+
p = np.asarray(p, dtype=np.float64)
|
|
307
|
+
e = np.asarray(e, dtype=np.float64)
|
|
308
|
+
x = np.asarray(x, dtype=np.float64)
|
|
309
|
+
assert p.shape == e.shape == x.shape, "If p, e, and x are numpy arrays, they must have the same shape."
|
|
310
|
+
if isinstance(a, (np.ndarray, list)):
|
|
311
|
+
a = np.asarray(a, dtype=np.float64)
|
|
312
|
+
assert a.shape == p.shape, "If a is a numpy array, it must have the same shape as p, e, and x."
|
|
313
|
+
else:
|
|
314
|
+
a = np.full(p.shape, a)
|
|
315
|
+
return _jacobian_ELQ_to_pex_array_wrapper(a, p, e, x)
|
|
316
|
+
else:
|
|
317
|
+
return _jacobian_ELQ_to_pex_wrapper(a, p, e, x)
|
|
318
|
+
|
|
319
|
+
def jacobian_pex_to_ELQ(a: ScalarOrArray,
|
|
320
|
+
p: ScalarOrArray,
|
|
321
|
+
e: ScalarOrArray,
|
|
322
|
+
x: ScalarOrArray) -> NumericArray:
|
|
323
|
+
"""
|
|
324
|
+
Returns the Jacobian matrix of the transformation from (p, e, x) to (E, Lz, Q):
|
|
325
|
+
| dE/dp dE/de dE/dx |
|
|
326
|
+
| dLz/dp dLz/de dLz/dx |
|
|
327
|
+
| dQ/dp dQ/de dQ/dx |
|
|
328
|
+
|
|
329
|
+
Parameters
|
|
330
|
+
----------
|
|
331
|
+
a : float or numpy.ndarray
|
|
332
|
+
The black hole spin parameter.
|
|
333
|
+
p : float or numpy.ndarray
|
|
334
|
+
The semilatus rectum of the orbit.
|
|
335
|
+
e : float or numpy.ndarray
|
|
336
|
+
The eccentricity of the orbit.
|
|
337
|
+
x : float or numpy.ndarray
|
|
338
|
+
The inclination of the orbit.
|
|
339
|
+
|
|
340
|
+
Returns
|
|
341
|
+
-------
|
|
342
|
+
numpy.ndarray
|
|
343
|
+
The Jacobian matrix of the transformation from (p, e, x) to (E, Lz, Q).
|
|
344
|
+
"""
|
|
345
|
+
if isinstance(p, (np.ndarray, list)):
|
|
346
|
+
assert isinstance(e, (np.ndarray, list)) and isinstance(x, (np.ndarray, list)), "If p is a numpy array, e and x must also be numpy arrays."
|
|
347
|
+
p = np.asarray(p, dtype=np.float64)
|
|
348
|
+
e = np.asarray(e, dtype=np.float64)
|
|
349
|
+
x = np.asarray(x, dtype=np.float64)
|
|
350
|
+
assert p.shape == e.shape == x.shape, "If p, e, and x are numpy arrays, they must have the same shape."
|
|
351
|
+
if isinstance(a, (np.ndarray, list)):
|
|
352
|
+
a = np.asarray(a, dtype=np.float64)
|
|
353
|
+
assert a.shape == p.shape, "If a is a numpy array, it must have the same shape as p, e, and x."
|
|
354
|
+
else:
|
|
355
|
+
a = np.full(p.shape, a)
|
|
356
|
+
return _jacobian_pex_to_ELQ_array_wrapper(a, p, e, x)
|
|
357
|
+
else:
|
|
358
|
+
return _jacobian_pex_to_ELQ_wrapper(a, p, e, x)
|
|
359
|
+
|
|
360
|
+
def is_power_of_two(n: int) -> bool:
|
|
361
|
+
return n > 0 and (n & (n - 1)) == 0
|
|
362
|
+
|
|
363
|
+
class KerrGeodesic:
|
|
364
|
+
"""
|
|
365
|
+
Class that produces a Kerr geodesic given the parameters of the orbit.
|
|
366
|
+
This class is a wrapper around the Cython implementation of the Kerr geodesic
|
|
367
|
+
and provides a Python interface to the underlying C++ code.
|
|
368
|
+
Parameters
|
|
369
|
+
----------
|
|
370
|
+
a : float
|
|
371
|
+
The black hole spin parameter.
|
|
372
|
+
p : float
|
|
373
|
+
The semilatus rectum of the orbit.
|
|
374
|
+
e : float
|
|
375
|
+
The eccentricity of the orbit.
|
|
376
|
+
x : float
|
|
377
|
+
The inclination of the orbit.
|
|
378
|
+
nsamples : int
|
|
379
|
+
The number of samples to use for the geodesic. Must be a power of two. Default is 256.
|
|
380
|
+
|
|
381
|
+
Attributes
|
|
382
|
+
----------
|
|
383
|
+
blackholespin : float
|
|
384
|
+
The black hole spin parameter.
|
|
385
|
+
semilatusrectum : float
|
|
386
|
+
The semilatus rectum of the orbit.
|
|
387
|
+
eccentricity : float
|
|
388
|
+
The eccentricity of the orbit.
|
|
389
|
+
inclination : float
|
|
390
|
+
The inclination of the orbit.
|
|
391
|
+
orbitalenergy : float
|
|
392
|
+
The orbital energy En of the orbit.
|
|
393
|
+
orbitalangularmomentum : float
|
|
394
|
+
Th z-component of the orbital angular momentum Lz of the orbit.
|
|
395
|
+
carterconstant : float
|
|
396
|
+
The Carter constant Qc of the orbit.
|
|
397
|
+
orbitalconstants : numpy.ndarray
|
|
398
|
+
The orbital constants (En, Lz, Qc) of the orbit.
|
|
399
|
+
radialroots : numpy.ndarray
|
|
400
|
+
The roots of the radial equation.
|
|
401
|
+
polarroots : numpy.ndarray
|
|
402
|
+
The roots of the polar equation.
|
|
403
|
+
minofrequencies : numpy.ndarray
|
|
404
|
+
The orbital frequencies with respect to Mino time.
|
|
405
|
+
timefrequencies : numpy.ndarray
|
|
406
|
+
The orbital frequencies with respect to the time coordinate.
|
|
407
|
+
frequencies : numpy.ndarray
|
|
408
|
+
The (coordinate time) frequencies of the orbit.
|
|
409
|
+
carterfrequencies : numpy.ndarray
|
|
410
|
+
The frequencies for computing Carter constant fluxes.
|
|
411
|
+
timeradialfourier : numpy.ndarray
|
|
412
|
+
The Fourier coefficients of coordinate time with respect to the radial Mino phase.
|
|
413
|
+
timepolarfourier : numpy.ndarray
|
|
414
|
+
The Fourier coefficients of coordinate time with respect to the polar Mino phase.
|
|
415
|
+
radialfourier : numpy.ndarray
|
|
416
|
+
The Fourier coefficients of radial position with respect to the radial Mino phase.
|
|
417
|
+
polarfourier : numpy.ndarray
|
|
418
|
+
The Fourier coefficients of polar position with respect to the polar Mino phase.
|
|
419
|
+
azimuthalradialfourier : numpy.ndarray
|
|
420
|
+
The Fourier coefficients of azimuthal position with respect to the radial Mino phase.
|
|
421
|
+
azimuthalpolarfourier : numpy.ndarray
|
|
422
|
+
The Fourier coefficients of azimuthal position with respect to the polar Mino phase.
|
|
423
|
+
"""
|
|
424
|
+
def __init__(self, a, p, e, x, nsamples = 2**8):
|
|
425
|
+
if a < 0 or a > 1:
|
|
426
|
+
raise ValueError(f"Black hole spin parameter {a} must be in the range [0, 1].")
|
|
427
|
+
if not is_power_of_two(nsamples):
|
|
428
|
+
raise ValueError(f"Number of samples {nsamples} must be a power of 2.")
|
|
429
|
+
|
|
430
|
+
self.base = _KerrGeodesicCython(a, p, e, x, nsamples)
|
|
431
|
+
"""The base class that contains the Cython implementation of the Kerr geodesic."""
|
|
432
|
+
self.timeradial = self.base.get_time_accumulation(1)
|
|
433
|
+
self.timepolar = self.base.get_time_accumulation(2)
|
|
434
|
+
self.radialpoints = self.base.get_radial_points()
|
|
435
|
+
self.polarpoints = self.base.get_polar_points()
|
|
436
|
+
self.azimuthalradial = self.base.get_azimuthal_accumulation(1)
|
|
437
|
+
self.azimuthalpolar = self.base.get_azimuthal_accumulation(2)
|
|
438
|
+
self.nsamples = self.base.nsamples
|
|
439
|
+
|
|
440
|
+
if np.isnan(self.frequencies).any():
|
|
441
|
+
raise ValueError(f"Orbital parameters (a, p, e, x) = {self.apex} do not represent a valid bound non-plunging orbit.")
|
|
442
|
+
|
|
443
|
+
@property
|
|
444
|
+
def blackholespin(self):
|
|
445
|
+
"""
|
|
446
|
+
The black hole spin parameter.
|
|
447
|
+
"""
|
|
448
|
+
return self.base.blackholespin
|
|
449
|
+
|
|
450
|
+
@property
|
|
451
|
+
def semilatusrectum(self):
|
|
452
|
+
"""
|
|
453
|
+
The semilatus rectum of the orbit.
|
|
454
|
+
"""
|
|
455
|
+
return self.base.semilatusrectum
|
|
456
|
+
|
|
457
|
+
@property
|
|
458
|
+
def eccentricity(self):
|
|
459
|
+
"""
|
|
460
|
+
The eccentricity of the orbit.
|
|
461
|
+
"""
|
|
462
|
+
return self.base.eccentricity
|
|
463
|
+
|
|
464
|
+
@property
|
|
465
|
+
def inclination(self):
|
|
466
|
+
"""
|
|
467
|
+
The cosine of the inclination angle of the orbit with respect to the equatorial plane.
|
|
468
|
+
"""
|
|
469
|
+
return self.base.inclination
|
|
470
|
+
|
|
471
|
+
@property
|
|
472
|
+
def a(self):
|
|
473
|
+
"""
|
|
474
|
+
The black hole spin parameter.
|
|
475
|
+
"""
|
|
476
|
+
return self.blackholespin
|
|
477
|
+
|
|
478
|
+
@property
|
|
479
|
+
def p(self):
|
|
480
|
+
"""
|
|
481
|
+
The semilatus rectum of the orbit.
|
|
482
|
+
"""
|
|
483
|
+
return self.semilatusrectum
|
|
484
|
+
|
|
485
|
+
@property
|
|
486
|
+
def e(self):
|
|
487
|
+
"""
|
|
488
|
+
The eccentricity of the orbit.
|
|
489
|
+
"""
|
|
490
|
+
return self.eccentricity
|
|
491
|
+
|
|
492
|
+
@property
|
|
493
|
+
def x(self):
|
|
494
|
+
"""
|
|
495
|
+
The inclination of the orbit.
|
|
496
|
+
"""
|
|
497
|
+
return self.inclination
|
|
498
|
+
|
|
499
|
+
@property
|
|
500
|
+
def apex(self):
|
|
501
|
+
"""
|
|
502
|
+
The parameters of the orbit (a, p, e, x).
|
|
503
|
+
"""
|
|
504
|
+
return np.array([self.blackholespin, self.semilatusrectum, self.eccentricity, self.inclination])
|
|
505
|
+
|
|
506
|
+
@property
|
|
507
|
+
def orbitalparameters(self):
|
|
508
|
+
"""
|
|
509
|
+
The parameters of the orbit (a, p, e, x).
|
|
510
|
+
"""
|
|
511
|
+
return self.apex
|
|
512
|
+
|
|
513
|
+
@property
|
|
514
|
+
def orbitalenergy(self):
|
|
515
|
+
"""
|
|
516
|
+
The orbital energy En of the orbit.
|
|
517
|
+
"""
|
|
518
|
+
return self.base.orbitalenergy
|
|
519
|
+
|
|
520
|
+
@property
|
|
521
|
+
def orbitalangularmomentum(self):
|
|
522
|
+
"""
|
|
523
|
+
The z-component of the orbital angular momentum Lz of the orbit.
|
|
524
|
+
"""
|
|
525
|
+
return self.base.orbitalangularmomentum
|
|
526
|
+
|
|
527
|
+
@property
|
|
528
|
+
def carterconstant(self):
|
|
529
|
+
"""
|
|
530
|
+
The Carter constant Qc of the orbit.
|
|
531
|
+
"""
|
|
532
|
+
return self.base.carterconstant
|
|
533
|
+
|
|
534
|
+
@property
|
|
535
|
+
def orbitalconstants(self):
|
|
536
|
+
"""
|
|
537
|
+
The orbital constants (En, Lz, Qc) of the orbit.
|
|
538
|
+
"""
|
|
539
|
+
return np.array([self.orbitalenergy, self.orbitalangularmomentum, self.carterconstant])
|
|
540
|
+
|
|
541
|
+
@property
|
|
542
|
+
def radialroots(self):
|
|
543
|
+
"""
|
|
544
|
+
The roots of the radial equation.
|
|
545
|
+
"""
|
|
546
|
+
return self.base.radialroots
|
|
547
|
+
|
|
548
|
+
@property
|
|
549
|
+
def polarroots(self):
|
|
550
|
+
"""
|
|
551
|
+
The roots of the polar equation.
|
|
552
|
+
"""
|
|
553
|
+
return self.base.polarroots
|
|
554
|
+
|
|
555
|
+
@property
|
|
556
|
+
def minofrequencies(self):
|
|
557
|
+
"""
|
|
558
|
+
The orbital frequencies with respect to Mino time.
|
|
559
|
+
"""
|
|
560
|
+
return self.base.minofrequencies
|
|
561
|
+
|
|
562
|
+
@property
|
|
563
|
+
def timefrequencies(self):
|
|
564
|
+
"""
|
|
565
|
+
The orbital frequencies with respect to the time coordinate.
|
|
566
|
+
"""
|
|
567
|
+
return self.base.timefrequencies
|
|
568
|
+
|
|
569
|
+
@property
|
|
570
|
+
def frequencies(self):
|
|
571
|
+
"""
|
|
572
|
+
The (coordinate time) frequencies of the orbit.
|
|
573
|
+
"""
|
|
574
|
+
return self.timefrequencies
|
|
575
|
+
|
|
576
|
+
@property
|
|
577
|
+
def carterfrequencies(self):
|
|
578
|
+
"""
|
|
579
|
+
The frequencies for computing Carter constant fluxes.
|
|
580
|
+
"""
|
|
581
|
+
return self.base.carterfrequencies
|
|
582
|
+
|
|
583
|
+
@property
|
|
584
|
+
def timeradialfourier(self):
|
|
585
|
+
"""
|
|
586
|
+
The Fourier coefficients of coordinate time with respect to the radial Mino phase.
|
|
587
|
+
"""
|
|
588
|
+
return self.base.get_time_coefficients(1)
|
|
589
|
+
|
|
590
|
+
@property
|
|
591
|
+
def timepolarfourier(self):
|
|
592
|
+
"""
|
|
593
|
+
The Fourier coefficients of coordinate time with respect to the polar Mino phase.
|
|
594
|
+
"""
|
|
595
|
+
return self.base.get_time_coefficients(2)
|
|
596
|
+
|
|
597
|
+
@property
|
|
598
|
+
def radialfourier(self):
|
|
599
|
+
"""
|
|
600
|
+
The Fourier coefficients of radial position with respect to the radial Mino phase.
|
|
601
|
+
"""
|
|
602
|
+
return self.base.get_radial_coefficients()
|
|
603
|
+
|
|
604
|
+
@property
|
|
605
|
+
def polarfourier(self):
|
|
606
|
+
"""
|
|
607
|
+
The Fourier coefficients of polar position with respect to the polar Mino phase.
|
|
608
|
+
"""
|
|
609
|
+
return self.base.get_polar_coefficients()
|
|
610
|
+
|
|
611
|
+
@property
|
|
612
|
+
def azimuthalradialfourier(self):
|
|
613
|
+
"""
|
|
614
|
+
The Fourier coefficients of azimuthal position with respect to the radial Mino phase.
|
|
615
|
+
"""
|
|
616
|
+
return self.base.get_azimuthal_coefficients(1)
|
|
617
|
+
|
|
618
|
+
@property
|
|
619
|
+
def azimuthalpolarfourier(self):
|
|
620
|
+
"""
|
|
621
|
+
The Fourier coefficients of azimuthal position with respect to the polar Mino phase.
|
|
622
|
+
"""
|
|
623
|
+
return self.base.get_azimuthal_coefficients(2)
|
|
624
|
+
|
|
625
|
+
def mode_frequency(self, m, k, n):
|
|
626
|
+
"""
|
|
627
|
+
Returns the frequency of the mode with azimuthal number m, polar number k, and radial number n.
|
|
628
|
+
|
|
629
|
+
Parameters
|
|
630
|
+
----------
|
|
631
|
+
m : int
|
|
632
|
+
The azimuthal number of the mode.
|
|
633
|
+
k : int
|
|
634
|
+
The polar number of the mode.
|
|
635
|
+
n : int
|
|
636
|
+
The radial number of the mode.
|
|
637
|
+
|
|
638
|
+
Returns
|
|
639
|
+
-------
|
|
640
|
+
float
|
|
641
|
+
The frequency of the mode with azimuthal number m, polar number k, and radial number n.
|
|
642
|
+
"""
|
|
643
|
+
return np.dot(np.array([n, k, m]), (self.frequencies))
|
|
644
|
+
|
|
645
|
+
def psi_radial(self, la):
|
|
646
|
+
"""
|
|
647
|
+
Function that returns the radial true anomaly for a given Mino time value.
|
|
648
|
+
|
|
649
|
+
Parameters
|
|
650
|
+
----------
|
|
651
|
+
la : float or numpy.ndarray
|
|
652
|
+
The Mino time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
653
|
+
|
|
654
|
+
Returns
|
|
655
|
+
-------
|
|
656
|
+
numpy.ndarray
|
|
657
|
+
The radial true anomaly for the given Mino time value(s).
|
|
658
|
+
"""
|
|
659
|
+
if isinstance(la, np.ndarray) or isinstance(la, list):
|
|
660
|
+
return self.base.psi_radial_vec(np.array(la))
|
|
661
|
+
else:
|
|
662
|
+
return self.base.psi_radial(la)
|
|
663
|
+
|
|
664
|
+
def psi_polar(self, la):
|
|
665
|
+
"""
|
|
666
|
+
Function that returns the polar Darwin phase for a given Mino time value.
|
|
667
|
+
|
|
668
|
+
Parameters
|
|
669
|
+
----------
|
|
670
|
+
la : float or numpy.ndarray
|
|
671
|
+
The Mino time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
672
|
+
|
|
673
|
+
Returns
|
|
674
|
+
-------
|
|
675
|
+
numpy.ndarray
|
|
676
|
+
The polar Darwin phase for the given Mino time value(s).
|
|
677
|
+
"""
|
|
678
|
+
if isinstance(la, np.ndarray) or isinstance(la, list):
|
|
679
|
+
return self.base.psi_polar_vec(np.array(la))
|
|
680
|
+
else:
|
|
681
|
+
return self.base.psi_polar(la)
|
|
682
|
+
|
|
683
|
+
def psi_radial_of_t(self, t):
|
|
684
|
+
"""
|
|
685
|
+
Function that returns the radial true anomaly for a given time value.
|
|
686
|
+
|
|
687
|
+
Parameters
|
|
688
|
+
----------
|
|
689
|
+
t : float or numpy.ndarray
|
|
690
|
+
The time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
691
|
+
|
|
692
|
+
Returns
|
|
693
|
+
-------
|
|
694
|
+
numpy.ndarray
|
|
695
|
+
The radial true anomaly for the given time value(s).
|
|
696
|
+
"""
|
|
697
|
+
if isinstance(t, np.ndarray) or isinstance(t, list):
|
|
698
|
+
return self.base.psi_radial_time_vec(np.array(t))
|
|
699
|
+
else:
|
|
700
|
+
return self.base.psi_radial_time(t)
|
|
701
|
+
|
|
702
|
+
def psi_polar_of_t(self, t):
|
|
703
|
+
"""
|
|
704
|
+
Function that returns the polar Darwin phase for a given time value.
|
|
705
|
+
|
|
706
|
+
Parameters
|
|
707
|
+
----------
|
|
708
|
+
t : float or numpy.ndarray
|
|
709
|
+
The time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
710
|
+
|
|
711
|
+
Returns
|
|
712
|
+
-------
|
|
713
|
+
numpy.ndarray
|
|
714
|
+
The polar Darwin phase for the given time value(s).
|
|
715
|
+
"""
|
|
716
|
+
if isinstance(t, np.ndarray) or isinstance(t, list):
|
|
717
|
+
return self.base.psi_polar_time_vec(np.array(t))
|
|
718
|
+
else:
|
|
719
|
+
return self.base.psi_polar_time(t)
|
|
720
|
+
|
|
721
|
+
def time_position(self, la):
|
|
722
|
+
"""
|
|
723
|
+
Function that returns the time position for a given Mino time value.
|
|
724
|
+
|
|
725
|
+
Parameters
|
|
726
|
+
----------
|
|
727
|
+
la : float or numpy.ndarray
|
|
728
|
+
The Mino time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
729
|
+
|
|
730
|
+
Returns
|
|
731
|
+
-------
|
|
732
|
+
numpy.ndarray
|
|
733
|
+
The time position for the given Mino time value(s).
|
|
734
|
+
"""
|
|
735
|
+
if isinstance(la, np.ndarray) or isinstance(la, list):
|
|
736
|
+
return self.base.time_position_vec(np.array(la))
|
|
737
|
+
else:
|
|
738
|
+
return self.base.time_position(la)
|
|
739
|
+
|
|
740
|
+
def radial_position(self, la):
|
|
741
|
+
"""
|
|
742
|
+
Function that returns the radial position for a given Mino time value.
|
|
743
|
+
|
|
744
|
+
Parameters
|
|
745
|
+
----------
|
|
746
|
+
la : float or numpy.ndarray
|
|
747
|
+
The Mino time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
748
|
+
|
|
749
|
+
Returns
|
|
750
|
+
-------
|
|
751
|
+
numpy.ndarray
|
|
752
|
+
The radial position for the given Mino time value(s).
|
|
753
|
+
"""
|
|
754
|
+
if isinstance(la, np.ndarray) or isinstance(la, list):
|
|
755
|
+
return self.base.radial_position_vec(np.array(la))
|
|
756
|
+
else:
|
|
757
|
+
return self.base.radial_position(la)
|
|
758
|
+
|
|
759
|
+
def polar_position(self, la):
|
|
760
|
+
"""
|
|
761
|
+
Function that returns the polar position for a given Mino time value.
|
|
762
|
+
|
|
763
|
+
Parameters
|
|
764
|
+
----------
|
|
765
|
+
la : float or numpy.ndarray
|
|
766
|
+
The Mino time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
767
|
+
|
|
768
|
+
Returns
|
|
769
|
+
-------
|
|
770
|
+
numpy.ndarray
|
|
771
|
+
The polar position for the given Mino time value(s).
|
|
772
|
+
"""
|
|
773
|
+
if isinstance(la, np.ndarray) or isinstance(la, list):
|
|
774
|
+
return self.base.polar_position_vec(np.array(la))
|
|
775
|
+
else:
|
|
776
|
+
return self.base.polar_position(la)
|
|
777
|
+
|
|
778
|
+
def azimuthal_position(self, la):
|
|
779
|
+
"""
|
|
780
|
+
Function that returns the azimuthal position for a given Mino time value.
|
|
781
|
+
|
|
782
|
+
Parameters
|
|
783
|
+
----------
|
|
784
|
+
la : float or numpy.ndarray
|
|
785
|
+
The Mino time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
786
|
+
|
|
787
|
+
Returns
|
|
788
|
+
-------
|
|
789
|
+
numpy.ndarray
|
|
790
|
+
The azimuthal position for the given Mino time value(s).
|
|
791
|
+
"""
|
|
792
|
+
if isinstance(la, np.ndarray) or isinstance(la, list):
|
|
793
|
+
return self.base.azimuthal_position_vec(np.array(la))
|
|
794
|
+
else:
|
|
795
|
+
return self.base.azimuthal_position(la)
|
|
796
|
+
|
|
797
|
+
def radial_position_of_t(self, t):
|
|
798
|
+
"""
|
|
799
|
+
Function that returns the radial position for a given Mino time value.
|
|
800
|
+
|
|
801
|
+
Parameters
|
|
802
|
+
----------
|
|
803
|
+
t : float or numpy.ndarray
|
|
804
|
+
The Mino time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
805
|
+
|
|
806
|
+
Returns
|
|
807
|
+
-------
|
|
808
|
+
numpy.ndarray
|
|
809
|
+
The radial position for the given Mino time value(s).
|
|
810
|
+
"""
|
|
811
|
+
if isinstance(t, np.ndarray) or isinstance(t, list):
|
|
812
|
+
return self.base.radial_position_time_vec(np.array(t))
|
|
813
|
+
else:
|
|
814
|
+
return self.base.radial_position_time(t)
|
|
815
|
+
|
|
816
|
+
def polar_position_of_t(self, t):
|
|
817
|
+
"""
|
|
818
|
+
Function that returns the polar position for a given time value.
|
|
819
|
+
|
|
820
|
+
Parameters
|
|
821
|
+
----------
|
|
822
|
+
t : float or numpy.ndarray
|
|
823
|
+
The time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
824
|
+
|
|
825
|
+
Returns
|
|
826
|
+
-------
|
|
827
|
+
numpy.ndarray
|
|
828
|
+
The polar position for the given time value(s).
|
|
829
|
+
"""
|
|
830
|
+
if isinstance(t, np.ndarray) or isinstance(t, list):
|
|
831
|
+
return self.base.polar_position_time_vec(np.array(t))
|
|
832
|
+
else:
|
|
833
|
+
return self.base.polar_position_time(t)
|
|
834
|
+
|
|
835
|
+
def azimuthal_position_of_t(self, t):
|
|
836
|
+
"""
|
|
837
|
+
Function that returns the azimuthal position for a given time value.
|
|
838
|
+
|
|
839
|
+
Parameters
|
|
840
|
+
----------
|
|
841
|
+
t : float or numpy.ndarray
|
|
842
|
+
The time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
843
|
+
|
|
844
|
+
Returns
|
|
845
|
+
-------
|
|
846
|
+
numpy.ndarray
|
|
847
|
+
The azimuthal position for the given time value(s).
|
|
848
|
+
"""
|
|
849
|
+
if isinstance(t, np.ndarray) or isinstance(t, list):
|
|
850
|
+
return self.base.azimuthal_position_time_vec(np.array(t))
|
|
851
|
+
else:
|
|
852
|
+
return self.base.azimuthal_position_time(t)
|
|
853
|
+
|
|
854
|
+
def mino_of_t(self, t):
|
|
855
|
+
"""
|
|
856
|
+
Function that returns the Mino time for a given Boyer-Lindquist time.
|
|
857
|
+
|
|
858
|
+
Parameters
|
|
859
|
+
----------
|
|
860
|
+
t : float or numpy.ndarray
|
|
861
|
+
The Boyer-Lindquist time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
862
|
+
|
|
863
|
+
Returns
|
|
864
|
+
-------
|
|
865
|
+
numpy.ndarray
|
|
866
|
+
The Mino time for the given Boyer-Lindquist time value(s).
|
|
867
|
+
"""
|
|
868
|
+
if isinstance(t, np.ndarray) or isinstance(t, list):
|
|
869
|
+
return self.base.mino_time_vec(np.array(t))
|
|
870
|
+
else:
|
|
871
|
+
return self.base.mino_time(t)
|
|
872
|
+
|
|
873
|
+
def position_of_t(self, t):
|
|
874
|
+
"""
|
|
875
|
+
Function that returns the position vector (r, theta, phi) for a given Boyer-Lindquist time value.
|
|
876
|
+
|
|
877
|
+
Parameters
|
|
878
|
+
----------
|
|
879
|
+
t : float or numpy.ndarray
|
|
880
|
+
The Boyer-Lindquist time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
881
|
+
|
|
882
|
+
Returns
|
|
883
|
+
-------
|
|
884
|
+
numpy.ndarray
|
|
885
|
+
The position vector (r, theta, phi) for the given Boyer-Lindquist time value(s).
|
|
886
|
+
"""
|
|
887
|
+
if isinstance(t, np.ndarray) or isinstance(t, list):
|
|
888
|
+
return self.base.position_time_vec(np.array(t))
|
|
889
|
+
else:
|
|
890
|
+
return self.base.position_time(t)
|
|
891
|
+
|
|
892
|
+
def position(self, la):
|
|
893
|
+
"""
|
|
894
|
+
Function that returns the position vector (t, r, theta, phi) for a given Mino time value.
|
|
895
|
+
Parameters
|
|
896
|
+
----------
|
|
897
|
+
la : float or numpy.ndarray
|
|
898
|
+
The Mino time value(s). If a numpy array is provided, the function will return a numpy array of the same shape.
|
|
899
|
+
Returns
|
|
900
|
+
-------
|
|
901
|
+
numpy.ndarray
|
|
902
|
+
The position vector (t, r, theta, phi) for the given Mino time value(s).
|
|
903
|
+
"""
|
|
904
|
+
if isinstance(la, np.ndarray) or isinstance(la, list):
|
|
905
|
+
return self.base.position_vec(np.array(la))
|
|
906
|
+
else:
|
|
907
|
+
return self.base.position(la)
|
|
908
|
+
|
|
909
|
+
def __call__(self, la):
|
|
910
|
+
return self.position(la)
|