Equazione di Euler-Lagrange¶
Consideriamo un sistema meccanico classico descritto mediante il formalismo lagrangiano. Il tempo è rappresentato dalla variabile indipendente $t$ e le coordinate generalizzate sono funzioni del tempo $q(t)$.
La velocità generalizzata è definita come $$ \dot{q}(t) = \frac{dq}{dt}. $$
Il cuore dell’esercizio è la funzione $euler\_lagrange$, che implementa in forma simbolica l’equazione di Eulero--Lagrange associata a un lagrangiano $$ \mathcal{L}(q,\dot{q},t). $$
L’equazione di Eulero--Lagrange è $$ \frac{d}{dt}\left( \frac{\partial \mathcal{L}}{\partial \dot{q}} \right)- \frac{\partial \mathcal{L}}{\partial q} = 0. $$
Nel codice:
- si calcola la derivata parziale del lagrangiano rispetto a $q$,
- si calcola la derivata parziale del lagrangiano rispetto a $\dot{q}$,
- si deriva quest’ultima rispetto al tempo,
- si restituisce la differenza tra i due termini.
Come esempio viene considerato l’oscillatore armonico unidimensionale, il cui lagrangiano è $$ \mathcal{L} = \frac{1}{2} m \dot{q}^2 - \frac{1}{2} k q^2, $$ dove $m$ è la massa e $k$ la costante elastica.
Applicando l’equazione di Eulero--Lagrange si ottiene $$ m \ddot{q} + k q = 0, $$ che è l’equazione del moto dell’oscillatore armonico.
Successivamente il codice generalizza il formalismo a sistemi con più gradi di libertà. Dato un insieme di coordinate generalizzate $$ \{q_1(t), q_2(t), \dots\}, $$ il lagrangiano totale viene costruito come $$ \mathcal{L} = T - V, $$ dove l’energia cinetica è $$ T = \sum_i \frac{1}{2} m_i \dot{q}_i^2 $$ e il potenziale $V$ può dipendere da tutte le coordinate.
La funzione $hamilton\_principle$ applica il principio di Hamilton, calcolando un’equazione di Eulero--Lagrange per ciascuna coordinata generalizzata. Il risultato è un sistema di equazioni differenziali del secondo ordine che descrive la dinamica completa del sistema.
Infine, il codice tenta di risolvere simbolicamente le equazioni del moto utilizzando $dsolve$. Questo passaggio è puramente computazionale e dipende dalla complessità del potenziale scelto.
In sintesi, l’esercizio mostra come tradurre in modo diretto e rigoroso il formalismo variazionale della meccanica classica in un algoritmo simbolico, capace di:
- costruire un lagrangiano,
- derivare automaticamente le equazioni di Eulero--Lagrange,
- estendersi a sistemi con più gradi di libertà.
Approccio simbolico¶
import sympy as sp
# Definiamo il tempo
t = sp.symbols('t')
# Coordinate generalizzate come funzioni del tempo
q = sp.Function('q')(t)
dq = sp.diff(q, t)
def euler_lagrange(L, q):
"""
Calcola l'equazione di Eulero-Lagrange per il lagrangiano L(q, dq, t)
"""
dq = sp.diff(q, t)
dL_dq = sp.diff(L, q)
dL_ddq = sp.diff(L, dq)
ddt_dL_ddq = sp.diff(dL_ddq, t)
return sp.simplify(ddt_dL_ddq - dL_dq)
# Esempio: oscillatore armonico
m, k = sp.symbols('m k', positive=True)
L_osc = sp.Rational(1, 2) * m * dq**2 - sp.Rational(1, 2) * k * q**2
eq_motion = euler_lagrange(L_osc, q)
aaa = sp.simplify(eq_motion)
print("Eulero-Lagrange Equation:")
display(aaa)
# For systems with multiple degrees of freedom
def multi_dof_lagrangian(masses, potentials, coordinates):
"""
Construct Lagrangian for a system with multiple degrees of
freedom.
:param masses: List of mass coefficients.
:param potentials: List of potential energy terms.
:param coordinates: List of generalized coordinates.
:retum:
Lagrangian as a sympy expression.
"""
kinetic = sum((1/2) * m * sp.diff(q, t)**2 for m, q in zip(masses, coordinates))
potential = sum(potentials)
return kinetic - potential
# Coordinate generalizzate
q_1 = sp.Function('q_1')(t)
q_2 = sp.Function('q_2')(t)
coordinates = [q_1, q_2]
# Masse simboliche
m1, m2 = sp.symbols('m1 m2')
masses = [m1, m2]
# Potenziale (esempio generico)
V = sp.Function('V')(q_1, q_2)
potentials = [V]
L_multi_dof = multi_dof_lagrangian(masses, potentials, coordinates)
print("Eulero-Lagrange Equation for multi-dof:")
display(L_multi_dof)
# Hamilton's Principle computational method
def hamilton_principle(initial_conditions, L):
"""
Apply Hamilton's principle to derive the equations of motion.
:param initial_conditions: Dictionary of initial conditions.
:param L: Lagrangian of the system.
:return:
System of Euler-Lagrange equations.
"""
equations = []
for coord in initial_conditions.keys():
equations.append(euler_lagrange(L, coord))
return equations
initial_conditions = {q_1: 1, q_2: 1}
eom_multi_dof = hamilton_principle(initial_conditions, L_multi_dof)
print("Hamilton Principle")
display(eom_multi_dof[0])
display(eom_multi_dof[1])
# Computational approach to solve E-L equation
def solve_ode(equations, initial_conditions, t_span):
solutions = {}
for eq in equations:
# eq = m * q'' + dV/dq
ode = sp.Eq(sp.diff(eq, t), 0) # simbolico placeholder
try:
sol = sp.dsolve(eq)
solutions[str(eq)] = sol
except Exception as e:
solutions[str(eq)] = f"Non risolvibile simbolicamente: {e}"
return solutions
t_span = (0, 10)
solutions_ode = solve_ode(eom_multi_dof, initial_conditions, t_span)
print("Equations of Motion (Harmonic Oscillator):")
display(eq_motion)
"""
print("Equations of Motion (Multi-DOF System):", eom_multi_dof)
print("ODE Solutions:", solutions_ode)
"""
a=1
Eulero-Lagrange Equation:
Eulero-Lagrange Equation for multi-dof:
Hamilton Principle
Equations of Motion (Harmonic Oscillator):
Esempio numerico : due oscillatori accoppiati¶
Potenziale = $V(q_1,q_2)=\frac{1}{2}k(q_1^2+q_2^2)+\frac{1}{2}kc(q_1−q_2)^2$¶
Mostra fenomeni interessanti: battimenti, modi normali, trasferimento di energia¶
import sympy as sp
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
# Parameters
m1_val, m2_val = 1.0, 1.0
k_val, kc_val = 2.0, 0.5
# ODE system manually defined (coupled harmonic oscillators)
def system(t, y):
q1, dq1, q2, dq2 = y
ddq1 = -(k_val + kc_val)*q1 + kc_val*q2
ddq2 = kc_val*q1 - (k_val + kc_val)*q2
return [dq1, ddq1, dq2, ddq2]
# Initial conditions
y0 = [0.0, 0.0, 1.0, 0.0]
# Time span
t_eval = np.linspace(0, 20, 2000)
sol = solve_ivp(system, (0, 20), y0, t_eval=t_eval)
# Plot
plt.figure(figsize=(6,3))
plt.plot(sol.t, sol.y[0], label="q1(t)")
plt.plot(sol.t, sol.y[2], label="q2(t)")
plt.xlabel("t")
plt.ylabel("q")
plt.legend()
plt.title("Evoluzione q1(t) e q2(t) per oscillatori accoppiati")
plt.show()