pybhpt 0.9.4__tar.gz → 0.9.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pybhpt might be problematic. Click here for more details.

Files changed (100) hide show
  1. pybhpt-0.9.5/.readthedocs.yml +13 -0
  2. {pybhpt-0.9.4 → pybhpt-0.9.5}/PKG-INFO +14 -4
  3. {pybhpt-0.9.4 → pybhpt-0.9.5}/README.md +13 -3
  4. {pybhpt-0.9.4 → pybhpt-0.9.5}/build_gsl.sh +7 -4
  5. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/swsh.hpp +0 -1
  6. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/swsh.cpp +1 -0
  7. pybhpt-0.9.5/cython/swsh_wrap.pyx +70 -0
  8. {pybhpt-0.9.4 → pybhpt-0.9.5}/cython/teukolsky_wrap.pyx +1 -0
  9. pybhpt-0.9.5/docs/Makefile +12 -0
  10. pybhpt-0.9.5/docs/about.md +26 -0
  11. pybhpt-0.9.5/docs/background/geo.md +76 -0
  12. pybhpt-0.9.5/docs/background/radial.md +38 -0
  13. pybhpt-0.9.5/docs/background/swsh.md +42 -0
  14. pybhpt-0.9.5/docs/background/teuk.md +42 -0
  15. pybhpt-0.9.5/docs/conf.py +51 -0
  16. pybhpt-0.9.5/docs/index.md +67 -0
  17. pybhpt-0.9.5/docs/installation.md +88 -0
  18. pybhpt-0.9.5/docs/notebooks/fluxes.ipynb +323 -0
  19. pybhpt-0.9.5/docs/notebooks/geodesics.ipynb +409 -0
  20. pybhpt-0.9.5/docs/notebooks/radial.ipynb +185 -0
  21. pybhpt-0.9.5/docs/notebooks/swsh.ipynb +309 -0
  22. pybhpt-0.9.5/docs/notebooks/teuk.ipynb +380 -0
  23. pybhpt-0.9.5/docs/notebooks/waveform.ipynb +472 -0
  24. pybhpt-0.9.5/docs/pybhpt.flux.md +24 -0
  25. pybhpt-0.9.5/docs/pybhpt.geo.md +18 -0
  26. pybhpt-0.9.5/docs/pybhpt.hertz.md +11 -0
  27. pybhpt-0.9.5/docs/pybhpt.metric.md +11 -0
  28. pybhpt-0.9.5/docs/pybhpt.radial.md +25 -0
  29. pybhpt-0.9.5/docs/pybhpt.redshift.md +11 -0
  30. pybhpt-0.9.5/docs/pybhpt.swsh.md +20 -0
  31. pybhpt-0.9.5/docs/pybhpt.teuk.md +19 -0
  32. pybhpt-0.9.5/docs/requirements.txt +7 -0
  33. {pybhpt-0.9.4 → pybhpt-0.9.5}/pybhpt/geo.py +126 -0
  34. {pybhpt-0.9.4 → pybhpt-0.9.5}/pybhpt/radial.py +70 -7
  35. pybhpt-0.9.5/pybhpt/swsh.py +481 -0
  36. {pybhpt-0.9.4 → pybhpt-0.9.5}/pybhpt/teuk.py +197 -6
  37. {pybhpt-0.9.4 → pybhpt-0.9.5}/pyproject.toml +1 -1
  38. pybhpt-0.9.4/pybhpt/swsh.py +0 -347
  39. {pybhpt-0.9.4 → pybhpt-0.9.5}/.gitmodules +0 -0
  40. {pybhpt-0.9.4 → pybhpt-0.9.5}/CMakeLists.txt +0 -0
  41. {pybhpt-0.9.4 → pybhpt-0.9.5}/LICENSE +0 -0
  42. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/bessel.hpp +0 -0
  43. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/cf.hpp +0 -0
  44. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/fluxes.hpp +0 -0
  45. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/geo.hpp +0 -0
  46. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/gsn_asymp.hpp +0 -0
  47. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/hertz.hpp +0 -0
  48. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/hypergeo_f.hpp +0 -0
  49. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/hypergeo_u.hpp +0 -0
  50. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/kerr.hpp +0 -0
  51. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/metric.hpp +0 -0
  52. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/metriccoeffs.hpp +0 -0
  53. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/monodromy.hpp +0 -0
  54. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/mst.hpp +0 -0
  55. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/nusolver.hpp +0 -0
  56. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/radialsolver.hpp +0 -0
  57. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/redshift.hpp +0 -0
  58. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/regularization.hpp +0 -0
  59. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/resflux.hpp +0 -0
  60. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/sourceintegration.hpp +0 -0
  61. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/specialfunc.hpp +0 -0
  62. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/teukolsky.hpp +0 -0
  63. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/include/utils.hpp +0 -0
  64. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/bessel.cpp +0 -0
  65. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/cf.cpp +0 -0
  66. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/fluxes.cpp +0 -0
  67. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/geo.cpp +0 -0
  68. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/gsn_asymp.cpp +0 -0
  69. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/hertz.cpp +0 -0
  70. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/hypergeo_f.cpp +0 -0
  71. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/hypergeo_u.cpp +0 -0
  72. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/kerr.cpp +0 -0
  73. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/metric.cpp +0 -0
  74. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/metriccoeffs.cpp +0 -0
  75. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/monodromy.cpp +0 -0
  76. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/mst.cpp +0 -0
  77. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/nusolver.cpp +0 -0
  78. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/radialsolver.cpp +0 -0
  79. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/redshift.cpp +0 -0
  80. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/regularization.cpp +0 -0
  81. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/resflux.cpp +0 -0
  82. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/sourceintegration.cpp +0 -0
  83. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/specialfunc.cpp +0 -0
  84. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/teukolsky.cpp +0 -0
  85. {pybhpt-0.9.4 → pybhpt-0.9.5}/cpp/src/utils.cpp +0 -0
  86. {pybhpt-0.9.4 → pybhpt-0.9.5}/cython/flux_wrap.pyx +0 -0
  87. {pybhpt-0.9.4 → pybhpt-0.9.5}/cython/geo_wrap.pyx +0 -0
  88. {pybhpt-0.9.4 → pybhpt-0.9.5}/cython/radialsolver_wrap.pyx +0 -0
  89. {pybhpt-0.9.4 → pybhpt-0.9.5}/cython/redshift_wrap.pyx +0 -0
  90. {pybhpt-0.9.4 → pybhpt-0.9.5}/environment-extended.yml +0 -0
  91. {pybhpt-0.9.4 → pybhpt-0.9.5}/environment.yml +0 -0
  92. {pybhpt-0.9.4 → pybhpt-0.9.5}/notebooks/flux-example.ipynb +0 -0
  93. {pybhpt-0.9.4 → pybhpt-0.9.5}/pybhpt/__init__.py +0 -0
  94. {pybhpt-0.9.4 → pybhpt-0.9.5}/pybhpt/flux.py +0 -0
  95. {pybhpt-0.9.4 → pybhpt-0.9.5}/pybhpt/hertz.py +0 -0
  96. {pybhpt-0.9.4 → pybhpt-0.9.5}/pybhpt/metric.py +0 -0
  97. {pybhpt-0.9.4 → pybhpt-0.9.5}/pybhpt/redshift.py +0 -0
  98. {pybhpt-0.9.4 → pybhpt-0.9.5}/tests/test_geo.py +0 -0
  99. {pybhpt-0.9.4 → pybhpt-0.9.5}/tests/test_radial.py +0 -0
  100. {pybhpt-0.9.4 → pybhpt-0.9.5}/tests/test_teuk.py +0 -0
@@ -0,0 +1,13 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-22.04
5
+ tools:
6
+ python: "3.9"
7
+
8
+ python:
9
+ install:
10
+ - requirements: docs/requirements.txt
11
+
12
+ sphinx:
13
+ configuration: docs/conf.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pybhpt
3
- Version: 0.9.4
3
+ Version: 0.9.5
4
4
  Summary: Black Hole Perturbation Theory and Self-Force Algorithms in Python
5
5
  Author-Email: Zach Nasipak <znasipak@gmail.com>
6
6
  License: GPL
@@ -30,11 +30,11 @@ Description-Content-Type: text/markdown
30
30
 
31
31
  # pybhpt
32
32
 
33
- A python package for solving problems in black hole perturbation theory
33
+ A python package for solving problems in black hole perturbation theory.
34
34
 
35
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
36
 
37
- - `pybhpt.geodesic`: a module that generates bound timelike geodesics in Kerr spacetime
37
+ - `pybhpt.geodesic`: a module that generates bound periodic timelike geodesics in Kerr spacetime
38
38
  - `pybhpt.radial`: a module that calculates homogeneous solutions of the radial Teukolsky equation
39
39
  - `pybhpt.swsh`: a module that constructs the spin-weighted spheroidal harmonics
40
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
@@ -43,9 +43,11 @@ A python package for solving problems in black hole perturbation theory
43
43
  - `pybhpt.metric`: a module that produces the coefficients needed to reconstruct the metric from the Hertz potentials
44
44
  - `pybhpt.redshift`: a module that computes the generalized Detweiler redshift invariant in a variety of gauges
45
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
+
46
48
  ## Quick Installation
47
49
 
48
- Tagged releases of `pybhpt` are available as wheel packages for macOS and 64-bit Linux on [PyPI](https://pypi.org/project/matplotlib/). Install using `pip`:
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`:
49
51
  ```
50
52
  python3 -m pip install pybhpt
51
53
  ```
@@ -130,6 +132,14 @@ To include the necessary compiler on Linux:
130
132
  conda install gcc_linux-64 gxx_linux-64
131
133
  ```
132
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
+
133
143
  ## Authors
134
144
 
135
145
  Zachary Nasipak
@@ -1,10 +1,10 @@
1
1
  # pybhpt
2
2
 
3
- A python package for solving problems in black hole perturbation theory
3
+ A python package for solving problems in black hole perturbation theory.
4
4
 
5
5
  `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:
6
6
 
7
- - `pybhpt.geodesic`: a module that generates bound timelike geodesics in Kerr spacetime
7
+ - `pybhpt.geodesic`: a module that generates bound periodic timelike geodesics in Kerr spacetime
8
8
  - `pybhpt.radial`: a module that calculates homogeneous solutions of the radial Teukolsky equation
9
9
  - `pybhpt.swsh`: a module that constructs the spin-weighted spheroidal harmonics
10
10
  - `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
@@ -13,9 +13,11 @@ A python package for solving problems in black hole perturbation theory
13
13
  - `pybhpt.metric`: a module that produces the coefficients needed to reconstruct the metric from the Hertz potentials
14
14
  - `pybhpt.redshift`: a module that computes the generalized Detweiler redshift invariant in a variety of gauges
15
15
 
16
+ 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.
17
+
16
18
  ## Quick Installation
17
19
 
18
- Tagged releases of `pybhpt` are available as wheel packages for macOS and 64-bit Linux on [PyPI](https://pypi.org/project/matplotlib/). Install using `pip`:
20
+ 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`:
19
21
  ```
20
22
  python3 -m pip install pybhpt
21
23
  ```
@@ -100,6 +102,14 @@ To include the necessary compiler on Linux:
100
102
  conda install gcc_linux-64 gxx_linux-64
101
103
  ```
102
104
 
105
+ ## References
106
+
107
+ Theoretical background for the code and explanations of the numerical methods used within are summarized in the references below:
108
+
109
+ - 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)
110
+ - 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)
111
+ - 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)
112
+
103
113
  ## Authors
