#!/usr/bin/env python # coding: utf-8 # # Walker-Penrose Killing tensor in Kerr spacetime # # This Jupyter/SageMath notebook is relative to the lectures # [Geometry and physics of black holes](https://relativite.obspm.fr/blackholes/). # # It focuses on the Killing tensor $K$ found by Walker & Penrose [[Commun. Math. Phys. **18**, 265 (1970)](https://doi.org/10.1007/BF01649445)]. # # The involved computations are based on tools developed through the [SageManifolds](https://sagemanifolds.obspm.fr) project. # *NB:* a version of SageMath at least equal to 8.2 is required to run this notebook: # In[1]: version() # First we set up the notebook to display mathematical objects using LaTeX rendering: # In[2]: get_ipython().run_line_magic('display', 'latex') # To speed up the computations, we ask for running them in parallel on 8 threads: # In[3]: Parallelism().set(nproc=8) # ## Spacetime manifold # # We declare the Kerr spacetime (or more precisely the Boyer-Lindquist domain of Kerr spacetime) as a 4-dimensional Lorentzian manifold: # In[4]: M = Manifold(4, 'M', latex_name=r'\mathcal{M}', structure='Lorentzian') print(M) # Let us declare the **Boyer-Lindquist coordinates** via the method `chart()`, the argument of which is a string expressing the coordinates names, their ranges (the default is $(-\infty,+\infty)$) and their LaTeX symbols: # In[5]: BL. = M.chart(r't r th:(0,pi):\theta ph:(0,2*pi):\phi') print(BL) ; BL # In[6]: BL[0], BL[1] # In[7]: BL.coord_range() #

Metric tensor

# #

The 2 parameters $m$ and $a$ of the Kerr spacetime are declared as symbolic variables:

# In[8]: var('m, a', domain='real') # We get the (yet undefined) spacetime metric by # In[9]: g = M.metric() #

The metric is set by its components in the coordinate frame associated with Boyer-Lindquist coordinates, which is the current manifold's default frame:

# In[10]: rho2 = r^2 + (a*cos(th))^2 Delta = r^2 -2*m*r + a^2 g[0,0] = -(1-2*m*r/rho2) g[0,3] = -2*a*m*r*sin(th)^2/rho2 g[1,1], g[2,2] = rho2/Delta, rho2 g[3,3] = (r^2+a^2+2*m*r*(a*sin(th))^2/rho2)*sin(th)^2 g.display() #

A matrix view of the components with respect to the manifold's default vector frame:

# In[11]: g[:] #

The list of the non-vanishing components:

# In[12]: g.display_comp() #

Levi-Civita Connection

# #

The Levi-Civita connection $\nabla$ associated with $g$:

# In[13]: nabla = g.connection() ; print(nabla) #

Let us verify that the covariant derivative of $g$ with respect to $\nabla$ vanishes identically:

# In[14]: nabla(g).display() #

Killing vectors

#

The default vector frame on the spacetime manifold is the coordinate basis associated with Boyer-Lindquist coordinates:

# In[15]: M.default_frame() is BL.frame() # In[16]: BL.frame() #

Let us consider the first vector field of this frame:

# In[17]: xi = BL.frame()[0] ; xi # In[18]: print(xi) #

The 1-form associated to it by metric duality is

# In[19]: xi_form = xi.down(g) ; xi_form.display() #

Its covariant derivative is

# In[20]: nab_xi = nabla(xi_form) ; print(nab_xi) ; nab_xi.display() #

Let us check that the Killing equation is satisfied:

# In[21]: nab_xi.symmetrize() == 0 #

Similarly, let us check that $\frac{\partial}{\partial\phi}$ is a Killing vector:

# In[22]: eta = BL.frame()[3] ; eta # In[23]: nabla(eta.down(g)).symmetrize() == 0 # ## Principal null vectors # # Let $k$ be the null vector tangent to the ingoing principal null geodesics associated # with their affine parameter $-r$; the expression of $k$ in term of the 3+1 ingoing Kerr coordinates $(\tilde{t}, r, \theta, \tilde\phi)$ is # $$k = \frac{\partial}{\partial\tilde{t}} - \frac{\partial}{\partial\tilde{r}} $$ # The expression of $k$ in terms of the Boyer-Lindquist coordinates is # In[24]: k = M.vector_field(name='k') k[:] = [(r^2 + a^2)/Delta, -1, 0, a/Delta] k.display() # Regarding the null vector tangent to the outgoing principal null geodesics, we select # one associated with a (non-affine) parameter $\lambda$ that is regular accross the two Killing horizons: # In[25]: el = M.vector_field(name='el', latex_name=r'\ell') el[:] = [1/2, Delta/(2*(r^2+a^2)), 0, a/(2*(r^2+a^2))] el.display() # Let us check that $k$ and $\ell$ are null vectors: # In[26]: g(k,k).expr() # In[27]: g(el,el).expr() # Their scalar product is $-\rho^2/(r^2 + a^2)$: # In[28]: g(k,el).expr() # Note that the scalar product (with respect to metric $g$) can also be computed by means of the method `dot`: # In[29]: k.dot(el).expr() # Let us check that $k$ is a geodesic vector, i.e. that it obeys $\nabla_k k = 0$: # In[30]: acc_k = nabla(k).contract(k) acc_k.display() # We check that $\ell$ is a pregeodesic vector, i.e. that $\nabla_\ell \ell = \kappa_\ell \ell$ for some scalar field $\kappa_\ell$: # In[31]: acc_l = nabla(el).contract(el) acc_l.display() # In[32]: kappa_l = acc_l[[0]] / el[[0]] kappa_l.display() # In[33]: acc_l == kappa_l * el # ## Walker-Penrose Killing tensor # # We need the 1-forms associated to $k$ and $\ell$ by metric duality: # In[34]: uk = k.down(g) ul = el.down(g) # In[35]: uk.display() # In[36]: uk[3] # In[37]: uk[3].factor() # In[38]: uk[3] == a*sin(th)^2 # In[39]: uk[3] = a*sin(th)^2 # In[40]: uk.display() # In[41]: ul.display() # In[42]: ul[3].factor() # In[43]: ul[3] == a*sin(th)^2*(a^2 + r^2 - 2*m*r)/(2*(a^2 + r^2)) # In[44]: ul[3] = a*sin(th)^2*(a^2 + r^2 - 2*m*r)/(2*(a^2 + r^2)) # In[45]: ul.display() # The Walker-Penrose Killing tensor $K$ is then formed as # $$ K = (r^2 + a^2) (\underline{\ell}\otimes \underline{k} + (\underline{k}\otimes \underline{\ell}) + r^2 g $$ # In[46]: K = 2*((r^2 + a^2)*(ul*uk)).symmetrize() + r^2*g K.set_name('K') print(K) # The non-vanishing components of $K$: # In[47]: K.display_comp() # We may simplify a little bit some components: # In[48]: K[0,3].factor() # In[49]: K[0,3] == - a*sin(th)^2*(r^2 + a^2 - 2*m*r*a^2*cos(th)^2/rho2) # In[50]: K[0, 3] = - a*sin(th)^2*(r^2 + a^2 - 2*m*r*a^2*cos(th)^2/rho2) # In[51]: K[1,1].factor() # In[52]: K[3,3] == sin(th)^2 * (r^2*(r^2 + a^2) + a^2*sin(th)^2*(r^2 + a^2 - 2*m*r/rho2*a^2*cos(th)^2)) # In[53]: K[3,3] = sin(th)^2 * (r^2*(r^2 + a^2) + a^2*sin(th)^2*(r^2 + a^2 - 2*m*r/rho2*a^2*cos(th)^2)) # In[54]: K.display_comp() # In[55]: DK = nabla(K) print(DK) # In[56]: DK.display_comp() # Let us check that $K$ is a Killing tensor: # In[57]: DK.symmetrize().display() # Equivalently, we may write, using index notation: # In[58]: DK['_(abc)'].display() # In[59]: pt = var('pt', latex_name=r'p^t') pr = var('pr', latex_name=r'p^r') pth = var('pth', latex_name=r'p^\theta') pph = var('pph', latex_name=r'p^\phi') p = M.vector_field(name='p') p[:] = [pt, pr, pth, pph] p.display() # In[60]: K(p, p).expr() # In[61]: s = K(p, p).expr() s # ### Metric dual of the Killing tensor ($K^{ab}$) # In[62]: uK = K.up(g) uK.set_name('uK', latex_name=r'\hat{K}') print(uK) # In[63]: uK.display_comp() # In[64]: uK[0,0] == a^2/Delta*(r^2 + a^2 - 2*m*r^3*sin(th)^2/rho2) # In[65]: uK[0,0] = a^2/Delta*(r^2 + a^2 - 2*m*r^3*sin(th)^2/rho2) # In[66]: uK[0,3] == a/Delta*(r^2 + a^2 - 2*m*r^3/rho2) # In[67]: uK[0,3] = a/Delta*(r^2 + a^2 - 2*m*r^3/rho2) # In[68]: uK[1,1] == - Delta*a^2*cos(th)^2/rho2 # In[69]: uK[1,1] = - Delta*a^2*cos(th)^2/rho2 # In[70]: uK[3,3] == (a^2 + r^2/sin(th)^2*(1 - 2*m*r/rho2))/Delta # In[71]: uK[3,3] = (a^2 + r^2/sin(th)^2*(1 - 2*m*r/rho2))/Delta # In[72]: uK.display_comp() # ### Killing tensor leading directly to Carter constant Q # We introduce first the Killing vector $V := \eta + a \xi$: # In[73]: V = eta + a*xi V.display() # In[74]: V_form = V.down(g) V_form.display() # and form the Killing tensor # $$\tilde{K} = K - \underline{V}\otimes\underline{V}$$ # In[75]: K2 = K - V_form*V_form K2.set_name('tK', latex_name=r'\tilde{K}') K2.display_comp() # Let us check that $\tilde{K}$ is indeed a Killing tensor: # In[76]: nabla(K2).symmetrize().display() # We check that # $$ \tilde{K}^{\alpha\beta} = - a^2 \cos^2 \theta \, g^{\alpha\beta} # + \mathrm{diag}(-a^2\cos^2\theta, 0, 1, \tan^{-2}\theta)^{\alpha\beta}$$ # In[77]: T = K2 + (a^2*cos(th)^2)*g uT = T.up(g) uT[:] # In[ ]: