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.
pybhpt/metric.py ADDED
@@ -0,0 +1,326 @@
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
+
5
+ def gauge_check(gauge):
6
+ if gauge not in available_gauges:
7
+ TypeError("{} is not a supported gauge.".format(gauge))
8
+
9
+ S0_gauges = ["IRG", "ARG0", "SRG0"]
10
+ S4_gauges = ["ORG", "ARG4", "SRG4"]
11
+
12
+ def metric_coefficients_S4dagger_ab(ai, bi, nt, nr, nz, nph, a, r, z):
13
+ """Compute the metric coefficients for the reconstructed perturbation associated with the
14
+ S4dagger reconstruction operator.
15
+
16
+ Parameters
17
+ ----------
18
+ ai, bi : int
19
+ The indices of the tetrad-projected components of the metric perturbation.
20
+ nt, nr, nz, nph : int
21
+ The indices associated with the time, radial, spin, and azimuthal derivative operators.
22
+ a : float
23
+ The black hole spin parameter.
24
+ r : float
25
+ The radial coordinate.
26
+ z : float
27
+ The polar coordinate (cosine of the polar angle).
28
+
29
+ Returns
30
+ -------
31
+ float
32
+ The computed metric coefficient."""
33
+ return _metric_coefficients_cython_S4dagger(ai, bi, nt, nr, nz, nph, a, r, z)
34
+
35
+ def metric_coefficients_S0dagger_ab(ai, bi, nt, nr, nz, nph, a, r, z):
36
+ """Compute the metric coefficients for the reconstructed perturbation associated with the
37
+ S0dagger reconstruction operator.
38
+
39
+ Parameters
40
+ ----------
41
+ ai, bi : int
42
+ The indices of the tetrad-projected components of the metric perturbation.
43
+ nt, nr, nz, nph : int
44
+ The indices associated with the time, radial, spin, and azimuthal derivative operators.
45
+ a : float
46
+ The black hole spin parameter.
47
+ r : float
48
+ The radial coordinate.
49
+ z : float
50
+ The polar coordinate (cosine of the polar angle).
51
+
52
+ Returns
53
+ -------
54
+ float
55
+ The computed metric coefficient."""
56
+ return _metric_coefficients_cython_S0dagger(ai, bi, nt, nr, nz, nph, a, r, z)
57
+
58
+ def metric_coefficients_S0dagger(a, b, c, d, q, rvals, zvals):
59
+ """Compute the metric coefficients for the reconstructed perturbation associated with the
60
+ S0dagger reconstruction operator.
61
+
62
+ Parameters
63
+ ----------
64
+ a, b, c, d : int
65
+ The indices associated with the time, radial, spin, and azimuthal derivative operators.
66
+ q : float
67
+ The black hole spin parameter.
68
+ rvals : numpy.ndarray
69
+ The radial coordinate.
70
+ zvals : np.ndarray
71
+ The polar coordinate (cosine of the polar angle).
72
+
73
+ Returns
74
+ -------
75
+ numpy.ndarray
76
+ A 3D array containing the computed metric coefficients for the S0dagger operator."""
77
+ h22 = np.array([[metric_coefficients_S0dagger_ab(2, 2, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
78
+ h24 = np.array([[metric_coefficients_S0dagger_ab(2, 4, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
79
+ h44 = np.array([[metric_coefficients_S0dagger_ab(4, 4, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
80
+ return np.array([2.*h22, h24, h44])
81
+
82
+ def metric_coefficients_S4dagger(a, b, c, d, q, rvals, zvals):
83
+ """Compute the metric coefficients for the reconstructed perturbation associated with the
84
+ S4dagger reconstruction operator.
85
+
86
+ Parameters
87
+ ----------
88
+ a, b, c, d : int
89
+ The indices associated with the time, radial, spin, and azimuthal derivative operators.
90
+ q : float
91
+ The black hole spin parameter.
92
+ rvals : numpy.ndarray
93
+ The radial coordinate.
94
+ zvals : np.ndarray
95
+ The polar coordinate (cosine of the polar angle).
96
+
97
+ Returns
98
+ -------
99
+ numpy.ndarray
100
+ A 3D array containing the computed metric coefficients for the S0dagger operator."""
101
+ h11 = np.array([[metric_coefficients_S4dagger_ab(1, 1, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
102
+ h13 = np.array([[metric_coefficients_S4dagger_ab(1, 3, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
103
+ h33 = np.array([[metric_coefficients_S4dagger_ab(3, 3, a, b, c, d, q, r, z) for z in zvals] for r in rvals])
104
+ return np.array([2.*h11, h13, h33])
105
+
106
+ def metric_coefficients(gauge, a, b, c, d, q, rvals, zvals):
107
+ """Compute the metric coefficients for the reconstructed perturbation associated with the
108
+ specified gauge.
109
+
110
+ Parameters
111
+ ----------
112
+ gauge : str
113
+ The gauge to use for the reconstruction. Must be one of the available gauges.
114
+ a, b, c, d : int
115
+ The indices associated with the time, radial, spin, and azimuthal derivative operators.
116
+ q : float
117
+ The black hole spin parameter.
118
+ rvals : numpy.ndarray
119
+ The radial coordinate.
120
+ zvals : np.ndarray
121
+ The polar coordinate (cosine of the polar angle).
122
+
123
+ Returns
124
+ -------
125
+ numpy.ndarray
126
+ A 3D array containing the computed metric coefficients for the specified gauge.
127
+ """
128
+ gauge_check(gauge)
129
+ if gauge in S0_gauges:
130
+ return metric_coefficients_S0dagger(a, b, c, d, q, rvals, zvals)
131
+ else:
132
+ return metric_coefficients_S4dagger(a, b, c, d, q, rvals, zvals)
133
+
134
+ class MetricCoefficients:
135
+ """
136
+ A class for computing the metric coefficients of the reconstructed perturbation
137
+ associated with the S0dagger or S4dagger reconstruction operator based on the specified gauge.
138
+
139
+ Parameters
140
+ ----------
141
+ gauge : str
142
+ The gauge to use for the reconstruction. Must be one of the available gauges.
143
+ q : float
144
+ The black hole spin parameter.
145
+ r : numpy.ndarray
146
+ The radial coordinate values.
147
+ th : numpy.ndarray
148
+ The polar coordinate values (cosine of the polar angle).
149
+
150
+ Attributes
151
+ ----------
152
+ gauge : str
153
+ The gauge used for the reconstruction.
154
+ blackholespin : float
155
+ The black hole spin parameter.
156
+ radialpoints : numpy.ndarray
157
+ The radial coordinate values.
158
+ polarpoints : numpy.ndarray
159
+ The polar coordinate values (cosine of the polar angle).
160
+ storedcomponents : dict
161
+ A dictionary mapping pairs of indices (a, b) to the index of the stored component
162
+ in the coefficients array.
163
+ conjugatecomponents : dict
164
+ A dictionary mapping pairs of indices (a, b) to the index of the conjugate component
165
+ in the coefficients array.
166
+ coeffs : numpy.ndarray
167
+ A 7D array containing the computed metric coefficients for the specified gauge.
168
+ zeros : numpy.ndarray
169
+ A 2D array of zeros with the same shape as the radial and polar coordinate arrays.
170
+
171
+ Methods
172
+ -------
173
+ hab(a, b, nt, nr, ns, nphi):
174
+ Returns the metric coefficient for the specified indices (a, b) and derivative orders
175
+ (nt, nr, ns, nphi). If the indices are not found in the stored or conjugate components,
176
+ it returns a zero array.
177
+ __call__(a, b, nt, nr, ns, nphi):
178
+ Calls the `hab` method to retrieve the metric coefficient for the specified indices
179
+ and derivative orders.
180
+ """
181
+ def __init__(self, gauge, q, r, th):
182
+ gauge_check(gauge)
183
+ self.gauge = gauge
184
+ rsamples = r.shape[0]
185
+ zsamples = th.shape[0]
186
+ self.blackholespin = q
187
+ self.radialpoints = r
188
+ self.polarpoints = th
189
+ if gauge in S0_gauges:
190
+ self.storedcomponents = {(2, 2): 0, (2, 4): 1, (4, 4): 2}
191
+ self.conjugatecomponents = {(2, 3): 1, (3, 3): 2}
192
+ else:
193
+ self.storedcomponents = {(1, 1): 0, (1, 3): 1, (3, 3): 2}
194
+ self.conjugatecomponents = {(1, 4): 1, (4, 4): 2}
195
+ z = np.cos(th)
196
+ z[np.abs(z) < 1.e-15] = 0.
197
+ self.coeffs = np.zeros((3, 3, 3, 3, 3, rsamples, zsamples), dtype=np.complex128)
198
+ self.zeros = np.zeros((rsamples, zsamples), dtype=np.complex128)
199
+ for ai in range(3):
200
+ for bi in range(3):
201
+ for ci in range(3):
202
+ for di in range(3):
203
+ self.coeffs[ai, bi, ci, di] = metric_coefficients(self.gauge, ai, bi, ci, di, q, r, z)
204
+
205
+ def hab(self, a, b, nt, nr, ns, nphi):
206
+ """
207
+ Returns the metric coefficient for the specified indices (a, b) and derivative orders
208
+ (nt, nr, ns, nphi). If the indices are not found in the stored or conjugate components,
209
+ it returns a zero array.
210
+
211
+ Parameters
212
+ ----------
213
+ a, b : int
214
+ The indices of the tetrad-projected components of the metric perturbation.
215
+ nt, nr, ns, nphi : int
216
+ The indices associated with the time, radial, spin, and azimuthal derivative operators.
217
+
218
+ Returns
219
+ -------
220
+ numpy.ndarray
221
+ The computed metric coefficient for the specified indices and derivative orders.
222
+ """
223
+ if b < a:
224
+ atemp = a
225
+ a = b
226
+ b = atemp
227
+ if (a, b) in self.storedcomponents.keys():
228
+ return self.coeffs[nt, nr, ns, nphi][self.storedcomponents[(a, b)]]
229
+ elif (a, b) in self.conjugatecomponents.keys():
230
+ return np.conj(self.coeffs[nt, nr, ns, nphi][self.conjugatecomponents[(a, b)]])
231
+ else:
232
+ return self.zeros
233
+
234
+ def __call__(self, a, b, nt, nr, ns, nphi):
235
+ """ Calls the `hab` method to retrieve the metric coefficient for the specified indices
236
+ and derivative orders.
237
+
238
+ Parameters
239
+ ----------
240
+ a, b : int
241
+ The indices of the tetrad-projected components of the metric perturbation.
242
+ nt, nr, ns, nphi : int
243
+ The indices associated with the time, radial, spin, and azimuthal derivative operators.
244
+
245
+ Returns
246
+ -------
247
+ numpy.ndarray
248
+ The computed metric coefficient for the specified indices and derivative orders.
249
+ """
250
+ return self.hab(a, b, nt, nr, ns, nphi)
251
+
252
+ def tetrad_project_l(a, r, z, mu):
253
+ if mu == 0:
254
+ return -1
255
+ elif mu == 1:
256
+ sigma = r**2 + a**2*z**2
257
+ delta = r**2 - 2.*r + a**2
258
+ return sigma/delta
259
+ elif mu == 2:
260
+ return 0.
261
+ elif mu == 3:
262
+ return a*(1. - z**2)
263
+ else:
264
+ return 0.
265
+
266
+ def tetrad_project_n(a, r, z, mu):
267
+ sigma = r**2 + a**2*z**2
268
+ delta = r**2 - 2.*r + a**2
269
+ if mu == 0:
270
+ return -0.5*delta/sigma
271
+ elif mu == 1:
272
+ return -0.5
273
+ elif mu == 2:
274
+ return 0.
275
+ elif mu == 3:
276
+ return 0.5*delta/sigma*a*(1. - z**2)
277
+ else:
278
+ return 0.
279
+
280
+ def tetrad_project_m(a, r, z, mu):
281
+ rhobar = -1./(r + 1j*a*z)
282
+ sigma = r**2 + a**2*z**2
283
+ pref = - rhobar*np.sqrt(0.5*(1. - z**2))
284
+ if mu == 0:
285
+ return -1j*pref*a
286
+ elif mu == 1:
287
+ return 0.
288
+ elif mu == 2:
289
+ return -pref*sigma/(1. - z**2)
290
+ elif mu == 3:
291
+ return 1j*pref*(r**2 + a**2)
292
+ else:
293
+ return 0.
294
+
295
+ def kinnersley_tetrad_covector(b, q, r, z, mu):
296
+ if b == 1:
297
+ return tetrad_project_l(q, r, z, mu)
298
+ elif b == 2:
299
+ return tetrad_project_n(q, r, z, mu)
300
+ elif b == 3:
301
+ return tetrad_project_m(q, r, z, mu)
302
+ elif b == 4:
303
+ return np.conj(tetrad_project_m(q, r, z, mu))
304
+ else:
305
+ return 0.
306
+
307
+ def hmunu_BL(gauge, mu, nu, q, r, hab):
308
+ gauge_check(gauge)
309
+ if gauge in S0_gauges:
310
+ e1mu = kinnersley_tetrad_covector(1, q, r, 0, mu)
311
+ e1nu = kinnersley_tetrad_covector(1, q, r, 0, nu)
312
+ e3mu = kinnersley_tetrad_covector(3, q, r, 0, mu)
313
+ e3nu = kinnersley_tetrad_covector(3, q, r, 0, nu)
314
+ h22 = e1mu*e1nu*hab[0]
315
+ h24 = -e1mu*e3nu*hab[1] - e1nu*e3mu*hab[1]
316
+ h44 = e3mu*e3nu*hab[2]
317
+ return (h22.real + 2.*h24.real + 2.*h44.real)
318
+ else:
319
+ e1mu = kinnersley_tetrad_covector(2, q, r, 0, mu)
320
+ e1nu = kinnersley_tetrad_covector(2, q, r, 0, nu)
321
+ e3mu = kinnersley_tetrad_covector(4, q, r, 0, mu)
322
+ e3nu = kinnersley_tetrad_covector(4, q, r, 0, nu)
323
+ h11 = e1mu*e1nu*hab[0]
324
+ h13 = -e1mu*e3nu*hab[1] - e1nu*e3mu*hab[1]
325
+ h33 = e3mu*e3nu*hab[2]
326
+ return (h11.real + 2.*h13.real + 2.*h33.real)