pybhpt 0.9.10__cp312-cp312-macosx_15_0_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-312-darwin.so +0 -0
- pybhpt/.dylibs/libgsl.28.dylib +0 -0
- pybhpt/.dylibs/libgslcblas.0.dylib +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 +16 -0
- pybhpt-0.9.10.dist-info/WHEEL +6 -0
- pybhpt-0.9.10.dist-info/licenses/LICENSE +674 -0
pybhpt/teuk.py
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
from cybhpt_full import _TeukolskyMode as _TeukolskyModeCython
|
|
2
|
+
|
|
3
|
+
class TeukolskyMode:
|
|
4
|
+
"""A class for computing Teukolsky modes sourced by a point-particle orbiting in a Kerr background.
|
|
5
|
+
|
|
6
|
+
Parameters
|
|
7
|
+
----------
|
|
8
|
+
s : int
|
|
9
|
+
The spin weight of the Teukolsky mode.
|
|
10
|
+
j : int
|
|
11
|
+
The spheroidal harmonic mode number.
|
|
12
|
+
m : int
|
|
13
|
+
The azimuthal harmonic mode number.
|
|
14
|
+
k : int
|
|
15
|
+
The polar harmonic mode number.
|
|
16
|
+
n : int
|
|
17
|
+
The radial harmonic mode number.
|
|
18
|
+
geo : KerrGeodesic class instance
|
|
19
|
+
KerrGeodesic object containing the background motion of the point-particle source.
|
|
20
|
+
auto_solve : bool, optional
|
|
21
|
+
If True, the Teukolsky equation is automatically solved upon initialization. Default is False
|
|
22
|
+
|
|
23
|
+
Attributes
|
|
24
|
+
----------
|
|
25
|
+
spinweight : int
|
|
26
|
+
The spin weight of the Teukolsky mode.
|
|
27
|
+
spheroidalmode : int
|
|
28
|
+
The spheroidal harmonic mode number.
|
|
29
|
+
azimuthalmode : int
|
|
30
|
+
The azimuthal harmonic mode number.
|
|
31
|
+
radialmode : int
|
|
32
|
+
The radial harmonic mode number.
|
|
33
|
+
polarmode : int
|
|
34
|
+
The polar harmonic mode number.
|
|
35
|
+
blackholespin : float
|
|
36
|
+
The spin of the black hole in the Kerr background.
|
|
37
|
+
frequency : float
|
|
38
|
+
The frequency of the Teukolsky mode.
|
|
39
|
+
horizonfrequency : float
|
|
40
|
+
The frequency of the mode at the horizon.
|
|
41
|
+
eigenvalue : float
|
|
42
|
+
The spheroidal eigenvalue of the Teukolsky mode.
|
|
43
|
+
mincouplingmode : int
|
|
44
|
+
The minimum l-mode used for coupling the spherical and spheroidal harmonics
|
|
45
|
+
maxcouplingmode : int
|
|
46
|
+
The maximum l-mode used for coupling the spherical and spheroidal harmonics
|
|
47
|
+
j : int
|
|
48
|
+
Alias for spheroidalmode.
|
|
49
|
+
m : int
|
|
50
|
+
Alias for azimuthalmode.
|
|
51
|
+
k : int
|
|
52
|
+
Alias for polarmode.
|
|
53
|
+
n : int
|
|
54
|
+
Alias for radialmode.
|
|
55
|
+
omega : float
|
|
56
|
+
Alias for frequency.
|
|
57
|
+
a : float
|
|
58
|
+
Alias for blackholespin.
|
|
59
|
+
|
|
60
|
+
Methods
|
|
61
|
+
-------
|
|
62
|
+
solve(geo, method = "AUTO", nsamples = 256, teuk = None, swsh = None)
|
|
63
|
+
Solve the Teukolsky equation for the given mode and geodesic.
|
|
64
|
+
flipspinweight()
|
|
65
|
+
Flip the spin weight of the Teukolsky mode.
|
|
66
|
+
flipspinweightandfrequency()
|
|
67
|
+
Flip the spin weight and frequency of the Teukolsky mode.
|
|
68
|
+
couplingcoefficient(l)
|
|
69
|
+
Compute the coupling coefficient for the given l-mode.
|
|
70
|
+
radialpoint(pos)
|
|
71
|
+
Compute the radial point for the given position.
|
|
72
|
+
radialsolution(bc, pos)
|
|
73
|
+
Compute the radial solution for the given boundary condition and position.
|
|
74
|
+
radialderivative(bc, pos)
|
|
75
|
+
Compute the radial derivative for the given boundary condition and position.
|
|
76
|
+
radialderivative2(bc, pos)
|
|
77
|
+
Compute the second radial derivative for the given boundary condition and position.
|
|
78
|
+
homogeneousradialsolution(bc, pos)
|
|
79
|
+
Compute the homogeneous radial solution for the given boundary condition and position.
|
|
80
|
+
homogeneousradialderivative(bc, pos)
|
|
81
|
+
Compute the homogeneous radial derivative for the given boundary condition and position.
|
|
82
|
+
homogeneousradialderivative2(bc, pos)
|
|
83
|
+
Compute the second homogeneous radial derivative for the given boundary condition and position.
|
|
84
|
+
polarpoint(pos)
|
|
85
|
+
Compute the polar point for the given position.
|
|
86
|
+
polarsolution(pos)
|
|
87
|
+
Compute the polar solution for the given position.
|
|
88
|
+
polarderivative(pos)
|
|
89
|
+
Compute the polar derivative for the given position.
|
|
90
|
+
polarderivative2(pos)
|
|
91
|
+
Compute the second polar derivative for the given position.
|
|
92
|
+
amplitude(bc)
|
|
93
|
+
Compute the Teukolsky amplitude for the given boundary condition.
|
|
94
|
+
precision(bc)
|
|
95
|
+
Compute the precision of the Teukolsky amplitude for the given boundary condition.
|
|
96
|
+
"""
|
|
97
|
+
def __init__(self, s, j, m, k, n, geo, auto_solve = False):
|
|
98
|
+
self.base = _TeukolskyModeCython(s, j, m, k, n, geo.base)
|
|
99
|
+
if auto_solve:
|
|
100
|
+
self.solve(geo)
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def spinweight(self):
|
|
104
|
+
return self.base.spinweight
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def spheroidalmode(self):
|
|
108
|
+
return self.base.spheroidalmode
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def azimuthalmode(self):
|
|
112
|
+
return self.base.azimuthalmode
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def radialmode(self):
|
|
116
|
+
return self.base.radialmode
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def polarmode(self):
|
|
120
|
+
return self.base.polarmode
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def blackholespin(self):
|
|
124
|
+
return self.base.blackholespin
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def frequency(self):
|
|
128
|
+
return self.base.frequency
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def horizonfrequency(self):
|
|
132
|
+
return self.base.horizonfrequency
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def eigenvalue(self):
|
|
136
|
+
return self.base.eigenvalue
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def mincouplingmode(self):
|
|
140
|
+
return self.base.mincouplingmode
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def maxcouplingmode(self):
|
|
144
|
+
return self.base.maxcouplingmode
|
|
145
|
+
|
|
146
|
+
# some useful aliases
|
|
147
|
+
@property
|
|
148
|
+
def j(self):
|
|
149
|
+
return self.spheroidalmode
|
|
150
|
+
@property
|
|
151
|
+
def m(self):
|
|
152
|
+
return self.azimuthalmode
|
|
153
|
+
@property
|
|
154
|
+
def k(self):
|
|
155
|
+
return self.polarmode
|
|
156
|
+
@property
|
|
157
|
+
def n(self):
|
|
158
|
+
return self.radialmode
|
|
159
|
+
@property
|
|
160
|
+
def omega(self):
|
|
161
|
+
return self.frequency
|
|
162
|
+
@property
|
|
163
|
+
def a(self):
|
|
164
|
+
return self.blackholespin
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def couplingcoefficients(self):
|
|
168
|
+
return self.base.couplingcoefficients
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def polarpoints(self):
|
|
172
|
+
return self.base.polarpoints
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def polarsolutions(self):
|
|
176
|
+
return self.base.polarsolutions
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def polarderivatives(self):
|
|
180
|
+
return self.base.polarderivatives
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def polarderivatives2(self):
|
|
184
|
+
return self.base.polarderivatives2
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def radialpoints(self):
|
|
188
|
+
return self.base.radialpoints
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def radialsolutions(self):
|
|
192
|
+
return self.base.radialsolutions
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def radialderivatives(self):
|
|
196
|
+
return self.base.radialderivatives
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def radialderivatives2(self):
|
|
200
|
+
return self.base.radialderivatives2
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def homogeneousradialsolutions(self):
|
|
204
|
+
return self.base.homogeneousradialsolutions
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def homogeneousradialderivatives(self):
|
|
208
|
+
return self.base.homogeneousradialderivatives
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def homogeneousradialderivatives2(self):
|
|
212
|
+
return self.base.homogeneousradialderivatives2
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def amplitudes(self):
|
|
216
|
+
return self.base.teukolsky_amplitudes
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def precisions(self):
|
|
220
|
+
return self.base.teukolsky_amplitude_precisions
|
|
221
|
+
|
|
222
|
+
def solve(self, geo, method = "AUTO", nsamples = 256, teuk = None, swsh = None):
|
|
223
|
+
"""Solve the Teukolsky equation for the given mode and geodesic.
|
|
224
|
+
Parameters
|
|
225
|
+
----------
|
|
226
|
+
geo : KerrGeodesic class instance
|
|
227
|
+
KerrGeodesic object containing the background motion of the point-particle source.
|
|
228
|
+
method : str, optional
|
|
229
|
+
The method to use for solving the Teukolsky equation. Default is "AUTO".
|
|
230
|
+
nsamples : int, optional
|
|
231
|
+
The number of samples to use for the solution. Default is 256.
|
|
232
|
+
teuk : RadialTeukolsky, optional
|
|
233
|
+
RadialTeukolsky object to use for constructing the radial Green function. Default is None.
|
|
234
|
+
swsh : SpheroidalHarmonicMode, optional
|
|
235
|
+
SpheroidalHarmonic object to use for coupling with spheroidal harmonics. Default is None.
|
|
236
|
+
|
|
237
|
+
"""
|
|
238
|
+
if teuk is None or swsh is None:
|
|
239
|
+
self.base.solve(geo.base, method, nsamples)
|
|
240
|
+
else:
|
|
241
|
+
self.base.solve(geo.base, method, nsamples, teuk.base, swsh.base)
|
|
242
|
+
|
|
243
|
+
"""
|
|
244
|
+
Flips the spin-weight of the Teukolsky solutions from :math:`s \rightarrow -s`
|
|
245
|
+
"""
|
|
246
|
+
def flipspinweight(self):
|
|
247
|
+
self.base.flip_spinweight()
|
|
248
|
+
|
|
249
|
+
"""
|
|
250
|
+
Flips the spin-weight and frequency of the Teukolsky solutions from :math:`s \rightarrow -s` and :math:`\omega \rightarrow -\omega`
|
|
251
|
+
"""
|
|
252
|
+
def flipspinweightandfrequency(self):
|
|
253
|
+
"""
|
|
254
|
+
Flips the spin-weight and frequency of the Teukolsky solutions from :math:`s \rightarrow -s` and :math:`\omega \rightarrow -\omega`
|
|
255
|
+
"""
|
|
256
|
+
self.base.flip_spinweight_frequency()
|
|
257
|
+
|
|
258
|
+
def couplingcoefficient(self, l):
|
|
259
|
+
"""
|
|
260
|
+
Spherical-spheroidal mixing coefficient between a spherical harmonic $l$ mode with a spheroidal $j$ mode.
|
|
261
|
+
|
|
262
|
+
Parameters
|
|
263
|
+
----------
|
|
264
|
+
l : int
|
|
265
|
+
Spherical harmonic mode.
|
|
266
|
+
|
|
267
|
+
Returns
|
|
268
|
+
-------
|
|
269
|
+
float
|
|
270
|
+
The coupling coefficient between the spherical harmonic mode `l` and the spheroidal harmonic mode `j`.
|
|
271
|
+
"""
|
|
272
|
+
return self.base.couplingcoefficient(l)
|
|
273
|
+
|
|
274
|
+
def radialpoint(self, pos):
|
|
275
|
+
"""
|
|
276
|
+
The radial point for the given position `pos`.
|
|
277
|
+
|
|
278
|
+
Parameters
|
|
279
|
+
----------
|
|
280
|
+
pos : int
|
|
281
|
+
The radial position.
|
|
282
|
+
|
|
283
|
+
Returns
|
|
284
|
+
-------
|
|
285
|
+
float
|
|
286
|
+
The radial point at the given position `pos`.
|
|
287
|
+
"""
|
|
288
|
+
return self.base.radialpoint(pos)
|
|
289
|
+
|
|
290
|
+
def radialsolution(self, bc, pos):
|
|
291
|
+
"""
|
|
292
|
+
The extended homogeneous radial solution for the given boundary condition `bc` and position `pos`.
|
|
293
|
+
|
|
294
|
+
Parameters
|
|
295
|
+
----------
|
|
296
|
+
bc : str
|
|
297
|
+
The boundary condition, either "In" for ingoing or "Up" for upgoing.
|
|
298
|
+
pos : int
|
|
299
|
+
The radial position.
|
|
300
|
+
|
|
301
|
+
Returns
|
|
302
|
+
-------
|
|
303
|
+
complex
|
|
304
|
+
The radial solution at the given boundary condition `bc` and position `pos`.
|
|
305
|
+
"""
|
|
306
|
+
return self.base.radialsolution(bc, pos)
|
|
307
|
+
|
|
308
|
+
def radialderivative(self, bc, pos):
|
|
309
|
+
"""
|
|
310
|
+
The derivative of the extended homogeneous radial solution for the given boundary condition `bc` and position `pos`.
|
|
311
|
+
|
|
312
|
+
Parameters
|
|
313
|
+
----------
|
|
314
|
+
bc : str
|
|
315
|
+
The boundary condition, either "In" for ingoing or "Up" for upgoing.
|
|
316
|
+
pos : int
|
|
317
|
+
The radial position.
|
|
318
|
+
|
|
319
|
+
Returns
|
|
320
|
+
-------
|
|
321
|
+
complex
|
|
322
|
+
The radial derivative at the given boundary condition `bc` and position `pos`.
|
|
323
|
+
"""
|
|
324
|
+
return self.base.radialderivative(bc, pos)
|
|
325
|
+
|
|
326
|
+
def radialderivative2(self, bc, pos):
|
|
327
|
+
"""
|
|
328
|
+
The second derivative of the extended homogeneous radial solution for the given boundary condition `bc` and position `pos`.
|
|
329
|
+
|
|
330
|
+
Parameters
|
|
331
|
+
----------
|
|
332
|
+
bc : str
|
|
333
|
+
The boundary condition, either "In" for ingoing or "Up" for upgoing.
|
|
334
|
+
pos : int
|
|
335
|
+
The radial position.
|
|
336
|
+
|
|
337
|
+
Returns
|
|
338
|
+
-------
|
|
339
|
+
complex
|
|
340
|
+
The radial second derivative at the given boundary condition `bc` and position `pos`.
|
|
341
|
+
"""
|
|
342
|
+
return self.base.radialderivative2(bc, pos)
|
|
343
|
+
|
|
344
|
+
def homogeneousradialsolution(self, bc, pos):
|
|
345
|
+
"""
|
|
346
|
+
The homogeneous radial solution for the given boundary condition `bc` and position `pos`.
|
|
347
|
+
|
|
348
|
+
Parameters
|
|
349
|
+
----------
|
|
350
|
+
bc : str
|
|
351
|
+
The boundary condition, either "In" for ingoing or "Up" for upgoing.
|
|
352
|
+
pos : int
|
|
353
|
+
The radial position.
|
|
354
|
+
|
|
355
|
+
Returns
|
|
356
|
+
-------
|
|
357
|
+
complex
|
|
358
|
+
The radial solution at the given boundary condition `bc` and position `pos`.
|
|
359
|
+
"""
|
|
360
|
+
return self.base.homogeneousradialsolution(bc, pos)
|
|
361
|
+
|
|
362
|
+
def homogeneousradialderivative(self, bc, pos):
|
|
363
|
+
"""
|
|
364
|
+
The radial derivative of the homogeneous radial solution for the given boundary condition `bc` and position `pos`.
|
|
365
|
+
|
|
366
|
+
Parameters
|
|
367
|
+
----------
|
|
368
|
+
bc : str
|
|
369
|
+
The boundary condition, either "In" for ingoing or "Up" for upgoing.
|
|
370
|
+
pos : int
|
|
371
|
+
The radial position.
|
|
372
|
+
|
|
373
|
+
Returns
|
|
374
|
+
-------
|
|
375
|
+
complex
|
|
376
|
+
The radial derivative at the given boundary condition `bc` and position `pos`.
|
|
377
|
+
"""
|
|
378
|
+
return self.base.homogeneousradialderivative(bc, pos)
|
|
379
|
+
|
|
380
|
+
def homogeneousradialderivative2(self, bc, pos):
|
|
381
|
+
"""
|
|
382
|
+
The second radial derivative of the homogeneous radial solution for the given boundary condition `bc` and position `pos`.
|
|
383
|
+
|
|
384
|
+
Parameters
|
|
385
|
+
----------
|
|
386
|
+
bc : str
|
|
387
|
+
The boundary condition, either "In" for ingoing or "Up" for upgoing.
|
|
388
|
+
pos : int
|
|
389
|
+
The radial position.
|
|
390
|
+
|
|
391
|
+
Returns
|
|
392
|
+
-------
|
|
393
|
+
complex
|
|
394
|
+
The radial second derivative at the given boundary condition `bc` and position `pos`.
|
|
395
|
+
"""
|
|
396
|
+
return self.base.homogeneousradialderivative2(bc, pos)
|
|
397
|
+
|
|
398
|
+
def polarpoint(self, pos):
|
|
399
|
+
"""
|
|
400
|
+
The polar point for the given position `pos`.
|
|
401
|
+
|
|
402
|
+
Parameters
|
|
403
|
+
----------
|
|
404
|
+
pos : int
|
|
405
|
+
The polar position.
|
|
406
|
+
|
|
407
|
+
Returns
|
|
408
|
+
-------
|
|
409
|
+
float
|
|
410
|
+
The polar point at the given position `pos`.
|
|
411
|
+
"""
|
|
412
|
+
return self.base.polarpoint(pos)
|
|
413
|
+
|
|
414
|
+
def polarsolution(self, pos):
|
|
415
|
+
"""
|
|
416
|
+
The polar solution for the given position `pos`.
|
|
417
|
+
|
|
418
|
+
Parameters
|
|
419
|
+
----------
|
|
420
|
+
pos : int
|
|
421
|
+
The polar position.
|
|
422
|
+
|
|
423
|
+
Returns
|
|
424
|
+
-------
|
|
425
|
+
float
|
|
426
|
+
The polar solution at the given position `pos`.
|
|
427
|
+
"""
|
|
428
|
+
return self.base.polarsolution(pos)
|
|
429
|
+
|
|
430
|
+
def polarderivative(self, pos):
|
|
431
|
+
"""
|
|
432
|
+
The derivative of the polar solution for the given position `pos`.
|
|
433
|
+
|
|
434
|
+
Parameters
|
|
435
|
+
----------
|
|
436
|
+
pos : int
|
|
437
|
+
The polar position.
|
|
438
|
+
|
|
439
|
+
Returns
|
|
440
|
+
-------
|
|
441
|
+
float
|
|
442
|
+
The polar derivative at the given position `pos`.
|
|
443
|
+
"""
|
|
444
|
+
return self.base.polarderivative(pos)
|
|
445
|
+
|
|
446
|
+
def polarderivative2(self, pos):
|
|
447
|
+
"""
|
|
448
|
+
The second derivative of the polar solution for the given position `pos`.
|
|
449
|
+
|
|
450
|
+
Parameters
|
|
451
|
+
----------
|
|
452
|
+
pos : int
|
|
453
|
+
The polar position.
|
|
454
|
+
|
|
455
|
+
Returns
|
|
456
|
+
-------
|
|
457
|
+
float
|
|
458
|
+
The polar second derivative at the given position `pos`.
|
|
459
|
+
"""
|
|
460
|
+
return self.base.polarderivative2(pos)
|
|
461
|
+
|
|
462
|
+
def amplitude(self, bc):
|
|
463
|
+
"""
|
|
464
|
+
The Teukolsky amplitude for the given boundary condition `bc`.
|
|
465
|
+
|
|
466
|
+
Parameters
|
|
467
|
+
----------
|
|
468
|
+
bc : str
|
|
469
|
+
The boundary condition, either "In" for ingoing or "Up" for upgoing.
|
|
470
|
+
|
|
471
|
+
Returns
|
|
472
|
+
-------
|
|
473
|
+
complex
|
|
474
|
+
The Teukolsky amplitude at the given boundary condition `bc`.
|
|
475
|
+
"""
|
|
476
|
+
return self.base.teukolsky_amplitude(bc)
|
|
477
|
+
|
|
478
|
+
def precision(self, bc):
|
|
479
|
+
"""
|
|
480
|
+
The precision of the Teukolsky amplitude for the given boundary condition `bc`.
|
|
481
|
+
|
|
482
|
+
Parameters
|
|
483
|
+
----------
|
|
484
|
+
bc : str
|
|
485
|
+
The boundary condition, either "In" for ingoing or "Up" for upgoing.
|
|
486
|
+
|
|
487
|
+
Returns
|
|
488
|
+
-------
|
|
489
|
+
float
|
|
490
|
+
The precision of the Teukolsky amplitude at the given boundary condition `bc`.
|
|
491
|
+
"""
|
|
492
|
+
return self.base.teukolsky_amplitude_precision(bc)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: pybhpt
|
|
3
|
+
Version: 0.9.10
|
|
4
|
+
Summary: Black Hole Perturbation Theory and Self-Force Algorithms in Python
|
|
5
|
+
Author-Email: Zach Nasipak <znasipak@gmail.com>
|
|
6
|
+
License: GPL
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Cython
|
|
9
|
+
Classifier: Programming Language :: C++
|
|
10
|
+
Classifier: License :: OSI Approved :: GNU General Public License (GPL)
|
|
11
|
+
Classifier: Natural Language :: English
|
|
12
|
+
Project-URL: Github, https://github.com/znasipak/pybhpt
|
|
13
|
+
Project-URL: Bug Tracker, https://github.com/znasipak/pybhpt/issues
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Requires-Dist: numpy<=2.2
|
|
16
|
+
Requires-Dist: scipy
|
|
17
|
+
Provides-Extra: testing
|
|
18
|
+
Requires-Dist: pytest; extra == "testing"
|
|
19
|
+
Requires-Dist: pytest-cov; extra == "testing"
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: matplotlib; extra == "dev"
|
|
22
|
+
Requires-Dist: jupyter; extra == "dev"
|
|
23
|
+
Requires-Dist: ipython; extra == "dev"
|
|
24
|
+
Requires-Dist: ipykernel; extra == "dev"
|
|
25
|
+
Provides-Extra: extended
|
|
26
|
+
Requires-Dist: pandas; extra == "extended"
|
|
27
|
+
Requires-Dist: spherical; extra == "extended"
|
|
28
|
+
Requires-Dist: tqdm; extra == "extended"
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# pybhpt
|
|
32
|
+
|
|
33
|
+
A python package for solving problems in black hole perturbation theory.
|
|
34
|
+
|
|
35
|
+
`pybhpt` is a collection of numerical tools for analyzing perturbations of Kerr spacetime, particularly the self-forces and metric-perturbations experienced by small bodies moving in a Kerr background. Subpackages include:
|
|
36
|
+
|
|
37
|
+
- `pybhpt.geodesic`: a module that generates bound periodic timelike geodesics in Kerr spacetime
|
|
38
|
+
- `pybhpt.radial`: a module that calculates homogeneous solutions of the radial Teukolsky equation
|
|
39
|
+
- `pybhpt.swsh`: a module that constructs the spin-weighted spheroidal harmonics
|
|
40
|
+
- `pybhpt.teuk`: a module that evaluates the inhomogeneous solutions (Teukolsky amplitudes) of the radial Teukolsky equation due to a point-particle on a bound timelike Kerr geodesic
|
|
41
|
+
- `pybhpt.flux`: a module that produces the gravitational wave fluxes sourced by a point-particle on a generic bound timelike Kerr geodesic
|
|
42
|
+
- `pybhpt.hertz`: a module that solves for the Hertz potentials for the CCK and AAB metric reconstruction procedures
|
|
43
|
+
- `pybhpt.metric`: a module that produces the coefficients needed to reconstruct the metric from the Hertz potentials
|
|
44
|
+
- `pybhpt.redshift`: a module that computes the generalized Detweiler redshift invariant in a variety of gauges
|
|
45
|
+
|
|
46
|
+
See the [Documentation](https://pybhpt.readthedocs.io/en/latest/) pages for more information about the package, including User Guides and API. References and author information can be found at the bottom of the README.
|
|
47
|
+
|
|
48
|
+
## Quick Installation
|
|
49
|
+
|
|
50
|
+
Tagged releases of `pybhpt` are available as wheel packages for macOS and 64-bit Linux on [PyPI](https://pypi.org/project/pybhpt). Install using `pip`:
|
|
51
|
+
```
|
|
52
|
+
python3 -m pip install pybhpt
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Developer Installation
|
|
56
|
+
|
|
57
|
+
`pybhpt` relies on several dependencies to install and run, namely a C/C++ compiler (e.g., `g++`), `gsl`, `boost`, `Cython`, `numpy`, `scipy`, and `python >= 3.8`. To reduce package conflicts and ensure that the proper dependencies are installed, we recommend using [conda](https://docs.conda.io/en/latest/) (paricularly through [Miniforge](https://github.com/conda-forge/miniforge)) and its virtual environments.
|
|
58
|
+
|
|
59
|
+
To create a conda environment `pybhpt-env` with just the necessary dependencies use `environment.yml`:
|
|
60
|
+
```
|
|
61
|
+
conda env create -f environment.yml
|
|
62
|
+
conda activate pybhpt-env
|
|
63
|
+
```
|
|
64
|
+
For an environment with the extended recommended software dependencies, one can replace `environment.yml` with `environment-extended.yml` or follow the extended `pip` install instructions below.
|
|
65
|
+
|
|
66
|
+
Next clone the `pybhpt` repository from GitHub:
|
|
67
|
+
```
|
|
68
|
+
git clone https://github.com/znasipak/pybhpt.git
|
|
69
|
+
cd pybhpt
|
|
70
|
+
```
|
|
71
|
+
The `boost` repository is included as a submodule under `extern/boost`. To activate the submodule:
|
|
72
|
+
```
|
|
73
|
+
git submodule update --init --recursive extern/boost
|
|
74
|
+
```
|
|
75
|
+
To include the Boost headers in the compilation path:
|
|
76
|
+
```
|
|
77
|
+
cd extern/boost
|
|
78
|
+
chmod +x bootstrap.sh
|
|
79
|
+
./bootstrap.sh
|
|
80
|
+
./b2 headers
|
|
81
|
+
```
|
|
82
|
+
Finally, we recommend installing the package via `pip`:
|
|
83
|
+
```
|
|
84
|
+
pip install .
|
|
85
|
+
```
|
|
86
|
+
or to get the basic development dependencies:
|
|
87
|
+
```
|
|
88
|
+
pip install '.[dev, testing]'
|
|
89
|
+
```
|
|
90
|
+
To get all recommended software:
|
|
91
|
+
```
|
|
92
|
+
pip install '.[dev, testing, extended]'
|
|
93
|
+
```
|
|
94
|
+
To ensure the package installed properly, run the unit tests via `pytest`:
|
|
95
|
+
```
|
|
96
|
+
pytest .
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Conda Environments with Jupyter
|
|
100
|
+
|
|
101
|
+
To run the code in a Jupyter notebook, we recommend `pip` installing the following dependencies:
|
|
102
|
+
```
|
|
103
|
+
pip install ipykernel matplotlib
|
|
104
|
+
```
|
|
105
|
+
These dependencies are already included in `environment-extended.yml` or in the optional `pip install` dependencies. To make the environment accessible within Jupyter:
|
|
106
|
+
```
|
|
107
|
+
python -m ipykernel install --user --name=pybhpt-env
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Uninstalling
|
|
111
|
+
|
|
112
|
+
If the package is installed using `pip`, then one can easily uninstall the package by executing
|
|
113
|
+
```
|
|
114
|
+
pip uninstall pybhpt
|
|
115
|
+
```
|
|
116
|
+
Developers may also need to remove the directories `build/` and `pybhpt.egg.info/` from the main repository.
|
|
117
|
+
|
|
118
|
+
## Troubleshooting compiling from source
|
|
119
|
+
|
|
120
|
+
If there are problems compiling `pybhpt` from source, it may be because `cmake` cannot identify the correct compiler. To fix this issue, one can try to explicitly download the necessary compiler into their conda environment.
|
|
121
|
+
|
|
122
|
+
To include the necessary compiler on macOS Intel:
|
|
123
|
+
```
|
|
124
|
+
conda install clang_osx-64 clangxx_osx-64
|
|
125
|
+
```
|
|
126
|
+
To include the necessary compiler on macOS arm/silicon:
|
|
127
|
+
```
|
|
128
|
+
conda install clang_osx-arm64 clangxx_osx-arm64
|
|
129
|
+
```
|
|
130
|
+
To include the necessary compiler on Linux:
|
|
131
|
+
```
|
|
132
|
+
conda install gcc_linux-64 gxx_linux-64
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## References
|
|
136
|
+
|
|
137
|
+
Theoretical background for the code and explanations of the numerical methods used within are summarized in the references below:
|
|
138
|
+
|
|
139
|
+
- Z. Nasipak, *Metric reconstruction and the Hamiltonian for eccentric, precessing binaries in the small-mass-ratio limit* (2025) [arXiv:2507.07746](https://arxiv.org/abs/2507.07746)
|
|
140
|
+
- Z. Nasipak, *An adiabatic gravitational waveform model for compact objects undergoing quasi-circular inspirals into rotating massive black holes*, Phys. Rev. D 109, 044020 (2024) [arXiv:2310.19706](https://arxiv.org/abs/2310.19706)
|
|
141
|
+
- Z. Nasipak, *Adiabatic evolution due to the conservative scalar self-force during orbital resonances*, Phys. Rev. D 106, 064042 (2022) [arXiv:2207.02224](https://arxiv.org/abs/2207.02224)
|
|
142
|
+
|
|
143
|
+
## Authors
|
|
144
|
+
|
|
145
|
+
Zachary Nasipak
|
|
146
|
+
|
|
147
|
+
## Contributors
|
|
148
|
+
|
|
149
|
+
Zachary Nasipak
|
|
150
|
+
|
|
151
|
+
Christian Chapman-Bird
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
cybhpt_full.cpython-312-darwin.so,sha256=rY1QfcVMUfAM_SvTQiwWMZM_apr_0HG6Z3ZUdd8hPu0,2360944
|
|
2
|
+
pybhpt-0.9.10.dist-info/RECORD,,
|
|
3
|
+
pybhpt-0.9.10.dist-info/WHEEL,sha256=bzH17ccJ1joRkQvwNza4T9UCzNV6eCuH71N8yWxKq_E,142
|
|
4
|
+
pybhpt-0.9.10.dist-info/METADATA,sha256=D3HVza1Dw0AenIHPUyrAYICu3RhX3Pv2X79JY50tqR0,6427
|
|
5
|
+
pybhpt-0.9.10.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
6
|
+
pybhpt/geo.py,sha256=PbRr_-KGthdDmhwEqiV69PX9ljnNjvYneKQWCBe8jWs,30534
|
|
7
|
+
pybhpt/redshift.py,sha256=eWQ9jGctxOOyOowP5BdBdnln3HdpQLubApDBFKoCL1Y,794
|
|
8
|
+
pybhpt/hertz.py,sha256=kLwiU_AAEzMMIKn3EI3KNg1y1bScZxC_F5n77VKMulc,13585
|
|
9
|
+
pybhpt/radial.py,sha256=6AzGvoyXfhRT1_87Y6fIQQ0EZnx9wO4GtSu3jWzM4Zg,15607
|
|
10
|
+
pybhpt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
pybhpt/swsh.py,sha256=rwkjlsDPg_Yx2R8r9d_gv2D1tShgGDqIjGkupiXbmZk,20956
|
|
12
|
+
pybhpt/metric.py,sha256=xS3VXti-qryUIm2pWdroHAkKCV_JQA0pCs_2aDn_Ffk,11917
|
|
13
|
+
pybhpt/teuk.py,sha256=rSo_1ENBt4qt5Ln94Q721FBV52ZCUtAPb20_aRaM9lM,14989
|
|
14
|
+
pybhpt/flux.py,sha256=uRjFHg1clHDN9MofiGS1ra2hGAt4Bv9kGogQ-OpNePY,6068
|
|
15
|
+
pybhpt/.dylibs/libgsl.28.dylib,sha256=LZzQOyyIx4U5-yAVbb_A1lNRXm8BwTToumfsFkzIfsU,2427264
|
|
16
|
+
pybhpt/.dylibs/libgslcblas.0.dylib,sha256=h1FSgXIm1ms4NxAp-R5eJ5IbvCHHK1aWJDAnHhHoL_Q,235616
|