Orbital Properties#

Constants of Motion#

The symmetries of Kerr spacetime generate three constants of motion for any given orbit:

\(E\) - Energy
\(L\) - \(z\)-component of Angular Momentum
\(Q\) - Carter Constant

Energy and angular momentum are generated by time translation symmetry and azimuthal symmetry respectively. The Carter constant is generated by a higher order symmetry of the Kerr metric which comes from a second order Killing tensor known as the Carter tensor.

These constants of motion can be computed for a StableOrbit using the constants_of_motion() method. By default, this method returns dimensionless quantities that are normalized as described in Getting Started.

import kerrgeopy as kg
from math import pi, cos
from IPython.display import display, Math

orbit = kg.StableOrbit(0.9,5,0.6,cos(pi/4))
E, L, Q = orbit.constants_of_motion()

display(Math(rf"\mathcal{{E}} = {E:.3f} \quad \mathcal{{L}} = {L:.3f} \quad \mathcal{{Q}} = {Q:.3f}"))
\[\displaystyle \mathcal{E} = 0.942 \quad \mathcal{L} = 2.028 \quad \mathcal{Q} = 4.160\]

Physical Units#

If \(M\) and \(\mu\) are defined, then constants of motion can be computed in physical units by setting the units option to "mks" or "cgs".

orbit = kg.StableOrbit(0.9,5,0.6,cos(pi/4), M=1e6,mu=10)

E, L, Q = orbit.constants_of_motion(units="mks")

display(Math(fr"""E = {E:.3e} \text{{ J}} 
             \quad L = {L:.3e} \text{{ kg m}}^2 \text{{s}}^{{-1}} 
             \quad Q = {Q:.3e} \text{{ kg}}^2 \text{{m}}^4 \text{{s}}^{{-2}}"""))
\[\displaystyle E = 1.684e+48 \text{ J} \quad L = 3.550e+79 \text{ kg m}^2 \text{s}^{-1} \quad Q = 1.274e+159 \text{ kg}^2 \text{m}^4 \text{s}^{-2}\]

Utility Methods#

Kerrgeopy also provides a constants_of_motion() utility method to compute the constants of motion directly from the orbital parameters \((a,p,e,x)\). The energy(), angular_momentum() and carter_constant() utility methods can be used to compute each of the constants individually.

E, L, Q = kg.constants_of_motion(0.9,5,0.6,cos(pi/4))
E = kg.energy(0.9,5,0.6,cos(pi/4))
L = kg.angular_momentum(0.9,5,0.6,cos(pi/4))
Q = kg.carter_constant(0.9,5,0.6,cos(pi/4))

Frequencies of Motion#

To compute the frequencies of motion in Mino time for a StableOrbit, use the mino_frequencies() method. This method returns the frequencies of motion for each of the three spatial coordinates \((\Upsilon_r,\Upsilon_\theta,\Upsilon_\phi)\) along with \(\Gamma\), which measures the average rate at which observer time accumulates in Mino time. The frequencies of motion can be computed in observer time by simply dividing each of the Mino frequencies by \(\Gamma\), or by using the fundamental_frequencies() method. This method returns the Boyer-Lindquist frequencies \((\Omega_r,\Omega_\theta,\Omega_\phi)\). By default, the frequencies returned by both methods are given in geometrized units where \(G=c=1\) and are normalized by \(M\) so that they are dimensionless.

orbit = kg.StableOrbit(0.9,5,0.6,cos(pi/4))

upsilon_r, upsilon_theta, upsilon_phi, gamma = orbit.mino_frequencies()
omega_r, omega_theta, omega_phi = orbit.fundamental_frequencies()


display(Math(fr"""\Upsilon_r = {upsilon_r:.3f} \quad 
             \Upsilon_\theta = {upsilon_theta:.3f} \quad 
             \Upsilon_\phi = {upsilon_phi:.3f} \quad 
             \Gamma = {gamma:.3f}"""))

display(Math(fr"""\Omega_r = {omega_r:.3f} \quad
            \Omega_\theta = {omega_theta:.3f} \quad
            \Omega_\phi = {omega_phi:.3f}"""))
\[\displaystyle \Upsilon_r = 1.559 \quad \Upsilon_\theta = 2.880 \quad \Upsilon_\phi = 3.369 \quad \Gamma = 56.927\]
\[\displaystyle \Omega_r = 0.027 \quad \Omega_\theta = 0.051 \quad \Omega_\phi = 0.059\]

Physical Units#

As with constants of motion, frequencies can be computed in physical units if M and mu are specified. Note that Mino frequencies have units of seconds, while \(\Gamma\) has units of \(\text{s}^2\). Observer-time frequencies can be given in units of Hz or mHz.

orbit = kg.StableOrbit(0.9,5,0.6,cos(pi/4), M=1e6,mu=10)

upsilon_r, upsilon_theta, upsilon_phi, gamma = orbit.mino_frequencies(units="mks")
omega_r, omega_theta, omega_phi = orbit.fundamental_frequencies(units="mHz")

display(Math(fr"""\Upsilon_r = {upsilon_r:.3f} \text{{ s}} \quad 
             \Upsilon_\theta = {upsilon_theta:.3f} \text{{ s}} \quad 
             \Upsilon_\phi = {upsilon_phi:.3f} \text{{ s}} \quad 
             \Gamma = {gamma:.3f} \text{{ s}}^2"""))

display(Math(fr"""\Omega_r = {omega_r:.3f} \text{{ mHz}} \quad
            \Omega_\theta = {omega_theta:.3f} \text{{ mHz}}\quad
            \Omega_\phi = {omega_phi:.3f} \text{{ mHz}}"""))
\[\displaystyle \Upsilon_r = 7.679 \text{ s} \quad \Upsilon_\theta = 14.188 \text{ s} \quad \Upsilon_\phi = 16.594 \text{ s} \quad \Gamma = 1381.074 \text{ s}^2\]
\[\displaystyle \Omega_r = 5.560 \text{ mHz} \quad \Omega_\theta = 10.273 \text{ mHz}\quad \Omega_\phi = 12.015 \text{ mHz}\]

Utility Methods#

There are also utility methods for computing frequencies of motion directly from the orbital parameters \((a,p,e,x)\). Use the mino_frequencies() and fundamental_frequencies() methods to compute the frequencies as a tuple, or use the r_frequency(), theta_frequency(), phi_frequency(), and gamma() methods to compute each of the Mino frequencies individually.

upsilon_r, upsilon_theta, upsilon_phi, gamma = kg.mino_frequencies(0.9,5,0.6,cos(pi/4))
omega_r, omega_theta, omega_phi = kg.fundamental_frequencies(0.9,5,0.6,cos(pi/4))
upsilon_r = kg.r_frequency(0.9,5,0.6,cos(pi/4))
upsilon_theta = kg.theta_frequency(0.9,5,0.6,cos(pi/4))
upsilon_phi = kg.phi_frequency(0.9,5,0.6,cos(pi/4))
gamma = kg.gamma(0.9,5,0.6,cos(pi/4))

Stability#

Note that not all combinations of orbital parameters \((a,p,e,x)\) define a stable orbit. The boundary in parameter space between stable and unstable orbits is known as the separatrix. It is most convenient to think of the separatrix as defining a minimum stable value of \(p\) for a given set of parameters \((a,e,x)\). Use the separatrix() method to compute this minimum value.

import kerrgeopy as kg
from math import pi, cos

kg.separatrix(0.9,0.6,cos(pi/3))
4.462323556641868

Use the is_stable() method to test if an orbit is stable. Running kg.is_stable(a,p,e,x) is equivalent to checking if p >= kg.separatrix(a,e,x)

kg.is_stable(0.9,5,0.6,cos(pi/3))
True
kg.is_stable(0.9,4,0.6,cos(pi/3))
False

For better performance, use the fast_separatrix() method to construct a faster separatrix function for a given value of \(a\) by interpolating from a grid of \(e\) and \(x\) values. The function returned by this method is slightly less accurate but runs around 100 times faster.

fast_sep = kg.fast_separatrix(a=0.9)
fast_sep(0.6,cos(pi/3))
array([[4.46232356]])
%timeit kg.separatrix(0.9,0.6,cos(pi/3))
119 µs ± 646 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit fast_sep(0.6,cos(pi/3))
1.02 µs ± 3.2 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Spacetime#

Kerrgeopy provides a KerrSpacetime class to model the spacetime around a spinning black hole. Construct a KerrSpacetime by passing in a dimensionless spin \(a\) and mass \(M\) in solar masses.

spacetime = kg.KerrSpacetime(a=0.99,M=1e6)

Metric#

Use the metric() method to evaluate the matrix representation of the metric tensor at a given point in Boyer-Linquist coordinates. For example, to compute the metric tensor at \((t=0,r=5,\theta=\pi/2,\phi=0)\), run the following code.

spacetime.metric(0,5,pi/2,0)
array([[-0.6       ,  0.        ,  0.        , -0.396     ],
       [ 0.        ,  1.56444578,  0.        ,  0.        ],
       [ 0.        ,  0.        , 25.        ,  0.        ],
       [-0.396     ,  0.        ,  0.        , 26.37214   ]])

The norm() method computes the norm of a four vector, defined as \(g_{\mu\nu}u^{\mu}u^{\nu}\), at a given point in spacetime. We can use this method to verify that the norm of the four-velocity for a geodesic is -1.

orbit = kg.StableOrbit(0.99,5,0.6,cos(pi/3))

t0, r0, theta0, phi0 = orbit.initial_position
u0 = orbit.initial_velocity

spacetime.norm(t0,r0,theta0,phi0,u0)
-1.0000000000000004

#