Home

GeneralizedSasakiNakamura.jl computes solutions to the frequency-domain radial Teukolsky equation with the Generalized Sasaki-Nakamura (GSN) formalism.

The code is capable of handling both ingoing and outgoing radiation of scalar, electromagnetic, and gravitational type (corresponding to spin weight of $s = 0, \pm 1, \pm 2$ respectively).

The angular Teukolsky equation is solved with an accompanying julia package SpinWeightedSpheroidalHarmonics.jl using a spectral decomposition method.

Both codes are capable of handling complex frequencies, and we use $M = 1$ convention throughout.

The paper describing both the GSN formalism and the implementation can be found in 2306.16469. A set of Mathematica notebooks deriving all the equations used in the code can be found in 10.5281/zenodo.8080241.

Installation

To install the package using the Julia package manager, simply type the following in the Julia REPL:

using Pkg
Pkg.add("GeneralizedSasakiNakamura")

Note: There is no need to install SpinWeightedSpheroidalHarmonics.jl separately as it should be automatically installed by the package manager.

Highlights

Performant frequency-domain Teukolsky solver

Works well at both low and high frequencies, and takes only a few tens of milliseconds on average:

GeneralizedSasakiNakamura.jl Teukolsky Mathematica package using the MST method

(There was no caching! We solved the equation on-the-fly! The notebook generating this animation can be found here)

Static/zero-frequency solutions are solved analytically with Gauss hypergeometric functions.

Solutions that are accurate everywhere

Numerical solutions are smoothly stitched to analytical ansatzes near the horizon and infinity at user-specified locations rsin and rsout respectively:

Easy to use

The following code snippet lets you solve the (source-free) Teukolsky function (in frequency domain) for the mode $s=-2, \ell=2, m=2, a/M=0.7, M\omega=0.5$ that satisfies the purely-ingoing boundary condition at the horizon, $R^{\textrm{in}}$, and the purely-outgoing boundary condition at spatial infinity, $R^{\textrm{up}}$, respectively:

using GeneralizedSasakiNakamura # This is going to take some time to pre-compile, mostly due to DifferentialEquations.jl

# Specify which mode to solve
s=-2; l=2; m=2; a=0.7; omega=0.5;

# NOTE: julia uses 'just-ahead-of-time' compilation. Calling this the first time in each session will take some time
Rin, Rup = Teukolsky_radial(s, l, m, a, omega)

That's it! If you run this on Julia REPL, it should give you something like this

(TeukolskyRadialFunction(mode=Mode(s=-2, l=2, m=2, a=0.7, omega=0.5, lambda=1.696609401635342), boundary_condition=IN), TeukolskyRadialFunction(mode=Mode(s=-2, l=2, m=2, a=0.7, omega=0.5, lambda=1.696609401635342), boundary_condition=UP))

In Julia REPL, you can check out all the asymptotic amplitudes at a glimpse using something like

julia> Rin
TeukolskyRadialFunction(
    mode=Mode(s=-2, l=2, m=2, a=0.7, omega=0.5, lambda=1.696609401635342),
    boundary_condition=IN,
    transmission_amplitude=1.0 + 0.0im,
    incidence_amplitude=6.5365876612287765 - 4.9412038970871555im,
    reflection_amplitude=-0.1282466191307726 - 0.440481334972911im,
    normalization_convention=UNIT_TEUKOLSKY_TRANS
)

For example, if we want to evaluate the Teukolsky function $R^{\textrm{in}}$ at the location $r = 10M$, simply do

Rin(10)

This should give

77.57508416835319 - 429.40290952262677im

Solving for complex frequencies

One can use the same interface to compute solutions with complex frequencies. For example, the QNM solution of the $s=-2, \ell=2, m=2, a/M=0.68$ fundamental tone can be obtained using

Rin, Rup = Teukolsky_radial(-2, 2, 2, 0.68, 0.5239751-0.0815126im)

We can check out the $R^{\textrm{up}}$ solution using

julia> Rup
TeukolskyRadialFunction(
    mode=Mode(s=-2, l=2, m=2, a=0.68, omega=0.5239751 - 0.0815126im, lambda=1.655003080578682 + 0.3602676563885877im),
    boundary_condition=UP,
    transmission_amplitude=1.0 + 0.0im,
    incidence_amplitude=-5.850900444651249e-8 - 3.80716581300155e-7im,
    reflection_amplitude=1.1011632133920028 + 2.1300597377432497im,
    normalization_convention=UNIT_TEUKOLSKY_TRANS
)

We see that the incidence amplitude is indeed very small numerically as a QNM solution should. This can be accessed using

Rup.incidence_amplitude

This should give

-5.850900444651249e-8 - 3.80716581300155e-7im

How to cite

If you have used this code in your research that leads to a publication, please cite the following article:

@article{Lo:2023fvv,
    author = "Lo, Rico K. L.",
    title = "{Recipes for computing radiation from a Kerr black hole using a generalized Sasaki-Nakamura formalism: Homogeneous solutions}",
    eprint = "2306.16469",
    archivePrefix = "arXiv",
    primaryClass = "gr-qc",
    doi = "10.1103/PhysRevD.110.124070",
    journal = "Phys. Rev. D",
    volume = "110",
    number = "12",
    pages = "124070",
    year = "2024"
}

Additionally, if you have used this code's capability to solve for solutions with complex frequencies, please also cite the following article:

@article{Lo:2025njp,
    author = "Lo, Rico K. L. and Sabani, Leart and Cardoso, Vitor",
    title = "{Quasinormal modes and excitation factors of Kerr black holes}",
    eprint = "2504.00084",
    archivePrefix = "arXiv",
    primaryClass = "gr-qc",
    doi = "10.1103/PhysRevD.111.124002",
    journal = "Phys. Rev. D",
    volume = "111",
    number = "12",
    pages = "124002",
    year = "2025"
}

License

The package is licensed under the MIT License.