Voici le code Python complet fourni pour reproduire cette animation sous forme de fenêtre interactive ou de fichier GIF animé à l'aide des bibliothèques numpy et matplotlib.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# --- Paramètres physiques (unités géométriques simplifiées, G=c=1) ---
M = 1.0 # masse du trou noir
rs = 2 * M # rayon de Schwarzschild (horizon des événements)
r_rings = [2.2, 3.0, 4.5, 7.0, 12.0] # rayons des anneaux (doivent être > rs)
labels = [f"r = {r:.1f} rs" for r in r_rings] # étiquettes
# Facteur de dilatation temporelle pour un observateur statique
def time_dilation_factor(r):
return np.sqrt(1 - rs / r)
# Couleurs pour les anneaux
colors = plt.cm.plasma(np.linspace(0.2, 0.9, len(r_rings)))
# --- Configuration de la figure ---
fig, ax = plt.subplots(figsize=(8, 8))
ax.set_aspect('equal')
ax.set_xlim(-13, 13)
ax.set_ylim(-13, 13)
ax.axis('off')
# Dessiner l'horizon des événements (le "trou noir")
horizon = plt.Circle((0, 0), rs, color='black', zorder=1)
ax.add_patch(horizon)
ax.text(0, 0, "Horizon\ndes événements", color='white', ha='center', va='center', fontsize=8, zorder=2)
# Dessiner les anneaux
for r, c in zip(r_rings, colors):
circle = plt.Circle((0, 0), r, color=c, fill=False, linewidth=1, alpha=0.4, zorder=1)
ax.add_patch(circle)
# Ajouter l'étiquette du rayon
ax.text(r * 1.02, 0.3, f"r={r}", color=c, fontsize=8, zorder=3)
# Créer un "marqueur d'horloge" (un point) sur chaque anneau
clock_dots = []
for r, c in zip(r_rings, colors):
dot, = ax.plot([], [], 'o', color=c, markersize=10, zorder=4)
clock_dots.append(dot)
# Ajouter une horloge de référence lointaine (à un rayon très grand)
r_far = 20
ax.text(r_far, 0.5, "Observateur\nlointain (t)", color='gray', fontsize=9, ha='left')
far_dot, = ax.plot([], [], 's', color='gray', markersize=8, zorder=4)
# Texte affichant le facteur de dilatation
text_factor = ax.text(0, -14, "", ha='center', fontsize=9, color='gray')
# --- Animation ---
# La vitesse angulaire de base représente le temps coordonné t
omega_base = 1.0 # radians par unité de temps
def init():
for dot in clock_dots:
dot.set_data([], [])
far_dot.set_data([], [])
text_factor.set_text("")
return clock_dots + [far_dot, text_factor]
def animate(frame):
# Le temps coordonné t avance uniformément
t = frame * 0.05
# Position de l'observateur lointain (tourne à vitesse "normale")
x_far = r_far * np.cos(omega_base * t)
y_far = r_far * np.sin(omega_base * t)
far_dot.set_data([x_far], [y_far])
# Position de chaque horloge sur son anneau, avec vitesse réduite
for i, (r, dot) in enumerate(zip(r_rings, clock_dots)):
# Facteur de dilatation : plus r est petit, plus la vitesse angulaire est faible
factor = time_dilation_factor(r)
omega_local = omega_base * factor
# L'angle dépend du temps coordonné t, mais la vitesse locale est ralentie
angle = omega_local * t + i * 0.5 # décalage initial pour éviter la superposition
x = r * np.cos(angle)
y = r * np.sin(angle)
dot.set_data([x], [y])
# Mettre à jour le texte du facteur (montrer le facteur pour le rayon le plus proche)
factor_closest = time_dilation_factor(r_rings[0])
text_factor.set_text(f"Facteur de dilatation le plus proche : sqrt(1 - rs/r) = {factor_closest:.3f}\n"
f"(le temps propre s'écoule plus lentement près du trou noir)")
return clock_dots + [far_dot, text_factor]
ani = animation.FuncAnimation(fig, animate, init_func=init,
frames=200, interval=50, blit=False)
plt.show()
# ani.save('time_dilation_black_hole.gif', writer='pillow', fps=20)