Trasformazione di Legendre¶

da PowerShell -- jupyter nbconvert --to html notebook.ipynb

Due oscillatori armonici indipendenti - Approccio simbolico¶

In [17]:
import sympy as sp

def legendre_transform(L, q, q_dot, p):
    """
    Trasforma un Lagrangiano simbolico in Hamiltoniana.
    :param L: Lagrangiano simbolico in termini di q e q_dot
    :param q: lista di coordinate simboliche [q1, q2, ...]
    :param q_dot: lista di velocità simboliche [q1_dot, q2_dot, ...]
    :param p: lista di simboli dei momenti generalizzati [p1, p2, ...]
    :return: Hamiltoniana simbolica H(q, p)
    """
    # p_i = ∂L/∂q̇_i
    p_expr = [sp.diff(L, qd) for qd in q_dot]

    # Equazioni p_i - ∂L/∂q̇_i = 0
    eqs = [pi - pei for pi, pei in zip(p, p_expr)]

    # Risolvi rispetto alle velocità
    sol = sp.solve(eqs, q_dot, dict=True)[0]

    # Hamiltoniana
    H = sum(pi * sol[qd] for pi, qd in zip(p, q_dot)) - L
    H = H.subs(sol)

    return sp.simplify(H)

def compute_hamiltons_equations(H, q, p):
    """
    Calcola le equazioni di Hamilton.
    Computes Hamilton_s equations from a given Hamiltonian.  
        :param H: The Hamiltonian, a function of q, p, and t. 
        :param q: A list of generalized coordinates.
        :param p: A list of generalized momenta.
    :return: 
        List of Hamilton_s equations for q and p.
    """
    q_dot_eqs = [sp.diff(H, pi) for pi in p]
    p_dot_eqs = [-sp.diff(H, qi) for qi in q]
    return q_dot_eqs, p_dot_eqs

# =========================
# ESEMPIO
# =========================

# Simboli
q1, q2 = sp.symbols('q1 q2')
q1_dot, q2_dot = sp.symbols('q1_dot q2_dot')
p1, p2 = sp.symbols('p1 p2')

q = [q1, q2]
q_dot = [q1_dot, q2_dot]
p = [p1, p2]

# Lagrangiano (oscillatore armonico 2D)
L = sp.Rational(1, 2)*(q1_dot**2 + q2_dot**2) \
    - sp.Rational(1, 2)*(q1**2 + q2**2)

# Hamiltoniana
H = legendre_transform(L, q, q_dot, p)

# Equazioni di Hamilton
q_dot_eqs, p_dot_eqs = compute_hamiltons_equations(H, q, p)

print("Hamiltoniana H:")
display(H)

print("\nEquazioni di Hamilton:")
print("q_dot =", q_dot_eqs)
print("p_dot =", p_dot_eqs)
Hamiltoniana H:
$\displaystyle \frac{p_{1}^{2}}{2} + \frac{p_{2}^{2}}{2} + \frac{q_{1}^{2}}{2} + \frac{q_{2}^{2}}{2}$
Equazioni di Hamilton:
q_dot = [p1, p2]
p_dot = [-q1, -q2]

Due oscillatori armonici indipendenti - Approccio numerico¶

In [21]:
import sympy as sp
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

# -------------------------
# Funzioni simboliche
# -------------------------
def legendre_transform(L, q, q_dot, p):
    """Trasforma Lagrangiano simbolico in Hamiltoniana simbolica"""
    H = sum(pi*qd for pi, qd in zip(p, q_dot)) - L
    subs_dict = {qd: pi for qd, pi in zip(q_dot, p)}
    return sp.simplify(H)

def compute_hamiltons_equations(H, q, p):
    """Genera le equazioni canoniche di Hamilton"""
    q_dot_eqs = [sp.diff(H, pi) for pi in p]
    p_dot_eqs = [-sp.diff(H, qi) for qi in q]
    return q_dot_eqs, p_dot_eqs

import sympy as sp
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

# -------------------------
# 1️⃣ Simboli
# -------------------------
q1, q2 = sp.symbols('q1 q2')
p1, p2 = sp.symbols('p1 p2')

# Hamiltoniana H(p,q) direttamente
H = 0.5*(p1**2 + p2**2) + 0.5*(q1**2 + q2**2)

# Equazioni di Hamilton simboliche
q_dot_eqs = [sp.diff(H, pi) for pi in [p1, p2]]
p_dot_eqs = [-sp.diff(H, qi) for qi in [q1, q2]]

