Code Python pour cette dernière vidéo :
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
import os
x0 = 0.2
def beta_function(t):
return np.array([0.,-x0*c*np.sin(np.pi*t),0])
def beta_dot_function(t):
return np.array([0,-x0*c*np.pi*np.cos(np.pi*t),0])
c = 1
def r_0(t):
return np.array([float(0.),float(x0*c/np.pi*np.cos(np.pi*t)),0])
def determinetprime(r,r_0,t):
"""
r_0(t_prime) est la fonction donnant la position au cours du temps
r est le point où on cherche la valeur du champ
"""
def func(t_prime):
return t - t_prime - np.linalg.norm(r - r_0(t_prime)) / c
t_prime_initial_guess = t - 1
t_prime_solution = fsolve(func, t_prime_initial_guess)
return t_prime_solution[0]
def champ_vectorized(x_grid, y_grid, r_0_func, beta_function, beta_dot_function, t):
q = 1
E_field = np.zeros(x_grid.shape + (3,)) # Initialisation d'un tableau 3D pour le champ électrique
for i in range(x_grid.shape[0]):
for j in range(x_grid.shape[1]):
r = np.array([x_grid[i, j], y_grid[i, j], 0])
tprime = determinetprime(r, r_0_func, t)
beta = beta_function(tprime)
beta_dot = beta_dot_function(tprime)
r0 = r_0_func(tprime)
R = r - r0
R_norm = np.linalg.norm(R)
R_hat = R / R_norm
gamma = 1 / np.sqrt(1 - np.dot(beta, beta))
term1_numerator = R_hat - beta
term1_denominator = gamma**2 * R_norm**2 * (1 - np.dot(R_hat, beta))**3
term1 = term1_numerator / term1_denominator
term2_numerator = np.cross(R_hat, np.cross(R_hat - beta, beta_dot))
term2_denominator = c * R_norm * (1 - np.dot(R_hat, beta))**3
term2 = term2_numerator / term2_denominator
E = q * (term1 + term2)
E_field[i, j, :] = E
return E_field
def calculate_field_line_point(r0, beta, n_hat, t, t_prime):
gamma = 1 / np.sqrt(1 - np.dot(beta, beta)) # Facteur de Lorentz
if np.linalg.norm(beta) != 0:
beta_hat = beta/np.linalg.norm(beta)
else:
beta_hat = np.array([0.0,0.0,0.0])
term_inside_brackets = beta + ((1/gamma - 1) * np.dot(n_hat, beta_hat) * beta_hat + n_hat) / (gamma * (1 + np.dot(n_hat, beta)))
return r0 + c * (t - t_prime) * term_inside_brackets
# Fonction pour tracer les lignes de champ à partir d'une position donnée à l'instant t
def plot_field_lines(r0_func, beta_func, t, num_lines=24, num_points=500, step=0.05):
for i in range(num_lines):
n_hat = np.array([np.cos(i/num_lines*2*np.pi),np.sin(i/num_lines*2*np.pi),0])
line_points = []
t_prime = t # Initialisation de t' à la valeur de t pour le début de la ligne de champ
for _ in range(num_points):
r0 = r0_func(t_prime)
beta = beta_func(t_prime)
point = calculate_field_line_point(r0, beta, n_hat, t, t_prime)
line_points.append(point)
t_prime -= step # Décrémentation de t' pour suivre la ligne de champ vers le passé
line_points = np.array(line_points)
plt.plot(line_points[:, 0], line_points[:, 1], 'r-') # Trace la ligne en rouge
# Set up grid for field calculation
x_range = np.linspace(-12, 12, 1200)
y_range = np.linspace(-6, 6, 600)
x_grid, y_grid = np.meshgrid(x_range, y_range)
# Créer le répertoire pour les images si nécessaire
output_dir = "animation"
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Définir la plage de temps et le nombre d'images
time_values = np.linspace(0, 2, num=51) # 401 images pour t de 0 à 4
for i, t in enumerate(time_values):
plt.figure(figsize=(15, 10), dpi=150)
plot_field_lines(r_0, beta_function, t)
E_field_grid = champ_vectorized(x_grid, y_grid, r_0, beta_function, beta_dot_function, t)
E_field_magnitude = np.linalg.norm(E_field_grid, axis=2)
plt.imshow(np.log10(E_field_magnitude), extent=(x_range.min(), x_range.max(), y_range.min(), y_range.max()), cmap='Spectral_r', aspect='equal')
plt.axis('off')
# Construire le nom de fichier avec un remplissage de zéros
filename = f"image{str(i).zfill(4)}.png"
filepath = os.path.join(output_dir, filename)
# Sauvegarder l'image
plt.savefig(filepath, bbox_inches='tight', pad_inches=0, transparent=True)
# Fermer la figure pour libérer de la mémoire
plt.close()
Ce code a été obtenu avec l'aide de ChatGPT à partir de cet article et de cette page de forum.