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.
pybhpt/radial.py ADDED
@@ -0,0 +1,444 @@
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, j, m, a, omega):
15
+ """
16
+ Computes the renormalized angular momentum for the given parameters.
17
+
18
+ Parameters
19
+ ----------
20
+ s : int
21
+ The spin weight of the field.
22
+ j : int
23
+ The spheroidal harmonic mode number.
24
+ m : int
25
+ The azimuthal harmonic mode number.
26
+ a : float
27
+ The black hole spin parameter.
28
+ omega : float
29
+ The frequency of the mode.
30
+
31
+ Returns
32
+ -------
33
+ complex
34
+ The renormalized angular momentum.
35
+ """
36
+ return _nu_cython(s, j, m, a, omega)
37
+
38
+ def renormalized_angular_momentum_monodromy(s, j, m, a, omega, la):
39
+ """
40
+ Computes the renormalized angular momentum using the monodromy method for the given parameters.
41
+
42
+ Parameters
43
+ ----------
44
+ s : int
45
+ The spin weight of the field.
46
+ j : int
47
+ The spheroidal harmonic mode number.
48
+ m : int
49
+ The azimuthal harmonic mode number.
50
+ a : float
51
+ The black hole spin parameter.
52
+ omega : complex
53
+ The frequency of the mode.
54
+ la : complex
55
+ The spheroidal eigenvalue.
56
+
57
+ Returns
58
+ -------
59
+ complex
60
+ The renormalized angular momentum.
61
+ """
62
+ return _nu_2_cython(s, j, m, a, omega, la)
63
+
64
+ class RadialTeukolsky:
65
+ """A class for solving the homogeneous radial Teukolsky equation.
66
+
67
+ Parameters
68
+ ----------
69
+ s : int
70
+ The spin weight of the field
71
+ j : int
72
+ The spheroidal harmonic mode number
73
+ m : int
74
+ The azimuthal harmonic mode number
75
+ a : float
76
+ The black hole spin parameter
77
+ omega : float
78
+ The frequency of the mode
79
+ r : numpy.ndarray
80
+ A numpy array of radial points at which to evaluate the solution
81
+
82
+ Attributes
83
+ ----------
84
+ radialpoints : numpy.ndarray
85
+ A numpy array of radial points at which the solution is evaluated.
86
+ base : RadialTeukolskyCython
87
+ The underlying Cython object that performs the computations.
88
+ nsamples : int
89
+ The number of radial points in the radialpoints array.
90
+
91
+ Properties
92
+ ----------
93
+ blackholespin : float
94
+ The black hole spin parameter.
95
+ spinweight : int
96
+ The spin weight of the field.
97
+ s : int
98
+ Alias for spinweight.
99
+ spheroidalmode : int
100
+ The spheroidal harmonic mode number.
101
+ j : int
102
+ Alias for spheroidalmode.
103
+ azimuthalmode : int
104
+ The azimuthal harmonic mode number.
105
+ m : int
106
+ Alias for azimuthalmode.
107
+ frequency : float
108
+ The frequency of the mode.
109
+ mode_frequency : float
110
+ Alias for frequency.
111
+ omega : float
112
+ Alias for frequency.
113
+ eigenvalue : float
114
+ The spheroidal eigenvalue of the radial Teukolsky equation.
115
+
116
+ Methods
117
+ -------
118
+ solveboundarycondition(method)
119
+ Solves the boundary condition for the radial Teukolsky equation.
120
+ setboundarycondition(bc, R, Rp, r)
121
+ Sets the boundary condition for the radial Teukolsky equation.
122
+ solve(method="AUTO", bc=None)
123
+ Solves the radial Teukolsky equation.
124
+ flipspinweight()
125
+ Flips the spin weight of the field.
126
+ radialpoint(pos)
127
+ Returns the radial point at the given position.
128
+ boundarypoint(bc)
129
+ Returns the boundary point for the given boundary condition.
130
+ boundarysolution(bc)
131
+ Returns the solution at the boundary for the given boundary condition.
132
+ boundaryderivative(bc)
133
+ Returns the derivative at the boundary for the given boundary condition.
134
+ radialsolution(bc, pos)
135
+ Returns the solution at the radial point for the given boundary condition and position.
136
+ radialderivative(bc, pos)
137
+ Returns the derivative at the radial point for the given boundary condition and position.
138
+ radialderivative2(bc, pos)
139
+ Returns the second derivative at the radial point for the given boundary condition and position.
140
+ radialsolutions(bc)
141
+ Returns the solutions at all radial points for the given boundary condition.
142
+ radialderivatives(bc)
143
+ Returns the derivatives at all radial points for the given boundary condition.
144
+ radialderivatives2(bc)
145
+ Returns the second derivatives at all radial points for the given boundary condition.
146
+ __call__(bc, deriv=0)
147
+ Returns the solutions, first derivatives, or second derivatives at all radial points for the given boundary condition.
148
+ The `deriv` parameter specifies which derivative to return: 0 for solutions,
149
+ 1 for first derivatives, and 2 for second derivatives. If `deriv` is not 0, 1, or 2, a ValueError is raised.
150
+ """
151
+ def __init__(self, s, j, m, a, omega, r):
152
+ if a < 0 or a > 1:
153
+ raise ValueError(f"Black hole spin parameter {a} must be in the range [0, 1].")
154
+ if j < np.abs(m):
155
+ raise ValueError(f"Spheroidal harmonic mode number {j} must be greater than or equal to the absolute value of azimuthal harmonic mode number {m}.")
156
+ if np.any(r <= 1 + np.sqrt(1 - a**2)):
157
+ raise ValueError(f"Radial point {r} must be greater than horizon radius r_+ = {1 + np.sqrt(1 - a**2)}.")
158
+ if isinstance(r, list) or (isinstance(r, np.ndarray) and r.ndim > 0):
159
+ self.radialpoints = np.asarray(r)
160
+ self.nsamples = self.radialpoints.shape[0]
161
+ else:
162
+ raise AttributeError("Radial points must be a list or a numpy array.")
163
+
164
+ if self.nsamples == 0:
165
+ raise ValueError("Radial points array is empty.")
166
+ self.base = _RadialTeukolskyCython(a, s, j, m, omega, self.radialpoints)
167
+
168
+
169
+ @property
170
+ def blackholespin(self):
171
+ return self.base.blackholespin
172
+
173
+ @property
174
+ def spinweight(self):
175
+ return self.base.spinweight
176
+
177
+ @property
178
+ def s(self):
179
+ return self.spinweight
180
+
181
+ @property
182
+ def spheroidalmode(self):
183
+ return self.base.spheroidalmode
184
+
185
+ @property
186
+ def j(self):
187
+ return self.spheroidalmode
188
+
189
+ @property
190
+ def azimuthalmode(self):
191
+ return self.base.azimuthalmode
192
+
193
+ @property
194
+ def m(self):
195
+ return self.azimuthalmode
196
+
197
+ @property
198
+ def frequency(self):
199
+ return self.base.frequency
200
+
201
+ @property
202
+ def mode_frequency(self):
203
+ return self.frequency
204
+
205
+ @property
206
+ def omega(self):
207
+ return self.frequency
208
+
209
+ @property
210
+ def eigenvalue(self):
211
+ return self.base.eigenvalue
212
+
213
+ def solveboundarycondition(self, method):
214
+ """Solves the boundary condition for the radial Teukolsky equation.
215
+
216
+ Parameters
217
+ ----------
218
+ method : str
219
+ The method to use for solving the boundary condition. Default is "AUTO".
220
+ """
221
+ self.base.solve_bc(method)
222
+
223
+ def setboundarycondition(self, bc, R, Rp, r):
224
+ """Sets the boundary condition for the radial Teukolsky equation.
225
+
226
+ Parameters
227
+ ----------
228
+ bc : str
229
+ The boundary condition to set. Can be "In" for horizon or "Up" for infinity.
230
+ R : float
231
+ The boundary condition function value at the radial point.
232
+ Rp : float
233
+ The derivative of the boundary condition function at the radial point.
234
+ r : float
235
+ The radial point at which the boundary condition is defined.
236
+ """
237
+ self.base.set_bc(bc, R, Rp, r)
238
+
239
+ def solve(self, method = "AUTO", bc = None):
240
+ """Solves the radial Teukolsky equation.
241
+
242
+ Parameters
243
+ ----------
244
+ method : str, optional
245
+ The method to use for solving the equation. Default is "AUTO".
246
+ bc : str, optional
247
+ Specifies which homogeneous solutions to compute. If None, both "In" (horizon) and "Up" (infinity) solutions are computed.
248
+ If "In", only the horizon solution is computed. If "Up", only the infinity solution is computed.
249
+ """
250
+ if bc is None:
251
+ self.base.solve(method, "None")
252
+ else:
253
+ self.base.solve(method, bc)
254
+
255
+ def flipspinweight(self):
256
+ """Flips the sign of the spin weight of the field."""
257
+ self.base.flip_spinweight()
258
+
259
+ def radialpoint(self, pos):
260
+ """Returns the radial point at the given position.
261
+ Parameters
262
+ ----------
263
+ pos : float
264
+ The position at which to evaluate the radial point.
265
+ Returns
266
+ -------
267
+ float
268
+ The radial point at the given position.
269
+ """
270
+ return self.base.radialpoint(pos)
271
+
272
+ def boundarypoint(self, bc):
273
+ """
274
+ Returns the boundary point for the given boundary condition.
275
+ Parameters
276
+ ----------
277
+ bc : str
278
+ The boundary condition to evaluate. Can be "In" for horizon or "Up" for infinity.
279
+ Returns
280
+ -------
281
+ float
282
+ The boundary point corresponding to the specified boundary condition.
283
+ """
284
+ return self.base.boundarypoint(bc)
285
+
286
+ def boundarysolution(self, bc):
287
+ """Returns the solution at the boundary for the given boundary condition.
288
+ Parameters
289
+ ----------
290
+ bc : str
291
+ The boundary condition to evaluate. Can be "In" for horizon or "Up" for infinity.
292
+ Returns
293
+ -------
294
+ float
295
+ The solution at the boundary corresponding to the specified boundary condition.
296
+ """
297
+ return self.base.boundarysolution(bc)
298
+
299
+ def boundaryderivative(self, bc):
300
+ """Returns the derivative at the boundary for the given boundary condition.
301
+ Parameters
302
+ ----------
303
+ bc : str
304
+ The boundary condition to evaluate. Can be "In" for horizon or "Up" for infinity.
305
+ Returns
306
+ -------
307
+ float
308
+ The derivative at the boundary corresponding to the specified boundary condition.
309
+ """
310
+ return self.base.boundaryderivative(bc)
311
+
312
+ def radialsolution(self, bc, pos):
313
+ """Returns the solution at the radial point for the given homogeneous solution and position.
314
+ Parameters
315
+ ----------
316
+ bc : str
317
+ The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
318
+ pos : float
319
+ The position at which to evaluate the solution.
320
+ Returns
321
+ -------
322
+ float
323
+ The solution at the radial point corresponding to the specified boundary condition and position.
324
+ """
325
+ return self.base.solution(bc, pos)
326
+
327
+ def radialderivative(self, bc, pos):
328
+ """Returns the derivative at the radial point for the given homogeneous solution and position.
329
+ Parameters
330
+ ----------
331
+ bc : str
332
+ The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
333
+ pos : float
334
+ The position at which to evaluate the solution.
335
+ Returns
336
+ -------
337
+ float
338
+ The solution at the radial point corresponding to the specified boundary condition and position.
339
+ """
340
+ return self.base.derivative(bc, pos)
341
+
342
+ def radialderivative2(self, bc, pos):
343
+ """Returns the second derivative at the radial point for the given homogeneous solution and position.
344
+ Parameters
345
+ ----------
346
+ bc : str
347
+ The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
348
+ pos : float
349
+ The position at which to evaluate the solution.
350
+ Returns
351
+ -------
352
+ float
353
+ The solution at the radial point corresponding to the specified boundary condition and position.
354
+ """
355
+ return self.base.derivative2(bc, pos)
356
+
357
+ def radialsolutions(self, bc):
358
+ """Returns a homogeneous solution at all radial points.
359
+ Parameters
360
+ ----------
361
+ bc : str
362
+ The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
363
+ Returns
364
+ -------
365
+ numpy.ndarray
366
+ A numpy array of solutions at all radial points corresponding to the specified boundary condition.
367
+ """
368
+ return np.array([self.base.solution(bc, i) for i in range(self.nsamples)])
369
+
370
+ def radialderivatives(self, bc):
371
+ """Returns the radial derivative at all radial points.
372
+ Parameters
373
+ ----------
374
+ bc : str
375
+ The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
376
+ Returns
377
+ -------
378
+ numpy.ndarray
379
+ A numpy array of solutions at all radial points corresponding to the specified boundary condition.
380
+ """
381
+ return np.array([self.base.derivative(bc, i) for i in range(self.nsamples)])
382
+
383
+ def radialderivatives2(self, bc):
384
+ """Returns the second radial derivative at all radial points.
385
+ Parameters
386
+ ----------
387
+ bc : str
388
+ The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
389
+ Returns
390
+ -------
391
+ numpy.ndarray
392
+ A numpy array of solutions at all radial points corresponding to the specified boundary condition.
393
+ """
394
+ return np.array([self.base.derivative2(bc, i) for i in range(self.nsamples)])
395
+
396
+ def __call__(self, bc, deriv = 0):
397
+ """Returns the solutions, first derivatives, or second derivatives at all radial points for the given boundary condition.
398
+
399
+ Parameters
400
+ ----------
401
+ bc : str
402
+ The homogeneous solution to evaluate. Can be "In" for horizon solution or "Up" for infinity solution.
403
+ deriv : int, optional
404
+ Specifies which derivative to return: 0 for solutions, 1 for first derivatives, and 2 for second derivatives.
405
+ Default is 0 (solutions).
406
+ Returns
407
+ -------
408
+ numpy.ndarray
409
+ A numpy array of solutions, first derivatives, or second derivatives at all radial points corresponding to the specified boundary condition.
410
+ Raises
411
+ ------
412
+ ValueError
413
+ If `deriv` is not 0, 1, or 2.
414
+ """
415
+ if deriv == 0:
416
+ return self.radialsolutions(bc)
417
+ elif deriv == 1:
418
+ return self.radialderivatives(bc)
419
+ elif deriv == 2:
420
+ return self.radialderivatives2(bc)
421
+ else:
422
+ raise ValueError("RadialTeukolsky only solves up to the second derivative")
423
+
424
+ def hypergeo_2F1(a, b, c, x):
425
+ """
426
+ Gauss hypergeometric function 2F1(a, b; c; x). Note that this function is not very stable across the complex domain.
427
+
428
+ Parameters
429
+ ----------
430
+ a : complex
431
+ The first parameter of the hypergeometric function.
432
+ b : complex
433
+ The second parameter of the hypergeometric function.
434
+ c : complex
435
+ The third parameter of the hypergeometric function.
436
+ x : complex
437
+ The argument of the hypergeometric function.
438
+
439
+ Returns
440
+ -------
441
+ complex
442
+ The value of the hypergeometric function 2F1(a, b; c; x).
443
+ """
444
+ return _hypergeo_2F1_cython(a, b, c, x)
pybhpt/redshift.py ADDED
@@ -0,0 +1,19 @@
1
+ from cybhpt_full import RedshiftCoefficients as _RedshiftCoefficientsCython
2
+ from cybhpt_full import SphericalHarmonicCoupling as _SphericalHarmonicCouplingCython
3
+
4
+ class RedshiftCoefficients:
5
+ def __init__(self, gauge, geo):
6
+ self.base = _RedshiftCoefficientsCython(gauge, geo.base)
7
+ def __call__(self, Ni, ai, bi, ci, di, jr = 0, jz = 0):
8
+ return self.base(Ni, ai, bi, ci, di, jr, jz)
9
+
10
+ class SphericalHarmonicCoupling:
11
+ def __init__(self, lmax, m):
12
+ self.base = _SphericalHarmonicCouplingCython(lmax, m)
13
+ self.azimuthalmode = self.base.azimuthalmode
14
+
15
+ def zcouplingcoefficient(self, n, i, l):
16
+ return self.base.zcouplingcoefficient(n, i, l)
17
+
18
+ def dzcouplingcoefficient(self, n, i, l):
19
+ return self.base.dzcouplingcoefficient(n, i, l)