104
114
 
105
115
  Zachary Nasipak
@@ -12,12 +12,15 @@ else
12
12
  CORES=$(sysctl -n hw.ncpu)
13
13
  fi
14
14
 
15
- # Download source
15
+ # Download source (use mirror redirector + retries)
16
16
  mkdir -p /tmp/gsl-src
17
17
  cd /tmp/gsl-src
18
- curl -LO https://ftp.gnu.org/gnu/gsl/gsl-${GSL_VERSION}.tar.gz
19
- tar -xzf gsl-${GSL_VERSION}.tar.gz
20
- cd gsl-${GSL_VERSION}
18
+ curl --fail --location --retry 5 --retry-delay 5 \
19
+ "https://ftpmirror.gnu.org/gsl/gsl-${GSL_VERSION}.tar.gz" \
20
+ -o "gsl-${GSL_VERSION}.tar.gz"
21
+
22
+ tar -xzf "gsl-${GSL_VERSION}.tar.gz"
23
+ cd "gsl-${GSL_VERSION}"
21
24
 
22
25
  # Build & install
23
26
  echo "Configuring GSL ${GSL_VERSION}..."
@@ -86,7 +86,6 @@ int spectral_matrix(const int &s, const int &lmin, const int &m, const double &g
86
86
  int spectral_matrix_sparse_init(const int &s, const int &lmin, const int &m, const double &g, gsl_spmatrix* mat);
87
87
  int spectral_matrix_sparse(const int &s, const int &lmin, const int &m, const double &g, gsl_spmatrix* mat, const size_t &nmax);
88
88
 
89
-
90
89
  // Solve eigensystem of spectral matrix
91
90
  int spectral_solver(const int &s, const int &l, const int &m, const double &g, double& la, Vector& bvec);
92
91
 
@@ -718,6 +718,7 @@ Complex Yslm(const int &s, const int &l, const int &m, const double &th, const d
718
718
 
719
719
  double Yslm(const int &s, const int &l, const int &m, const double &th){
720
720
  if( s == 0 ) return Ylm(l, m, th);
721
+ if( th == 0.) return pow(-1, s)*Yslm(0, l, 0, 0.);
721
722
 
722
723
  int lmin = std::max(std::abs(m), l - std::abs(s));
723
724
  int lmax = l + std::abs(s);
@@ -0,0 +1,70 @@
1
+ from libcpp.vector cimport vector
2
+ from libcpp.complex cimport complex as cpp_complex
3
+ import numpy as np
4
+ cimport numpy as np
5
+
6
+ cdef extern from "gsl/gsl_errno.h":
7
+ void gsl_set_error_handler_off()
8
+
9
+ # If you need to disable GSL error handling, do so in a targeted way within specific functions.
10
+ # gsl_set_error_handler_off() # Removed global call to avoid masking numerical errors.
11
+
12
+ cdef extern from "swsh.hpp":
13
+ cdef cppclass SpinWeightedHarmonic:
14
+ SpinWeightedHarmonic(int s, int L, int m, double gamma, vector[double]& theta)
15
+
16
+ int getSpinWeight()
17
+ int getSpheroidalModeNumber()
18
+ int getAzimuthalModeNumber()
19
+ double getSpheroidicity()
20
+ double getEigenvalue()
21
+ vector[double] getCouplingCoefficient()
22
+ double getCouplingCoefficient(int l)
23
+ int getMinCouplingModeNumber()
24
+ int getMaxCouplingModeNumber()
25
+
26
+ int generateSolutionsAndDerivatives()
27
+ int generateCouplingCoefficients()
28
+ int generateSolutions()
29
+ int generateDerivatives()
30
+
31
+ vector[double] getArguments()
32
+ vector[double] getSolution()
33
+ vector[double] getDerivative()
34
+ vector[double] getSecondDerivative()
35
+
36
+ double getArguments(int pos)
37
+ double getSolution(int pos)
38
+ double getDerivative(int pos)
39
+ double getSecondDerivative(int pos)
40
+
41
+ double Asljm(int &s, int &l, int &j, int &m)
42
+ double dAsljm(int &s, int &l, int &j, int &m)
43
+
44
+ double clebsch(int &j1, int &j2, int &j, int &m1, int &m2, int &m)
45
+ double w3j(int &j1, int &j2, int &j, int &m1, int &m2, int &m)
46
+
47
+ cpp_complex[double] Sslm(int &s, int &l, int &m, double &g, double &th, double &ph)
48
+ double Sslm(int &s, int &l, int &m, double &g, double &th)
49
+
50
+ double Sslm(int &s, int &l, int &m, double &g, vector[double]& bvec, double &th)
51
+ double Sslm_derivative(int &s, int &l, int &m, double &g, vector[double]& bvec, double &th)
52
+ double Sslm_secondDerivative(int &s, int &l, int &m, double &g, double& la, double &th, double &Slm, double &SlmP)
53
+
54
+ double swsh_eigenvalue(int &s, int &l, int &m, double &g)
55
+
56
+ cpp_complex[double] Yslm(int &s, int &l, int &m, double &th, double &ph)
57
+ double Yslm(int &s, int &l, int &m, double &th) except +
58
+ double Yslm_derivative(int &s, int &l, int &m, double &th)
59
+
60
+ def YslmCy(int s, int l, int m, double theta):
61
+ return Yslm(s, l, m, theta)
62
+
63
+ def YslmCy_derivative(int s, int l, int m, double theta):
64
+ return Yslm_derivative(s, l, m, theta)
65
+
66
+ def clebschCy(int j1, int j2, int j, int m1, int m2, int m):
67
+ return clebsch(j1, j2, j, m1, m2, m)
68
+
69
+ def w3jCy(int j1, int j2, int j, int m1, int m2, int m):
70
+ return w3j(j1, j2, j, m1, m2, m)
@@ -7,6 +7,7 @@ cimport numpy as np
7
7
  # from geo_wrap cimport GeodesicSource
8
8
  include "geo_wrap.pyx"
9
9
  include "radialsolver_wrap.pyx"
10
+ include "swsh_wrap.pyx"
10
11
 
11
12
  cdef extern from "teukolsky.hpp":
12
13
  cdef cppclass SpinWeightedHarmonic:
@@ -0,0 +1,12 @@
1
+ # Clean target to remove build directory
2
+ clean:
3
+ rm -rf _build
4
+ # Minimal Sphinx Makefile
5
+ SPHINXOPTS =
6
+ SPHINXBUILD = sphinx-build
7
+ SOURCEDIR = .
8
+ BUILDDIR = _build
9
+
10
+ .PHONY: html
11
+ html:
12
+ $(SPHINXBUILD) -b html $(SOURCEDIR) $(BUILDDIR)/html $(SPHINXOPTS)
@@ -0,0 +1,26 @@
1
+ # About
2
+
3
+ `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.
4
+
5
+ ## Subpackages
6
+ - [`pybhpt.geo`](pybhpt.geo): generates bound periodic timelike geodesics in Kerr spacetime
7
+ - [`pybhpt.radial`](pybhpt.radial): calculates homogeneous solutions of the radial Teukolsky equation
8
+ - [`pybhpt.swsh`](pybhpt.swsh): constructs the spin-weighted spheroidal harmonics
9
+ - [`pybhpt.teuk`](pybhpt.teuk): evaluates inhomogeneous solutions (Teukolsky amplitudes) of the radial Teukolsky equation due to a point-particle on a bound timelike Kerr geodesic
10
+ - [`pybhpt.flux`](pybhpt.flux): produces gravitational wave fluxes sourced by a point-particle on a generic bound timelike Kerr geodesic
11
+ - [`pybhpt.hertz`](pybhpt.hertz): solves for the Hertz potentials for the CCK and AAB metric reconstruction procedures
12
+ - [`pybhpt.metric`](pybhpt.metric): produces coefficients needed to reconstruct the metric from the Hertz potentials
13
+ - [`pybhpt.redshift`](pybhpt.redshift): computes the generalized Detweiler redshift invariant in a variety of gauges
14
+
15
+ One can find out more information about each module by exploring the User Guides or clicking on the subpackages, which are linked to the API.
16
+
17
+ ## References
18
+
19
+ Theoretical background for the code and explanations of the numerical methods used within are summarized in the references below:
20
+
21
+ - 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)
22
+ - 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)
23
+ - 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)
24
+
25
+ ## Authors
26
+ Zachary Nasipak
@@ -0,0 +1,76 @@
1
+ # Geodesics in Kerr
2
+
3
+ We work in a Kerr background with angular momentum and mass parameters $(J, M)$ and use Boyer-Lindquist coordinates $(t, r, \theta, \phi)$.
4
+
5
+ Bound periodic timelike geodesics in Kerr spacetime are defined in terms of the turning points of the motion:
6
+
7
+ - $r_\mathrm{min}$ : minimum Boyer-Lindquist radius
8
+ - $r_\mathrm{max}$ : maximum Boyer-Lindquist radius
9
+ - $\theta_\mathrm{min}$ : minimum Boyer-Lindquist polar angle
10
+ - $\pi-\theta_\mathrm{min}$ : maximum Boyer-Lindquist polar angle
11
+
12
+ From these we parametrize the geodesic in terms of the generalized Keplerian parameters:
13
+
14
+ - $a$ : the dimensionless Kerr spin parameter
15
+ - $p$ : the dimensionless semilatus rectum
16
+ - $e$ : the orbital eccentricty
17
+ - $x$ : cosine of the orbital inclination
18
+
19
+ where $a = J/M^2$, $pM = 2r_\mathrm{max}r_\mathrm{min}/(r_\mathrm{min}+r_\mathrm{max})$ and $e = (r_\mathrm{max}-r_\mathrm{min})/(r_\mathrm{min}+r_\mathrm{max})$. The motion can also be described in terms of the conserved orbital constants:
20
+
21
+ - $E$ : the specific orbital energy
22
+ - $L_z$ : the specific orbital angular momentum
23
+ - $Q$ : the Carter constant
24
+
25
+ which have units $\{1, M, M^2\}$, respectively, along with the mass of the small body $\mu$.
26
+
27
+ With these conserved quantities, we obtain four first-order ordinary differential equations (ODEs) for $x_p^\mu$, which decouple when parametrized in terms of the Mino(-Carter) time parameter $\lambda$,
28
+ $$\begin{align}
29
+ \frac{dt_p}{d\lambda} &= V_{tr}(r_p) + V_{t\theta}(\theta_p),
30
+ \\
31
+ \frac{dr_p}{d\lambda} &= \pm \sqrt{V_r(r_p)},
32
+ \\
33
+ \frac{d\theta_p}{d\lambda} &= \pm \sqrt{V_\theta(\theta_p)},
34
+ \\
35
+ \frac{d\phi_p}{d\lambda} &= V_{\phi r}(r_p) + V_{\phi \theta}(\theta_p),
36
+ \end{align}$$
37
+ where $d\lambda = \Sigma^{-1} d\tau$, and the potential functions are given by
38
+ $$\begin{align}
39
+ V_{r}(r) &= { P^2(r) - \Delta\left(r^2 + {K} \right),}
40
+ &
41
+ V_{\theta}(\theta) &= {{Q} - {L}_z^2 \cot^2\theta - a^2 (1 -{E}^2)\cos^2\theta,}
42
+ \\
43
+ V_{tr}(r) &= \frac{r^2+a^2}{\Delta}P(r),
44
+ &
45
+ V_{t\theta}(\theta) &= a{L}_z - a^2 {E} \sin^2\theta,
46
+ \\
47
+ V_{\phi r}(r) &= \frac{a}{\Delta}P(r),
48
+ &
49
+ V_{\phi \theta}(\theta) &= {L}_z \csc^2\theta - a {E},
50
+ \end{align}$$
51
+
52
+ with $P(r) = (r^2+a^2){E} - a {L}_z$.
53
+
54
+ The resulting bound solutions can be separated into terms that are periodic with respect to the Mino time radial and polar frequencies $\Upsilon_r$ and $\Upsilon_\theta$ and terms that grow secularly with the Mino time rates $\Upsilon_t$ and $\Upsilon_\phi$.
55
+ Therefore, the fundamental coordinate time frequencies are given by
56
+ $$\begin{align}
57
+ \Omega_r &= \frac{\Upsilon_r}{\Upsilon_t},
58
+ &
59
+ \Omega_\theta &= \frac{\Upsilon_\theta}{\Upsilon_t},
60
+ &
61
+ \Omega_\phi &= \frac{\Upsilon_\phi}{\Upsilon_t}.
62
+ \end{align}$$
63
+
64
+ We then represent the radial and polar motion by
65
+ $$\begin{align}
66
+ r_p(\lambda) &= \Delta r^{(r)}(\Upsilon_r\lambda) = \Delta r^{(r)}(\Upsilon_r\lambda + 2\pi),
67
+ \\
68
+ \theta_p(\lambda) &= \Delta \theta^{(\theta)}(\Upsilon_\theta\lambda) = \Delta \theta^{(\theta)}(\Upsilon_\theta\lambda + 2\pi),
69
+ \end{align}$$
70
+ while time and azimuthal angle grow as
71
+ $$\begin{align}
72
+ t_p(\lambda) &= \Upsilon_t \lambda + \Delta t^{(r)}(\Upsilon_r\lambda) + \Delta t^{(\theta)}(\Upsilon_\theta\lambda),
73
+ \\
74
+ \phi_p(\lambda) &= \Upsilon_\phi \lambda + \Delta \phi^{(r)}(\Upsilon_r\lambda) + \Delta \phi^{(\theta)}(\Upsilon_\theta\lambda),
75
+ \end{align}$$
76
+ where $\Delta t^{(r)}$, $\Delta \phi^{(r)}$, $\Delta t^{(\theta)}$, and $\Delta \phi^{(\theta)}$ are $2\pi$-periodic odd functions.
@@ -0,0 +1,38 @@
1
+ # Radial Teukolsky equation
2
+
3
+ The radial Teukolsky equation for spin-weight $s$, harmonic numbers $(j,m)$, frequency $\omega$, and $a$ the dimensionless Kerr spin parameter is given by
4
+ $$\left[\Delta^{-s} \frac{d}{dr} \left(\Delta^{s+1} \frac{d }{dr} \right) + \left(\frac{K^2-2is(r-M)K}{\Delta}+4is\omega r - \lambda_{sjm\omega} \right)\right]R_{sjm\omega} = T_{slm\omega},$$
5
+ where $\Delta=r^2-2Mr+a^2$, $K=(r^2+a^2)\omega-ma$, $\lambda_{sjm\omega}$ is the spheroidal eigenvalue (separation constant), and $T_{slm\omega}$ is the radial decomposition of the source.
6
+
7
+ ## Homogeneous solutions
8
+
9
+ For $T_{slm\omega} = 0$, we construct the homogeneous solutions $R^\mathrm{In}_{sjm\omega}$ and $R^\mathrm{Up}_{sjm\omega}$, which correspond to the asymptotic boundary conditions
10
+ $$\begin{align}
11
+ R^\mathrm{In}_{sjm\omega} (r \rightarrow r_+) &\sim A^\mathrm{trans}_s \Delta^{-s} e^{-i k r_*},
12
+ \\
13
+ R^\mathrm{In}_{sjm\omega} (r \rightarrow \infty) &\sim A^\mathrm{ref}_s r^{-(2s+1)} e^{i\omega r_*}
14
+ + A^\mathrm{inc}_s r^{-1} e^{-i\omega r_*},
15
+ \\
16
+ R^\mathrm{Up}_{sjm\omega} (r \rightarrow r_+) &\sim B^\mathrm{ref}_s \Delta^{-s} e^{-i k r_*}
17
+ + B^\mathrm{inc}_s e^{i k r_*},
18
+ \\
19
+ R^\mathrm{Up}_{sjm\omega} (r \rightarrow \infty) &\sim
20
+ B^\mathrm{trans}_s r^{-(2s+1)} e^{i\omega r_*},
21
+ \end{align}$$
22
+ where $k = \omega - m \omega_+$, $\omega_+ = a/(2Mr_+)$, and the tortoise coordinate is given by the differential relation $dr_{*}/dr = (r^2+a^2)/\Delta$, which can be immediately integrated, leading to
23
+ $$r_* = r + \frac{r_+}{\kappa} \ln \frac{r-r_+}{2M} - \frac{r_-}{\kappa} \ln \frac{r-r_-}{2M},$$
24
+ where $\kappa = \sqrt{1 - q^2}$ and $q = a/M$.
25
+
26
+ ## Inhomogeneous solutions
27
+
28
+ Rather than constructing the full inhomogeneous solutions, we can instead construct the so-called *extended homogeneous solutions* for a point-particle source on a bound periodic geodesic,
29
+ $$\begin{align}
30
+ \Psi_s &= \Psi_s^+ \Theta(r-r_p) + \Psi_s^- \Theta(r_p-r),
31
+ \\
32
+ \Psi_s^\pm &= \sum_{jmkn}\Psi^\pm_{sjmkn}(r)S_{sj\gamma_{mkn}}(\theta)e^{im\phi}e^{-i\omega_{mkn}t},
33
+ \end{align}$$
34
+ where we have the mode frequencies $\omega_{mkn} = m\Omega_\phi + k \Omega_\theta + n \Omega_r$, the discrete spheroidicity $\gamma_{mkn} = a\omega_{mkn}$, and the extended homogeneous radial solutions
35
+ $$
36
+ \Psi^\pm_{sjmkn}(r) = Z^{\mathrm{Up/In}}_{sjmkn} R^{\mathrm{Up/In}}_{sjmkn}(r),
37
+ $$
38
+ with Teukolsky amplitudes $Z^{\mathrm{Up/In}}_{sjmkn}$.
@@ -0,0 +1,42 @@
1
+ # Angular Teukolsky equation
2
+
3
+ The spin-weighted spheroidal harmonics $S_{sjm\gamma}(\theta)$ satisfy the equation
4
+ $$
5
+ \left[\frac{1}{\sin\theta}\frac{d}{d\theta}\left(\sin\theta \frac{d}{d\theta} \right)
6
+ - \left(\gamma^2\sin^2\theta+\frac{(m+s\cos\theta)^2}{\sin^2\theta}
7
+ +2\gamma s\cos\theta-s-2m\gamma-\lambda_{sjm\gamma} \right)\right]S_{sjm\gamma} = 0,
8
+ $$
9
+ with eigenvalues $\lambda_{sjm\gamma}$ and spheroidicity $\gamma$. For the Teukolsky equation, $\gamma = a\omega$.
10
+
11
+ The spheroidal harmonics can be expressed as rapidly convergent sums of spin-weighted spherical harmonics,
12
+ $$
13
+ S_{sjm\gamma}(\theta)e^{im\phi} = \sum_{\ell = \ell_\mathrm{min}}^\infty b^{\ell}_{sjm\gamma} Y_{s\ell m}(\theta,\phi),
14
+ $$
15
+ where $\ell_\mathrm{min} = \mathrm{max}[|m|, |s|]$ and the coupling coefficients $b^{\ell}_{sjm\gamma}$ satisfy a five-term recursion relation. Similarly we can represent spin-weighted spherical harmonics as finite series of *scalar* spherical harmonics $Y_{lm}=Y_{0lm}$
16
+ $$
17
+ Y_{s\ell m}(\theta)
18
+ = \sin^{-|s|}\theta \sum_{l=|m|}^\infty \mathcal{A}^l_{s\ell m}
19
+ Y_{lm}(\theta),
20
+ $$
21
+ where the coefficients are given analytically in terms of the Wigner $3j$ symbol,
22
+ $$\begin{align}
23
+ \mathcal{A}^l_{s\ell m} &=
24
+ (-1)^{m+s(1+\mathrm{sgn}(s))/2} \mathcal{C}_{|s|\ell l}
25
+ \left(
26
+ \begin{array}{ccc}
27
+ |s| & \ell & l
28
+ \\
29
+ 0 & m & -m
30
+ \end{array}
31
+ \right)
32
+ \left(
33
+ \begin{array}{ccc}
34
+ |s| & \ell & l
35
+ \\
36
+ s & -s & 0
37
+ \end{array}
38
+ \right),
39
+ \\
40
+ \mathcal{C}_{s\ell l} &= \sqrt{\frac{4^{s} (s!)^2 (2\ell+1)(2l+1)}{(2s)!}}.
41
+ \end{align}$$
42
+ The selection rules of the $3j$-symbol mean that the coefficients vanish unless $\ell - |s| \leq l \leq \ell + |s|$.
@@ -0,0 +1,42 @@
1
+ # Teukolsky equation
2
+
3
+ In Boyer-Lindquist coordinates $(t,r,\theta,\phi)$, the Teukolsky equation takes the form
4
+ $$\begin{align}
5
+ \mathcal{O}^T_s \Psi_s = -4\pi \zeta\bar{\zeta} T_s,
6
+ \end{align}$$
7
+ where $\zeta=r-ia\cos\theta$, $T_s$ is the (tetrad-projected) source, and the spin-weighted Teukolsky operator is given by,
8
+ $$\begin{align}
9
+ \mathcal{O}^T_s &:=-\left(\frac{(r^2+a^2)^2}{\Delta} - a^2 \sin^2\theta\right)\partial_t^2 - \frac{4 M a r}{\Delta} \partial_t \partial_\phi - \left(\frac{a^2}{\Delta} - \frac{1}{\sin^2\theta}\right)\partial_\phi^2
10
+ \\
11
+ & \qquad \qquad + \Delta^{-s}\partial_r\left(\Delta^{s+1} \partial_r\right) + \frac{1}{\sin\theta}\partial_\theta\left({\sin\theta}\partial_\theta \right) + 2s\left(\frac{M(r^2-a^2)}{\Delta} - r-ia\cos\theta \right)\partial_t
12
+ \\ \notag
13
+ & \qquad \qquad \qquad \qquad +2 s\left(\frac{a(r-M)}{\Delta} - \frac{i\cos\theta}{\sin^2\theta} \right)\partial_\phi - s\left(\frac{s\cos^2\theta}{\sin^2\theta} - 1\right),
14
+ \end{align}$$
15
+ with $\Delta = r^2-2Mr+a^2$, and $\Psi_{0}=\Phi$ for scalar perturbations; $\Psi_{+1}=\phi_0$ and $\Psi_{-1}=\zeta^2\phi_2$ ; and $\Psi_{+2}=\psi_0$ and $\Psi_{-2}=\zeta^4\psi_4$ for gravitational perturbations.
16
+
17
+ Transforming to the frequency domain, the fields and sources can be mode-decomposed into
18
+ $$\begin{align}
19
+ \Psi_s = \int d\omega \sum_{jm} \Psi_{sjm\omega}(r) S_{sjm\gamma}(\theta) e^{im\phi} e^{-i\omega t},
20
+ \\
21
+ T_s = \int d\omega \sum_{jm} T_{sjm\omega}(r) S_{sjm\gamma}(\theta) e^{im\phi} e^{-i\omega t},
22
+ \end{align}$$
23
+ with $\gamma = a\omega$, leading to separated ODEs
24
+ $$\left[\Delta^{-s} \frac{d}{dr} \left(\Delta^{s+1} \frac{d }{dr} \right) + \left(\frac{K^2-2is(r-M)K}{\Delta}+4is\omega r - \lambda_{sjm\omega} \right)\right]R_{sjm\omega} = T_{slm\omega},$$
25
+ and
26
+ $$
27
+ \left[\frac{1}{\sin\theta}\frac{d}{d\theta}\left(\sin\theta \frac{d}{d\theta} \right)
28
+ - \left(\gamma^2\sin^2\theta+\frac{(m+s\cos\theta)^2}{\sin^2\theta}
29
+ +2\gamma s\cos\theta-s-2m\gamma-\lambda_{sjm\gamma} \right)\right]S_{sjm\gamma} = 0,
30
+ $$
31
+ with eigenvalues $\lambda_{sjm\gamma}$ and spheroidicity $\gamma$.
32
+
33
+ The time-averaged rate of change of the orbital energy $\langle \dot{E}\rangle$, angular momentum $\langle \dot{L}_z\rangle$, and Carter constant $\langle \dot{Q}\rangle$ can then be expressed in terms of the Teukolsky amplitudes $Z^\mathrm{Up/In}_{sjmkn}$,
34
+ $$
35
+ \begin{align}
36
+ \langle \dot{\mathcal{J}} \rangle & = \langle \dot{\mathcal{J}} \rangle^\mathrm{inf} + \langle \dot{\mathcal{J}} \rangle^\mathrm{hor},
37
+ \\
38
+ &= \sum_{jmkn} \langle \dot{\mathcal{J}} \rangle^\mathrm{inf/hor}_{jmkn},
39
+ \\
40
+ &= \sum_{jmkn} \alpha_{sjmkn}^{(\mathcal{J})\mathrm{inf/hor}}\left| Z^\mathrm{Up/In}_{sjmkn} \right|^2,
41
+ \end{align}$$
42
+ where $\mathcal{J} = (E, L_z, Q)$, $\alpha_{sjmkn}^{(\mathcal{J})\mathrm{inf}/\mathrm{hor}}$ are known coefficients, and $s=0, \pm 2$ produce either scalar or gravitational fluxes, respectively.
@@ -0,0 +1,51 @@
1
+ import os
2
+ import sys
3
+ import toml
4
+ sys.path.insert(0, os.path.abspath('..'))
5
+
6
+ project = 'pybhpt'
7
+ copyright = '2025, znasipak'
8
+ author = 'znasipak'
9
+
10
+ # Read version from pyproject.toml
11
+ pyproject_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'pyproject.toml'))
12
+ with open(pyproject_path, 'r') as f:
13
+ pyproject = toml.load(f)
14
+ release = pyproject['project']['version']
15
+
16
+ extensions = ['sphinx.ext.autodoc',
17
+ 'sphinx.ext.autosummary',
18
+ 'myst_nb',
19
+ 'sphinx.ext.viewcode',
20
+ 'sphinx.ext.napoleon',]
21
+ napoleon_use_ivar = True
22
+ myst_enable_extensions = ["dollarmath", "amsmath"]
23
+ nb_execution_mode = "off"
24
+ autosummary_generate = True
25
+ myst_dmath_double_inline = True
26
+
27
+ templates_path = ['_templates']
28
+ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
29
+
30
+ autodoc_default_options = {
31
+ 'members': True,
32
+ 'member-order': 'bysource',
33
+ 'special-members': '__call__',
34
+ 'undoc-members': True,
35
+ 'exclude-members': '__weakref__'
36
+ }
37
+
38
+ # -- Options for HTML output -------------------------------------------------
39
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
40
+
41
+ html_theme = 'sphinx_book_theme'
42
+ html_static_path = ['_static']
43
+ html_theme_options = {
44
+ "repository_url": "https://github.com/znasipak/pybhpt",
45
+ "use_repository_button": True,
46
+ "navbar_end": ["navbar-icon-links"],
47
+ }
48
+ html_title = "pybhpt"
49
+ html_context = {
50
+ "default_mode": "light"
51
+ }
@@ -0,0 +1,67 @@
1
+ # Welcome to pybhpt's documentation
2
+
3
+ `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.
4
+
5
+ ## Subpackages
6
+ - [`pybhpt.geo`](pybhpt.geo): generates bound periodic timelike geodesics in Kerr spacetime
7
+ - [`pybhpt.radial`](pybhpt.radial): calculates homogeneous solutions of the radial Teukolsky equation
8
+ - [`pybhpt.swsh`](pybhpt.swsh): constructs the spin-weighted spheroidal harmonics
9
+ - [`pybhpt.teuk`](pybhpt.teuk): evaluates inhomogeneous solutions (Teukolsky amplitudes) of the radial Teukolsky equation due to a point-particle on a bound timelike Kerr geodesic
10
+ - [`pybhpt.flux`](pybhpt.flux): produces gravitational wave fluxes sourced by a point-particle on a generic bound timelike Kerr geodesic
11
+ - [`pybhpt.hertz`](pybhpt.hertz): solves for the Hertz potentials for the CCK and AAB metric reconstruction procedures
12
+ - [`pybhpt.metric`](pybhpt.metric): produces coefficients needed to reconstruct the metric from the Hertz potentials
13
+ - [`pybhpt.redshift`](pybhpt.redshift): computes the generalized Detweiler redshift invariant in a variety of gauges
14
+
15
+ One can find out more information about each module by exploring the [User Guides](#contents) or clicking on the subpackages, which are linked to the API. References and author information are provided in the [About](about) section.
16
+
17
+ ## Quick Installation
18
+
19
+ 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`:
20
+ ```
21
+ python3 -m pip install pybhpt
22
+ ```
23
+ Developers can compile from source using the instructions in [Installation](installation). User guides and documentation are provided below.
24
+
25
+ ## Contents
26
+
27
+ ```{toctree}
28
+ :maxdepth: 1
29
+ :caption: User Guides
30
+
31
+ about
32
+ installation
33
+ notebooks/geodesics.ipynb
34
+ notebooks/radial.ipynb
35
+ notebooks/swsh.ipynb
36
+ notebooks/teuk.ipynb
37
+ notebooks/fluxes.ipynb
38
+ notebooks/waveform.ipynb
39
+ notebooks/tutorial.ipynb
40
+ ```
41
+
42
+ ```{toctree}
43
+ :maxdepth: 1
44
+ :caption: Background
45
+
46
+ background/geo
47
+ background/teuk
48
+ background/radial
49
+ background/swsh
50
+ ```
51
+
52
+ ```{toctree}
53
+ :maxdepth: 1
54
+ :caption: API Reference
55
+
56
+ pybhpt.geo
57
+ pybhpt.radial
58
+ pybhpt.swsh
59
+ pybhpt.teuk
60
+ pybhpt.hertz
61
+ pybhpt.flux
62
+ pybhpt.metric
63
+ pybhpt.redshift
64
+ ```
65
+
66
+ ## Authors
67
+ Zachary Nasipak