Small Oscillations¶

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

Pendoli che si sincronizzano - interazione viscosa¶

Sì, il fenomeno esiste ed è ben documentato: pendoli nominalmente identici e presenti nella stessa stanza possono sincronizzarsi spontaneamente grazie a un’interazione debole, tipicamente attraverso il supporto comune (la trave, il muro, il tavolo) che funziona come un mezzo di accoppiamento dissipativo/viscoso.¶

$$ \large interazione \; \propto\, c\, (\dot{\theta_j}-\dot{\theta_i})$$
In [3]:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp

# ---------------------------------------------------------
# Modello: N pendoli accoppiati debolmente (accoppiamento viscoso)
# ---------------------------------------------------------

def coupled_pendula(t, y, N, omegas, c):
    """
    y = [theta1, theta2, ..., thetaN, dtheta1, ..., dthetaN]
    """
    thetas = y[:N]
    dthetas = y[N:]
    dd = np.zeros(N)

    # Equazioni del moto: ddtheta_i = -omega_i^2 * theta_i  + accoppiamento viscoso
    for i in range(N):
        # damping accoppiato con tutti gli altri pendoli
        coupling = 0
        for j in range(N):
            if j != i:
                coupling += c * (dthetas[j] - dthetas[i])

        dd[i] = - omegas[i]**2 * thetas[i] + coupling

    return np.concatenate([dthetas, dd])


# parametri
N = 5
omegas = 2*np.pi*(1 + 0.01*np.random.randn(N))   # piccole differenze nelle frequenze
c = 0.05                                         # forza di accoppiamento
t_max = 80

# condizioni iniziali
thetas0 = np.random.uniform(-0.5, 0.5, N)
dthetas0 = np.zeros(N)
y0 = np.concatenate([thetas0, dthetas0])

# integrazione
sol = solve_ivp(
    coupled_pendula, [0, t_max], y0,
    args=(N, omegas, c), t_eval=np.linspace(0, t_max, 2000)
)

# plotting
plt.figure(figsize=(10, 6))
for i in range(N):
    plt.plot(sol.t, sol.y[i], lw=1)
plt.xlabel("t")
plt.ylabel("theta(t)")
plt.title("Sincronizzazione spontanea di pendoli accoppiati")
plt.show()
No description has been provided for this image

Pendoli accoppiati con una molla¶

In [6]:
import numpy as np
def potential_energy_matrix(n, k, mg_l):
    """
    Constructs the stiffness matrix for a system of n coupled oscillators.
        : param n: Number of oscillators.
        :param k: Spring constant between oscillators.
        :param mg_l: Coupled weight force constant.
    :return: 
        Stiffness matrix C.
    """
    C = np.zeros((n, n))
    for i in range(n):
        C[i, i] = mg_l + k
        if i > 0:
            C[i, i - 1] = -k
            C[i - 1, i] = -k
    return C 
    
def normal_modes_analysis(mass, C):
    """
    Analyzes normal modes by solving the eigenvalue problem for coupled oscillations.
        :param mass: Mass of each oscillator.
        :param C: Potential energy matrix.
    :return: 
        Normal mode frequencies, mode shapes.
    """
    M_inv_sqrt = np.linalg.inv(np.sqrt(np.diag([mass] * len(C))))
    D = np.dot(M_inv_sqrt, np.dot(C, M_inv_sqrt))
    eigenvalues, eigenvectors = np.linalg.eigh(D)
    frequencies = np.sqrt(eigenvalues)
    mode_shapes = np.dot(M_inv_sqrt, eigenvectors)
    return frequencies, mode_shapes 
    
def coupled_pendula_example():
    """
    Example analysis of two coupled pendula with equal mass and spring connection.
    return: 
        Normal mode frequencies, mode shapes of the system.
    """
    n = 2
    mass = 1.0
    k = 0.5
    mg_l = 9.81
    C = potential_energy_matrix(n, k, mg_l)
    frequencies, mode_shapes = normal_modes_analysis(mass, C)
    return frequencies, mode_shapes # Outputs demonstration for coupled pendula

frequencies, mode_shapes = coupled_pendula_example() 
print("Normal Mode Frequencies:", frequencies)
print("Mode Shapes:\n", mode_shapes)
Normal Mode Frequencies: [3.13209195 3.28785644]
Mode Shapes:
 [[-0.70710678 -0.70710678]
 [-0.70710678  0.70710678]]

Pendoli accoppiati con una molla¶

In [1]:
import numpy as np

# -------------------------
# Parameters (SI units)
# -------------------------
m = 1.0      # mass [kg]
l = 1.0      # length [m]
k = 5.0      # spring constant [N/m]
g = 9.81     # gravity [m/s^2]

# -------------------------
# Mass and stiffness matrices
# -------------------------
M = m * l**2 * np.eye(2)

K = np.array([
    [m*g*l + k*l**2,   -k*l**2],
    [-k*l**2,          m*g*l + k*l**2]
])

# -------------------------
# Generalized eigenproblem
# -------------------------
eigvals, eigvecs = np.linalg.eig(np.linalg.inv(M) @ K)

# Angular frequencies
omega = np.sqrt(np.real(eigvals))

# Sort modes
idx = np.argsort(omega)
omega = omega[idx]
eigvecs = eigvecs[:, idx]

# Normalize mode shapes
mode_shapes = eigvecs / np.max(np.abs(eigvecs), axis=0)

# -------------------------
# Output
# -------------------------
for i in range(2):
    print(f"Mode {i+1}")
    print(f"  omega = {omega[i]:.4f} rad/s")
    print(f"  f     = {omega[i]/(2*np.pi):.4f} Hz")
    print(f"  mode shape = {mode_shapes[:, i]}")
Mode 1
  omega = 3.1321 rad/s
  f     = 0.4985 Hz
  mode shape = [1. 1.]
Mode 2
  omega = 4.4508 rad/s
  f     = 0.7084 Hz
  mode shape = [ 1. -1.]
In [ ]: