# -*- coding: utf-8 -*-
"""
Created on Sun Sep  7 19:25:05 2025

@author: AKourgli
"""

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.animation import FFMpegWriter

# ---------- Paramètres généraux ----------
N = 20
x = np.linspace(-2, 2, N)
y = np.linspace(-2, 2, N)
X, Y = np.meshgrid(x, y)

# Champ radial (Gauss électricité)
def champ_electrique(t):
    R2 = X**2 + Y**2 + 1e-3
    Ex = X / R2 * (1 + 0.2*np.sin(t))
    Ey = Y / R2 * (1 + 0.2*np.sin(t))
    return Ex, Ey

# Champ dipôle magnétique (Gauss B)
def champ_magnetique(t):
    R2 = X**2 + Y**2 + 1e-3
    Bx = -Y / R2 * (1 + 0.2*np.cos(t))
    By = X / R2 * (1 + 0.2*np.cos(t))
    return Bx, By

# Champ de Faraday (E induit par variation de B)
def champ_faraday(t):
    Bz = np.sin(t)  # B variable
    R2 = X**2 + Y**2 + 1e-3
    Ex = -Y / R2 * Bz
    Ey = X / R2 * Bz
    return Ex, Ey, Bz

# Champ d’Ampère–Maxwell (B induit par dE/dt)
def champ_ampere(t):
    Ez = np.sin(t)
    dEz_dt = np.cos(t)
    Bx = -Y * dEz_dt
    By = X * dEz_dt
    return Bx, By, Ez

# ---------- Animation ----------
fig, axs = plt.subplots(2, 2, figsize=(12, 12))

# Couleurs
color_E = 'r'
color_B = 'b'

# --- Gauss E ---
quiv_E = axs[0,0].quiver(X, Y, *champ_electrique(0), color=color_E)
axs[0,0].set_title("Gauss (Électricité)")
axs[0,0].text(-2, -2.3, "∇·E = ρ/ε0 : lignes sortent d’une charge.", fontsize=9)
axs[0,0].annotate("Charge ponctuelle", xy=(0,0), xytext=(0.5,0.5),
                  arrowprops=dict(arrowstyle="->"))

# --- Gauss B ---
quiv_B = axs[0,1].quiver(X, Y, *champ_magnetique(0), color=color_B)
axs[0,1].set_title("Gauss (Magnétisme)")
axs[0,1].text(-2, -2.3, "∇·B = 0 : lignes de B toujours fermées.", fontsize=9)
axs[0,1].annotate("Pas de monopôle", xy=(0,0), xytext=(-1,1),
                  arrowprops=dict(arrowstyle="->"))

# --- Faraday ---
quiv_F = axs[1,0].quiver(X, Y, *champ_faraday(0)[:2], color=color_E)
axs[1,0].set_title("Faraday")
axs[1,0].text(-2, -2.3, "∇×E = -∂B/∂t : B variable → E tourbillonnaire.", fontsize=9)
text_Bz = axs[1,0].text(-1.8,1.7,"Bz=0", fontsize=10, color='k')

# Flèche centrale pour Bz
arrow_B = axs[1,0].arrow(0, 0, 0, 1, color=color_B, width=0.05)

# Cercle représentant le flux
circle = plt.Circle((0,0), 0.8, fill=False, color='b', linestyle='--')
axs[1,0].add_patch(circle)
axs[1,0].annotate("Flux Bz variable", xy=(0.8,0), xytext=(1.2,0.8),
                  arrowprops=dict(arrowstyle="->"))

# --- Ampère-Maxwell ---
quiv_A = axs[1,1].quiver(X, Y, *champ_ampere(0)[:2], color=color_B)
axs[1,1].set_title("Ampère-Maxwell")
axs[1,1].text(-2, -2.3, "∇×B = μ0(J+ε0∂E/∂t) : E variable → B circulaire.", fontsize=9)
text_Ez = axs[1,1].text(-1.5,1.5,"Ez=0", fontsize=10, color='k')

# Légende globale
fig.legend(["Champ électrique E (rouge)", "Champ magnétique B (bleu)"],
           loc="lower center", fontsize=11)

for ax in axs.flat:
    ax.set_xlim(-2,2)
    ax.set_ylim(-2,2)
    ax.set_xticks([])
    ax.set_yticks([])

# ---------- Update ----------
def update(frame):
    global arrow_B
    t = frame/10

    # Gauss E
    Ex, Ey = champ_electrique(t)
    quiv_E.set_UVC(Ex, Ey)

    # Gauss B
    Bx, By = champ_magnetique(t)
    quiv_B.set_UVC(Bx, By)

    # Faraday
    Ex, Ey, Bz = champ_faraday(t)
    quiv_F.set_UVC(Ex, Ey)
    text_Bz.set_text(f"Bz={Bz:.2f}")
    circle.set_radius(0.8 + 0.2*Bz)

    # Met à jour la flèche B centrale
    arrow_B.remove()
    if Bz >= 0:
        arrow_B = axs[1,0].arrow(0, 0, 0, 1, color=color_B, width=0.05)
    else:
        arrow_B = axs[1,0].arrow(0, 0, 0, -1, color=color_B, width=0.05)

    # Ampère–Maxwell
    Bx, By, Ez = champ_ampere(t)
    quiv_A.set_UVC(Bx, By)
    text_Ez.set_text(f"Ez={Ez:.2f}")

ani = animation.FuncAnimation(fig, update, frames=200, interval=50)

# ---------- Sauvegarde ----------
try:
    writer = FFMpegWriter(fps=20, metadata=dict(artist='ChatGPT'), bitrate=1800)
    ani.save("maxwell_equations.mp4", writer=writer)
    print("✅ Animation sauvegardée en MP4 (maxwell_equations.mp4)")
except Exception as e:
    print("⚠️ ffmpeg introuvable, export en GIF…")
    ani.save("maxwell_equations.gif", writer="pillow", fps=20)
    print("✅ Animation sauvegardée en GIF (maxwell_equations.gif)")

plt.tight_layout(rect=[0,0.05,1,1])
plt.show()
