Chapter 12: The Equivalence Principle
The equivalence principle is the cornerstone of general relativity. It states that gravitational and inertial mass are equivalent, and that locally, gravity is indistinguishable from acceleration. This insight led Einstein to describe gravity as spacetime curvature.
Three Forms
Weak Equivalence Principle (WEP)
All test particles fall with the same acceleration in a gravitational field, regardless of their composition.
\( m_{inertial} = m_{gravitational} \) (tested to 10-15 precision)
Einstein Equivalence Principle (EEP)
In a freely falling local reference frame, the laws of physics are those of special relativity.
Includes WEP + local Lorentz invariance + local position invariance
Strong Equivalence Principle (SEP)
EEP applies to all physics, including gravitational experiments. Self-gravitating bodies fall like test particles.
Only satisfied by general relativity (not scalar-tensor theories)
Einstein's Thought Experiments
The Elevator
An observer in a closed elevator cannot distinguish between:
• Resting on Earth's surface in gravity g
• Accelerating upward at g in empty space
Free Fall
An observer in free fall cannot distinguish between:
• Falling in a gravitational field
• Floating in empty space far from masses
Key Implication
Gravity can be "transformed away" locally by choosing a freely falling frame. This means gravity is not a force but a property of spacetime geometry!
Mathematical Formulation
At any point in spacetime, we can choose coordinates where the metric is locally Minkowski:
\( g_{\mu\nu}(P) = \eta_{\mu\nu}, \quad \Gamma^\rho_{\mu\nu}(P) = 0 \)
Local inertial frame (Riemann normal coordinates)
However, second derivatives (curvature) cannot be transformed away:\( R^\rho_{\;\sigma\mu\nu}(P) \neq 0 \) in general. This is the tidal effect that distinguishes true gravity from mere acceleration.
Python: Free Fall Simulation
#!/usr/bin/env python3
"""
equivalence_principle.py - Demonstrate equivalence of gravity and acceleration
Run: python3 equivalence_principle.py
"""
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, Circle
def simulate_elevator(g, a_elevator, t_max=3.0, dt=0.01):
"""
Simulate a ball dropped in an elevator
g: gravitational acceleration (downward positive)
a_elevator: elevator acceleration (upward positive)
In the elevator frame, effective gravity is g_eff = g - a_elevator
"""
t = np.arange(0, t_max, dt)
# Ball starts at rest in elevator frame
g_eff = g - a_elevator
# Position in elevator frame
y_ball = -0.5 * g_eff * t**2
# Position of elevator floor in ground frame
y_elevator = 0.5 * a_elevator * t**2
# Ball position in ground frame
y_ball_ground = y_elevator + 2.0 + y_ball # Start 2m above floor
return t, y_ball, y_elevator, y_ball_ground
# Three scenarios
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# Scenario 1: Stationary elevator in gravity
t1, y_ball1, _, _ = simulate_elevator(g=9.8, a_elevator=0)
axes[0].plot(t1, y_ball1, 'b-', linewidth=2)
axes[0].axhline(y=-2, color='brown', linewidth=3, label='Floor')
axes[0].set_xlabel('Time (s)')
axes[0].set_ylabel('Height above floor (m)')
axes[0].set_title('Stationary in Gravity (g=9.8 m/s²)')
axes[0].set_ylim(-2.5, 0.5)
axes[0].grid(True, alpha=0.3)
axes[0].legend()
# Scenario 2: Accelerating elevator in empty space
t2, y_ball2, _, _ = simulate_elevator(g=0, a_elevator=-9.8)
axes[1].plot(t2, y_ball2, 'r-', linewidth=2)
axes[1].axhline(y=-2, color='brown', linewidth=3, label='Floor')
axes[1].set_xlabel('Time (s)')
axes[1].set_ylabel('Height above floor (m)')
axes[1].set_title('Accelerating Upward (a=9.8 m/s², no gravity)')
axes[1].set_ylim(-2.5, 0.5)
axes[1].grid(True, alpha=0.3)
axes[1].legend()
# Scenario 3: Free falling elevator in gravity
t3, y_ball3, _, _ = simulate_elevator(g=9.8, a_elevator=9.8)
axes[2].plot(t3, y_ball3, 'g-', linewidth=2)
axes[2].axhline(y=-2, color='brown', linewidth=3, label='Floor')
axes[2].set_xlabel('Time (s)')
axes[2].set_ylabel('Height above floor (m)')
axes[2].set_title('Free Falling (a=g=9.8 m/s²)')
axes[2].set_ylim(-2.5, 0.5)
axes[2].grid(True, alpha=0.3)
axes[2].legend()
plt.tight_layout()
plt.savefig('equivalence_principle.png', dpi=150)
plt.show()
print("Equivalence Principle Demonstration")
print("="*60)
print("\nScenario 1: Ball dropped in stationary elevator on Earth")
print(" → Ball falls with g = 9.8 m/s²")
print("\nScenario 2: Ball 'dropped' in elevator accelerating upward at 9.8 m/s²")
print(" → Ball appears to fall with same acceleration!")
print(" → Observer cannot distinguish from Scenario 1")
print("\nScenario 3: Ball in free-falling elevator")
print(" → Ball floats (g_eff = g - a = 0)")
print(" → Observer feels weightless, like in empty space")
print("\nThis is the Equivalence Principle:")
print(" Gravity ↔ Acceleration (locally indistinguishable)")
print("\nPlot saved as 'equivalence_principle.png'")To Run:
python3 equivalence_principle.py
Requires: numpy, matplotlib
Fortran: Tidal Forces
! tidal_forces.f90 - Compute tidal forces that distinguish gravity from acceleration
! Compile: gfortran -o tidal_forces tidal_forces.f90
! Run: ./tidal_forces
program tidal_forces
implicit none
integer, parameter :: dp = selected_real_kind(15)
real(dp), parameter :: G = 6.674e-11_dp ! N m²/kg²
real(dp), parameter :: M_earth = 5.972e24_dp ! kg
real(dp), parameter :: R_earth = 6.371e6_dp ! m
real(dp), parameter :: M_sun = 1.989e30_dp
real(dp), parameter :: AU = 1.496e11_dp
real(dp) :: r, delta_r, a_near, a_far, tidal_acc
real(dp) :: R_schwarzschild, r_orbit
print '(A)', 'Tidal Forces: What Distinguishes Gravity from Acceleration'
print '(A)', '=========================================================='
print '(A)', ''
print '(A)', 'In a uniform gravitational field or constant acceleration,'
print '(A)', 'there are NO tidal forces. Real gravity has tidal forces'
print '(A)', 'because g varies with position.'
print '(A)', ''
! Earth surface tidal force
r = R_earth
delta_r = 2.0_dp ! 2 meter person
a_near = G * M_earth / r**2
a_far = G * M_earth / (r + delta_r)**2
tidal_acc = a_near - a_far
print '(A)', 'Tidal Forces on Earth Surface (2m tall person):'
print '(A,E12.4,A)', ' g at feet: ', a_near, ' m/s²'
print '(A,E12.4,A)', ' g at head: ', a_far, ' m/s²'
print '(A,E12.4,A)', ' Tidal stretch: ', tidal_acc, ' m/s²'
print '(A)', ' (Barely noticeable - ~3 micro-g over 2m)'
print '(A)', ''
! Sun tidal force on Earth
r = AU
delta_r = 2.0_dp * R_earth ! Earth diameter
a_near = G * M_sun / r**2
a_far = G * M_sun / (r + delta_r)**2
tidal_acc = a_near - a_far
print '(A)', 'Sun''s Tidal Force on Earth (across Earth diameter):'
print '(A,E12.4,A)', ' Tidal acceleration: ', tidal_acc, ' m/s²'
print '(A)', ' (This causes ocean tides!)'
print '(A)', ''
! Black hole tidal forces
print '(A)', 'Tidal Forces Near Black Holes:'
print '(A)', ''
! Stellar mass BH
R_schwarzschild = 2.0_dp * G * (10.0_dp * M_sun) / (3.0e8_dp)**2
r_orbit = 3.0_dp * R_schwarzschild ! Photon sphere
delta_r = 2.0_dp ! 2m person
a_near = G * (10.0_dp * M_sun) / r_orbit**2
a_far = G * (10.0_dp * M_sun) / (r_orbit + delta_r)**2
tidal_acc = a_near - a_far
print '(A)', '10 Solar Mass Black Hole at r = 3Rs (photon sphere):'
print '(A,E12.4,A)', ' Schwarzschild radius: ', R_schwarzschild, ' m'
print '(A,E12.4,A)', ' Tidal acceleration: ', tidal_acc, ' m/s²'
print '(A)', ' → Spaghettification! Person torn apart.'
print '(A)', ''
! Supermassive BH
R_schwarzschild = 2.0_dp * G * (4.0e6_dp * M_sun) / (3.0e8_dp)**2
r_orbit = R_schwarzschild ! At horizon
delta_r = 2.0_dp
a_near = G * (4.0e6_dp * M_sun) / r_orbit**2
a_far = G * (4.0e6_dp * M_sun) / (r_orbit + delta_r)**2
tidal_acc = a_near - a_far
print '(A)', 'Sgr A* (4 million solar masses) at horizon:'
print '(A,E12.4,A)', ' Schwarzschild radius: ', R_schwarzschild, ' m'
print '(A,E12.4,A)', ' Tidal acceleration: ', tidal_acc, ' m/s²'
print '(A)', ' → Survivable! Could cross horizon intact.'
print '(A)', ''
print '(A)', 'Key Point: Tidal forces (curvature) are the TRUE measure'
print '(A)', 'of gravity. They cannot be transformed away by changing'
print '(A)', 'to a freely falling frame.'
end program tidal_forcesTo Compile and Run:
gfortran -o tidal_forces tidal_forces.f90
./tidal_forces