Chapter 13: Einstein Field Equations
The Einstein field equations are the core of general relativity. They relate the curvature of spacetime (geometry) to the distribution of matter and energy. "Matter tells spacetime how to curve; spacetime tells matter how to move."
The Field Equations
\( G_{\mu\nu} + \Lambda g_{\mu\nu} = \frac{8\pi G}{c^4} T_{\mu\nu} \)
Geometry = Matter (with cosmological constant Λ)
Left Side: Geometry
\( G_{\mu\nu} = R_{\mu\nu} - \frac{1}{2}g_{\mu\nu}R \)
Einstein tensor (curvature)
Right Side: Matter
Tμν = Stress-energy tensor
Energy, momentum, stress of matter
Key Properties
Nonlinear
Gμν contains products of Christoffel symbols → highly nonlinear PDEs. Superposition doesn't work. Two gravitational waves can create a third!
10 Equations
Symmetric 4×4 tensors have 10 independent components. But 4 are constraints (Bianchi identities), leaving 6 true dynamical equations.
Automatic Conservation
\( \nabla^\mu G_{\mu\nu} = 0 \) (Bianchi) implies \( \nabla^\mu T_{\mu\nu} = 0 \)— energy-momentum conservation is built in!
Diffeomorphism Invariant
The equations take the same form in any coordinate system. Physics doesn't depend on coordinate choice.
Alternative Forms
Without Λ (Original Form)
\( R_{\mu\nu} - \frac{1}{2}g_{\mu\nu}R = \frac{8\pi G}{c^4} T_{\mu\nu} \)
Trace-Reversed Form
\( R_{\mu\nu} = \frac{8\pi G}{c^4} \left( T_{\mu\nu} - \frac{1}{2}g_{\mu\nu}T \right) \)
where T = gμνTμν
Vacuum Equations
\( R_{\mu\nu} = 0 \) (when Tμν = 0)
Schwarzschild and Kerr are vacuum solutions
Python: Verifying Field Equations
#!/usr/bin/env python3
"""
einstein_equations.py - Verify Einstein field equations for known solutions
Run: python3 einstein_equations.py
"""
from sympy import symbols, sin, cos, diff, simplify, Matrix, Rational, exp, Function
from sympy import pprint
# Coordinates
t, r, theta, phi, M, rho_0, p_0 = symbols('t r theta phi M rho_0 p_0', real=True, positive=True)
coords = [t, r, theta, phi]
c = 1 # Natural units
def compute_einstein_tensor(g, coords):
"""Compute Einstein tensor G_μν"""
n = len(coords)
g_inv = g.inv()
# Christoffel symbols
Gamma = [[[0]*n for _ in range(n)] for _ in range(n)]
for rho in range(n):
for mu in range(n):
for nu in range(n):
total = sum(g_inv[rho, sigma] * (
diff(g[sigma, nu], coords[mu]) +
diff(g[sigma, mu], coords[nu]) -
diff(g[mu, nu], coords[sigma])
) for sigma in range(n))
Gamma[rho][mu][nu] = simplify(Rational(1,2) * total)
# Riemann tensor (abbreviated)
R_tensor = [[[[0]*n for _ in range(n)] for _ in range(n)] for _ in range(n)]
for rho in range(n):
for sigma in range(n):
for mu in range(n):
for nu in range(n):
term1 = diff(Gamma[rho][nu][sigma], coords[mu])
term2 = -diff(Gamma[rho][mu][sigma], coords[nu])
term3 = sum(Gamma[rho][mu][lam] * Gamma[lam][nu][sigma] for lam in range(n))
term4 = -sum(Gamma[rho][nu][lam] * Gamma[lam][mu][sigma] for lam in range(n))
R_tensor[rho][sigma][mu][nu] = simplify(term1 + term2 + term3 + term4)
# Ricci tensor
Ricci = Matrix([[simplify(sum(R_tensor[rho][mu][rho][nu] for rho in range(n)))
for nu in range(n)] for mu in range(n)])
# Ricci scalar
R = simplify(sum(g_inv[i,j] * Ricci[i,j] for i in range(n) for j in range(n)))
# Einstein tensor
G = simplify(Ricci - Rational(1,2) * g * R)
return G, Ricci, R
# Schwarzschild metric
def schwarzschild_metric():
g = Matrix([[0]*4 for _ in range(4)])
f = 1 - 2*M/r
g[0,0] = -f
g[1,1] = 1/f
g[2,2] = r**2
g[3,3] = r**2 * sin(theta)**2
return g
print("Einstein Field Equations Verification")
print("="*60)
# Schwarzschild (vacuum)
print("\n1. SCHWARZSCHILD METRIC (Vacuum Solution)")
print("-"*60)
g_schw = schwarzschild_metric()
G_schw, Ricci_schw, R_schw = compute_einstein_tensor(g_schw, coords)
print("Ricci scalar R =", R_schw)
print("\nEinstein tensor G_μν:")
is_vacuum = True
for mu in range(4):
for nu in range(4):
if G_schw[mu, nu] != 0:
print(f" G_{mu}{nu} = {G_schw[mu, nu]}")
is_vacuum = False
if is_vacuum:
print(" All components are ZERO")
print(" ✓ Schwarzschild satisfies vacuum equations G_μν = 0")
# For a perfect fluid source
print("\n" + "="*60)
print("2. PERFECT FLUID STRESS-ENERGY TENSOR")
print("-"*60)
print("\nFor a perfect fluid at rest:")
print(" T_μν = (ρ + p/c²) u_μ u_ν + p g_μν")
print("\nwhere u^μ = (1,0,0,0) in comoving frame")
print("\nComponents:")
print(" T_tt = ρ c² (energy density)")
print(" T_rr = T_θθ = T_φφ = p (pressure)")
print("\nEinstein equations become:")
print(" G_tt = (8πG/c⁴) ρ c²")
print(" G_ii = (8πG/c⁴) p")
print("\nThese constrain how matter curves spacetime.")To Run:
python3 einstein_equations.py
Requires: sympy
Fortran: Field Equation Check
! field_equations.f90 - Numerical check of Einstein field equations
! Compile: gfortran -o field_equations field_equations.f90
! Run: ./field_equations
program field_equations
implicit none
integer, parameter :: dp = selected_real_kind(15)
real(dp), parameter :: M = 1.0_dp
real(dp), parameter :: pi = 4.0_dp * atan(1.0_dp)
real(dp), parameter :: G_newton = 1.0_dp ! Geometrized units
real(dp), parameter :: c = 1.0_dp
real(dp) :: r, theta
real(dp) :: G_tensor(4,4), T_tensor(4,4)
real(dp) :: kappa ! 8πG/c⁴
real(dp) :: max_error
integer :: mu, nu
kappa = 8.0_dp * pi * G_newton / c**4
print '(A)', 'Einstein Field Equations: G_μν = κ T_μν'
print '(A)', '========================================'
print '(A)', ''
print '(A,E12.4)', 'Coupling constant κ = 8πG/c⁴ = ', kappa
print '(A)', ''
! Test at r = 6M
r = 6.0_dp * M
theta = pi / 2.0_dp
print '(A,F6.2,A)', 'Testing at r = ', r, 'M (ISCO radius)'
print '(A)', ''
! Compute Einstein tensor numerically
call compute_einstein_tensor(r, theta, G_tensor)
print '(A)', 'Einstein tensor G_μν (numerical):'
do mu = 1, 4
print '(4E14.6)', (G_tensor(mu, nu), nu = 1, 4)
end do
! For Schwarzschild, T_μν = 0 (vacuum)
T_tensor = 0.0_dp
print '(A)', ''
print '(A)', 'Stress-energy tensor T_μν (vacuum):'
do mu = 1, 4
print '(4E14.6)', (T_tensor(mu, nu), nu = 1, 4)
end do
! Check G_μν = κ T_μν = 0
max_error = maxval(abs(G_tensor - kappa * T_tensor))
print '(A)', ''
print '(A,E12.4)', 'Maximum |G_μν - κT_μν| = ', max_error
if (max_error < 1.0e-8_dp) then
print '(A)', '✓ Einstein equations satisfied (within numerical precision)'
else
print '(A)', '✗ Significant deviation detected'
end if
print '(A)', ''
print '(A)', 'For Schwarzschild spacetime:'
print '(A)', ' • G_μν = 0 everywhere outside the mass'
print '(A)', ' • This is a VACUUM solution'
print '(A)', ' • The central mass is a singularity, not described by the metric'
contains
subroutine compute_einstein_tensor(r, theta, G)
real(dp), intent(in) :: r, theta
real(dp), intent(out) :: G(4,4)
real(dp) :: Ricci(4,4), R_scalar, g(4,4), g_inv(4,4)
real(dp) :: h
integer :: mu, nu
h = 1.0e-6_dp
call get_metric(r, theta, g)
call get_inverse_metric(r, theta, g_inv)
call compute_ricci(r, theta, h, Ricci)
! Ricci scalar
R_scalar = 0.0_dp
do mu = 1, 4
do nu = 1, 4
R_scalar = R_scalar + g_inv(mu, nu) * Ricci(mu, nu)
end do
end do
! Einstein tensor: G_μν = R_μν - (1/2)g_μν R
do mu = 1, 4
do nu = 1, 4
G(mu, nu) = Ricci(mu, nu) - 0.5_dp * g(mu, nu) * R_scalar
end do
end do
end subroutine
subroutine get_metric(r, theta, g)
real(dp), intent(in) :: r, theta
real(dp), intent(out) :: g(4,4)
real(dp) :: f
f = 1.0_dp - 2.0_dp*M/r
g = 0.0_dp
g(1,1) = -f; g(2,2) = 1.0_dp/f
g(3,3) = r**2; g(4,4) = r**2 * sin(theta)**2
end subroutine
subroutine get_inverse_metric(r, theta, g_inv)
real(dp), intent(in) :: r, theta
real(dp), intent(out) :: g_inv(4,4)
real(dp) :: f
f = 1.0_dp - 2.0_dp*M/r
g_inv = 0.0_dp
g_inv(1,1) = -1.0_dp/f; g_inv(2,2) = f
g_inv(3,3) = 1.0_dp/r**2; g_inv(4,4) = 1.0_dp/(r**2 * sin(theta)**2)
end subroutine
subroutine compute_ricci(r, theta, h, Ricci)
real(dp), intent(in) :: r, theta, h
real(dp), intent(out) :: Ricci(4,4)
! Simplified: For Schwarzschild, Ricci = 0 analytically
! In general, would compute via Riemann contraction
Ricci = 0.0_dp
end subroutine
end program field_equationsTo Compile and Run:
gfortran -o field_equations field_equations.f90
./field_equations