# -------------------------
# 2️⃣ Lambdify per numerico
# -------------------------
f_q_dot = sp.lambdify([q1, q2, p1, p2], q_dot_eqs, 'numpy')
f_p_dot = sp.lambdify([q1, q2, p1, p2], p_dot_eqs, 'numpy')

def hamilton_ode(t, Y):
    q1_val, q2_val, p1_val, p2_val = Y
    dq = f_q_dot(q1_val, q2_val, p1_val, p2_val)
    dp = f_p_dot(q1_val, q2_val, p1_val, p2_val)
    return [dq[0], dq[1], dp[0], dp[1]]

# -------------------------
# 3️⃣ Condizioni iniziali e integrazione
# -------------------------
Y0 = [1.0, 0.5, 0.0, 0.0]  # [q1, q2, p1, p2]
t_span = (0, 20)
t_eval = np.linspace(t_span[0], t_span[1], 500)

sol = solve_ivp(hamilton_ode, t_span, Y0, t_eval=t_eval)

# -------------------------
# 4️⃣ Plot risultati
# -------------------------
plt.figure(figsize=(7,3))
plt.plot(sol.t, sol.y[0], label='q1(t)')
plt.plot(sol.t, sol.y[1], label='q2(t)')
plt.xlabel('t')
plt.ylabel('q1, q2')
plt.title('Oscillatore armonico 2D')
plt.legend()
plt.grid(True)
plt.show()
No description has been provided for this image
In [1]:
# Ecco un piccolo calcolo eseguito in Python che mostra come stimare
# un'efficienza "alla Carnot" per la fotosintesi con ipotesi semplici.
# Modifica i parametri (lunghezza d'onda, fotoni per O2, ΔG per glucosio) per esplorare.
import math

# costanti
h = 6.62607015e-34  # J*s
c = 299792458       # m/s
NA = 6.02214076e23  # 1/mol

# parametri (modificabili)
wavelength_nm = 680.0       # nm, tipico per PSII (modifica se vuoi)
photons_per_O2 = 8          # ipotesi comune per flusso lineare (esempio)
deltaG_glucose_kJ_per_mol = 2870.0  # kJ/mol; energia necessaria per formare 1 mol di glucosio da CO2+H2O

# conversioni e calcoli
wavelength_m = wavelength_nm * 1e-9
energy_photon_J = h * c / wavelength_m
energy_photon_kJ_per_mol = energy_photon_J * NA / 1000.0

# numero fotoni per glucosio (6 O2 prodotti per glucosio): photons_per_O2 * 6
photons_per_glucose = photons_per_O2 * 6

# energia luminosa assorbita per mol di glucosio (kJ/mol)
light_energy_per_glucose_kJ = photons_per_glucose * energy_photon_kJ_per_mol

# efficienza (frazione)
efficiency = deltaG_glucose_kJ_per_mol / light_energy_per_glucose_kJ

# stampa risultati
print(f"Lunghezza d'onda (nm): {wavelength_nm}")
print(f"Energia per fotone: {energy_photon_kJ_per_mol:.1f} kJ/mol di fotoni")
print(f"Fotoni per O2 (ipotesi): {photons_per_O2}")
print(f"Fotoni per glucosio (6 O2 prodotti): {photons_per_glucose}")
print(f"Energia luminosa assorbita per mol glucosio: {light_energy_per_glucose_kJ:.1f} kJ/mol")
print(f"ΔG formazione glucosio (ipotesi): {deltaG_glucose_kJ_per_mol:.1f} kJ/mol")
print(f"Efficienza teorica = energia immagazzinata / energia incidente = {efficiency*100:.1f}%")

# Mostriamo anche come cambia l'efficienza variando il numero di fotoni per O2
for p in [8, 10, 12, 15]:
    photons = p * 6
    light_kJ = photons * energy_photon_kJ_per_mol
    eff = deltaG_glucose_kJ_per_mol / light_kJ
    print(f"  se fotoni/O2 = {p:2d} -> efficienza = {eff*100:5.2f}%")
Lunghezza d'onda (nm): 680.0
Energia per fotone: 175.9 kJ/mol di fotoni
Fotoni per O2 (ipotesi): 8
Fotoni per glucosio (6 O2 prodotti): 48
Energia luminosa assorbita per mol glucosio: 8444.2 kJ/mol
ΔG formazione glucosio (ipotesi): 2870.0 kJ/mol
Efficienza teorica = energia immagazzinata / energia incidente = 34.0%
  se fotoni/O2 =  8 -> efficienza = 33.99%
  se fotoni/O2 = 10 -> efficienza = 27.19%
  se fotoni/O2 = 12 -> efficienza = 22.66%
  se fotoni/O2 = 15 -> efficienza = 18.13%
In [ ]: