KAM - Kolgomorov-Arnold-Moser Theorem¶
da PowerShell -- jupyter nbconvert --to html notebook.ipynb
Consideriamo un sistema hamiltoniano integrabile¶
$$\large H_0(I), \quad I \in \mathbb{R}^n, $$con coordinate d'azione-angle $(I, \theta)$. Le traiettorie del sistema si muovono su tori invarianti con frequenze $$\large \omega(I) = \nabla H_0(I). $$ Se il sistema integrabile viene perturbato leggermente $$\large H(I, \theta) = H_0(I) + \epsilon H_1(I, \theta), \quad 0<\epsilon \ll 1, $$ il teorema KAM afferma che, sotto una condizione di non risonanza sulle frequenze $\omega(I)$ e alcune ipotesi di regolarità, una gran parte dei tori invarianti del sistema integrabile originale sopravvive, sebbene deformata dalla perturbazione. Questi tori sono detti $\textbf{tori KAM}$.
La condizione di non risonanza si scrive spesso come:¶
$$\large |\langle k, \omega(I) \rangle| \ge \frac{C}{|k|^\tau}, \quad \forall k \in \mathbb{Z}^n \setminus \{0\}, $$dove:
- $k = (k_1, \dots, k_n)$ è un vettore di numeri interi;
- $\omega(I) = (\omega_1(I), \dots, \omega_n(I))$ è il vettore delle frequenze del sistema integrabile;
- $\langle k, \omega(I) \rangle = k_1 \omega_1(I) + \dots + k_n \omega_n(I)$ è il \emph{prodotto scalare} tra $k$ e $\omega(I)$;
- $C>0$ e $\tau>n-1$ sono costanti che dipendono dal sistema.
$\textbf{Significato del primo membro:}$ $$\large |\langle k, \omega(I) \rangle| $$ rappresenta la distanza (in valore assoluto) della combinazione lineare delle frequenze pesata dagli interi $k$ dallo zero.
In altre parole, misura quanto la combinazione lineare $$\large k_1 \omega_1 + \dots + k_n \omega_n $$ si avvicina a una risonanza $(=0)$.
- Se fosse esattamente zero ($\langle k, \omega(I) \rangle = 0$) per qualche $k \neq 0$, le frequenze sarebbero \emph{risonanti}, e il moto sul toro potrebbe chiudersi su se stesso dopo un certo numero di cicli. In questo caso, anche piccole perturbazioni possono distruggere il toro.
- La condizione di non risonanza assicura che nessuna combinazione lineare intera non banale delle frequenze sia troppo vicina a zero, come quantificato dal lato destro $\frac{C}{|k|^\tau}$.
In pratica, il primo membro misura quanto le frequenze \emph{evitano le risonanze}, condizione fondamentale per la persistenza dei tori invarianti sotto piccole perturbazioni.
Esercizio del libro¶
Confronta le vecchie Azioni - poco significativo¶
import numpy as np
def hamiltonian(I, theta, H0, H1, epsilon):
'''
Calculate the perturbed Hamiltonian.
:param I: Action variables.
:param theta: Angle variables.
:param HO: Unperturbed Hamiltonian function.
:param Hl: Perturbation Hamiltonian function.
:param epsilon: Small perturbation parameter.
:return:
Total Hamiltonian.
'''
return H0(I, theta) + epsilon * H1(I, theta)
def validate_non_resonance(omega, tau, C):
'''
Validate the non-resonance condition for frequencies.
:param omega: Frequency vector.
:param tau: Resonance condition parameter.
:param C: Positive constant for non-resonance.
:return:
True if non-resonance condition is met, False otherwise.
'''
omega1 = np.array(omega)
for k in np.ndindex(omega1.shape):
if np.linalg.norm(k) != 0: # Ensure k is not the zero vector
if abs(sum(k * omega1)) < C / (np.linalg.norm(k) ** tau):
return False
return True
def iterative_kam_validation(I_init, H0, epsilon, tau, C, iterations=3000):
'''
Iteratively validate invariant tori with KAM conditions.
:param I_init: Initial action variables.
:param HO: Unperturbed Hamiltonian function.
:param epsilon: Small perturbation parameter.
:param tau: Resonance condition parameter.
:param C: Positive constant for non-resonance.
:param iterations: Number of iterations for validation.
:return:
Final state of action variables and validation status.
'''
I = I_init
for _ in range(iterations):
omega = np.gradient(H0(I))
if not validate_non_resonance(omega, tau, C):
return I, False
I += -epsilon * np.gradient(epsilon * np.random.rand(*I.shape)) # Example update
return I, True
# Example functions for unperturbed and perturbed Hamiltonians
def H0_example(I):
return np.sum(I**2 / 2)
def H1_example(I, theta):
return np.sum(np.sin(theta) * I)
# Example usage
I_init = np.array([1.0, 2.0])
theta = 1
epsilon = 0.01
tau = 2.5
C = 1.0
final_I, is_valid = iterative_kam_validation(I_init, H0_example, epsilon, tau, C)
print("Final action variables:", final_I)
print("KAM validation status:", is_valid)
Final action variables: [0.99999408 1.99999408] KAM validation status: True
Toy Hamiltoniano Giove–Saturno - con due metodi + controllo finale¶
import numpy as np
from numpy.fft import rfft, rfftfreq
from scipy.integrate import solve_ivp
# -----------------------------
# 1. Hamiltoniano Giove-Saturno toy
# -----------------------------
def H0(I):
# parte integrabile
return 0.5 * np.sum(I**2)
def H1(I, theta):
# perturbazione tipo near 5:2
return np.cos(5*theta[1] - 2*theta[0])
def equations(t, y, epsilon):
I = y[:2]
theta = y[2:]
# Frequenze integrabili
omega = I
# Derivate
dtheta = omega + epsilon * np.array([
2*np.sin(5*theta[1] - 2*theta[0]),
-5*np.sin(5*theta[1] - 2*theta[0])
])
dI = epsilon * np.array([
2*np.sin(5*theta[1] - 2*theta[0]),
-5*np.sin(5*theta[1] - 2*theta[0])
])
return np.concatenate([dI, dtheta])
# -----------------------------
# 2. Integrazione simplettica (Stormer-Verlet)
# -----------------------------
def symplectic_integrator(I0, theta0, epsilon, dt, steps):
I = I0.copy()
theta = theta0.copy()
I_hist = []
theta_hist = []
for _ in range(steps):
# kick
I_half = I + 0.5 * dt * epsilon * np.array([
2*np.sin(5*theta[1] - 2*theta[0]),
-5*np.sin(5*theta[1] - 2*theta[0])
])
# drift
theta = theta + dt * I_half
# kick
I = I_half + 0.5 * dt * epsilon * np.array([
2*np.sin(5*theta[1] - 2*theta[0]),
-5*np.sin(5*theta[1] - 2*theta[0])
])
I_hist.append(I.copy())
theta_hist.append(theta.copy())
return np.array(I_hist), np.array(theta_hist)
# -----------------------------
# 3. Parametri realistici Giove-Saturno
# -----------------------------
I0 = np.array([5.2, 9.5])
theta0 = np.array([0.1, 0.2])
epsilon = 1e-3
dt = 0.01
steps = 200000 # tempo lungo ma non folle
# -----------------------------
# 4. Simulazione
# -----------------------------
#I_hist = symplectic_integrator(I0, theta0, epsilon, dt, steps)
I_hist, theta_hist = symplectic_integrator(
I0, theta0, epsilon, dt, steps
)
# -----------------------------
# 5. Diagnostica KAM-like
# -----------------------------
# Oscillazione massima
delta_I = np.max(np.linalg.norm(I_hist - I0, axis=1))
print("Max |I(t) - I(0)| =", delta_I)
# Azione mediata
I_mean = np.mean(I_hist, axis=0)
print("Time-averaged action:", I_mean)
# -----------------------------
# 6. Frequency Map Analysis minimale
# -----------------------------
def dominant_frequency(signal, dt):
fft = np.abs(rfft(signal - np.mean(signal)))
freqs = rfftfreq(len(signal), dt)
return freqs[np.argmax(fft[1:]) + 1]
def fundamental_frequency_from_slope(theta, dt):
t = np.arange(len(theta)) * dt
coeff = np.polyfit(t, theta, 1)
return coeff[0] # pendenza = frequenza
from numpy.fft import rfft, rfftfreq
from numpy.fft import fft, fftfreq
def fundamental_frequency_fft(theta, dt):
z = np.exp(1j * theta)
z = z - np.mean(z)
F = np.abs(fft(z))
freqs = fftfreq(len(z), dt)
# solo frequenze positive
mask = freqs > 0
return freqs[mask][np.argmax(F[mask])]
# Metodo A — Frequenze come pendenza media (molto robusto)
omega1 = fundamental_frequency_from_slope(theta_hist[:,0], dt)
omega2 = fundamental_frequency_from_slope(theta_hist[:,1], dt)
print("Fundamental frequencies (slope):", omega1, omega2)
print("Ratio omega2 / omega1:", omega2 / omega1)
print('')
# Metodo B — Frequency Map (FFT su e^(i*theta) )
omega1_fft = fundamental_frequency_fft(theta_hist[:,0], dt)
omega2_fft = fundamental_frequency_fft(theta_hist[:,1], dt)
print("Fundamental frequencies (FFT):", omega1_fft, omega2_fft)
print("Ratio omega2 / omega1:", omega2_fft / omega1_fft)
print('')
# Ripeto l’estrazione delle frequenze su due finestre temporali e confronto
mid = len(theta_hist) // 2
omega1_a = fundamental_frequency_from_slope(theta_hist[:mid,0], dt)
omega1_b = fundamental_frequency_from_slope(theta_hist[mid:,0], dt)
print("Frequency drift:", abs(omega1_a - omega1_b))
Max |I(t) - I(0)| = 0.0002434546018488399 Time-averaged action: [5.20003713 9.49990718] Fundamental frequencies (slope): 5.200037127652402 9.499907180868544 Ratio omega2 / omega1: 1.8268921832020366 Fundamental frequencies (FFT): 0.8275 1.512 Ratio omega2 / omega1: 1.827190332326284 Frequency drift: 1.4033219031261979e-13