Se dice que un sistema cualquiera, mecánico, eléctrico, neumático, etc., es un oscilador armónico si, cuando se deja en libertad fuera de su posición de equilibrio, vuelve hacia ella describiendo oscilaciones sinusoidales, o sinusoidales amortiguadas en torno a dicha posición estable.
En realidad esto es el estudio de oscilaciones.
Los sistemas mas sencillos a estudiar en oscilaciones son el sistema masa-resorte
y el péndulo simple
.
La solución a este sistema masa-resorte
se explica en términos de la segunda ley de Newton. Para este caso, si la masa permanece constante y solo consideramos la dirección en $x$. Entonces,
¿ Cuál es la fuerza? Ley de Hooke! \begin{equation} F = -k x, \quad k > 0 \end{equation} Vemos que la fuerza se opone al desplazamiento y su intensidad es proporcional al mismo. Y $k$ es la constante elástica o recuperadora del resorte.
Cuya solución se escribe como \begin{equation} x(t) = A \cos(\omega_{o} t) + B \sin(\omega_{o} t) \end{equation} Y su primera derivada (velocidad) sería \begin{equation} \dot{x}(t) = \omega_{0}[- A \sin(\omega_{0} t) + B\cos(\omega_{0}t)] \end{equation}
x vs t
, tanto para la posición y velocidad? Esta instrucción es para que las gráficas aparezcan dentro de este entorno.
In [1]:
%matplotlib inline
Esta es la librería con todas las instrucciones para realizar gráficos.
In [2]:
import matplotlib.pyplot as plt
In [3]:
import matplotlib as mpl
label_size = 14
mpl.rcParams['xtick.labelsize'] = label_size
mpl.rcParams['ytick.labelsize'] = label_size
Y esta es la librería con todas las funciones matemáticas necesarias.
In [4]:
import numpy as np
In [5]:
t = np.linspace(0, 50, 100)
plt.figure(figsize = (7, 4))
plt.plot(t, .5*np.cos(.5 *t) + .1 * np.sin(.5 *t), '-', lw = 1, ms = 4,
label = '$x(t)$')
plt.plot(t, .5*.1*np.cos(.5*t) - .5*.5 * np.sin(.5*t), 'ro-', lw = 1, ms = 4,
label = r'$\dot{x(t)}$')
plt.xlabel('$t$', fontsize = 20)
plt.show()
In [6]:
plt.figure(figsize = (7, 4))
plt.scatter(t, .5*np.cos(.5 *t) + .1 * np.sin(.5 *t), lw = 0, c = 'red',
label = '$x(t)$')
plt.plot(t, .5*np.cos(.5 *t) + .1 * np.sin(.5 *t), 'r-', lw = 1)
plt.scatter(t, .5*.1*np.cos(.5*t) - .5*.5 * np.sin(.5*t), lw = 0, c = 'b',
label = r'$\dot{x(t)}$')
plt.plot(t, .5*.1*np.cos(.5*t) - .5*.5 * np.sin(.5*t), 'b-', lw = 1)
plt.xlabel('$t$', fontsize = 20)
plt.legend(loc = 'best')
plt.show()
Y si consideramos un conjunto de frecuencias de oscilación, entonces
In [49]:
frecuencias = np.array([.1, .2 , .5, .6])
plt.figure(figsize = (7, 4))
for f in frecuencias:
plt.plot(t, .5 * np.cos(f * t) + .1 * np.sin(f * t), '*-')
plt.xlabel('$t$', fontsize = 16)
plt.ylabel('$x(t)$', fontsize = 16)
plt.title('Oscilaciones', fontsize = 16)
plt.show()
In [9]:
t=np.linspace(0,50)
Estos colores, son el default de matplotlib
, sin embargo existe otra librería dedicada, entre otras cosas, a la presentación de gráficos.
In [10]:
import seaborn as sns
sns.set(style='ticks', palette='Set2')
In [11]:
frecuencias = np.array([.1, .2 , .5, .6])
plt.figure(figsize = (7, 4))
for f in frecuencias:
plt.plot(t, .5 * np.cos(f * t) + .1 * np.sin(f * t), 'o-',
label = '$\omega_0 = %s$'%f)
plt.xlabel('$t$', fontsize = 16)
plt.ylabel('$x(t)$', fontsize = 16)
plt.title('Oscilaciones', fontsize = 16)
plt.legend(loc='center left', bbox_to_anchor=(-.5, 0.9), prop={'size': 20})
plt.show()
In [11]:
frecuencias = np.array([.1, .2 , .5, .6])
simbolos = np.array(['o', 'D', '*', '.'])
plt.figure(figsize = (7, 4))
for indx, f in enumerate (frecuencias):
plt.plot(t, .5 * np.cos(f * t) + .1 * np.sin(f * t), simbolos[indx],
label = '$\omega_0 = %s$'%f)
plt.xlabel('$t$', fontsize = 16)
plt.ylabel('$x(t)$', fontsize = 16)
plt.title('Oscilaciones', fontsize = 16)
plt.legend(loc='center left', bbox_to_anchor=(-.5, 0.9), prop={'size': 20})
plt.show()
In [12]:
frecuencias = np.array([.1, .2 , .5, .6])
lineas = np.array(['-', '-.', ':', '.'])
colores = np.array(['blue', 'black', 'magenta', 'orange'])
plt.figure(figsize = (7, 4))
for indx, f in enumerate (frecuencias):
plt.plot(t, .5 * np.cos(f * t) + .1 * np.sin(f * t), lineas[indx], lw = 3.4,
color = colores[indx],
label = '$\omega_0 = %s$'%f)
plt.xlabel('$t$', fontsize = 16)
plt.ylabel('$x(t)$', fontsize = 16)
plt.title('Oscilaciones', fontsize = 16)
plt.legend(loc='center left', bbox_to_anchor=(-.5, 0.9), prop={'size': 20})
plt.show()
Si queremos tener manipular un poco mas las cosas, hacemos uso de lo siguiente:
In [13]:
from ipywidgets import *
In [14]:
def masa_resorte(t = 0):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(.5 * np.cos(.5 * t) + .1 * np.sin(.5 * t), [0], 'ko', ms = 10)
ax.set_xlim(xmin = -0.6, xmax = .6)
ax.axvline(x=0, color = 'r')
ax.axhline(y=0, color = 'grey', lw = 1)
fig.canvas.draw()
interact(masa_resorte, t = (0, 50,.01));
La opción de arriba generalmente será lenta, así que lo recomendable es usar interact_manual
.
In [15]:
def masa_resorte(t = 0):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(.5 * np.cos(.5 * t) + .1 * np.sin(.5 * t), [0], 'ko', ms = 10)
ax.set_xlim(xmin = -0.6, xmax = .6)
ax.axvline(x=0, color = 'r')
ax.axhline(y=0, color = 'grey', lw = 1)
fig.canvas.draw()
interact_manual(masa_resorte, t = (0, 50,.01));
Ahora, si fijamos nuestra atención al movimiento de un péndulo simple (oscilaciones pequeñas). La ecuación diferencial a resolver tiene la misma forma. La diferencia más evidente es como hemos definido a $\omega_{0}$. Esto quiere decir que,
\begin{equation} \theta(t) = A\cos(\omega_{0} t) + B\sin(\omega_{0}t) \end{equation}Si graficamos la ecuación de arriba vamos a encontrar un comportamiento muy similar al ya discutido anteriormente. Es por ello que ahora veremos el movimiento en el plano $xy$. Es decir,
\begin{align} x &= l \sin(\theta), \quad y = l \cos(\theta) \end{align}
In [16]:
def theta_t(a, b, g, l, t):
omega_0 = np.sqrt(g/l)
return a * np.cos(omega_0 * t) + b * np.sin(omega_0 * t)
In [32]:
def pendulo_simple(t = 0):
fig = plt.figure(figsize = (5,5))
ax = fig.add_subplot(1, 1, 1)
x = 2 * np.sin(theta_t(.4, .6, 9.8, 2, t))
y = - 2 * np.cos(theta_t(.4, .6, 9.8, 2, t))
ax.plot(x, y, 'ko', ms = 10)
ax.plot([0], [0], 'rD')
ax.plot([0, x ], [0, y], 'k-', lw = 1)
ax.set_xlim(xmin = -2.2, xmax = 2.2)
ax.set_ylim(ymin = -2.2, ymax = .2)
fig.canvas.draw()
interact_manual(pendulo_simple, t = (0, 10,.01));
Realmente lo que se tiene que resolver es,
\begin{equation} \theta(t) = \theta(0) \cos(\omega_{0} t) + \frac{\dot{\theta}(0)}{\omega_{0}} \sin(\omega_{0} t) \end{equation}Actividad. Modificar el programa anterior para incorporar las condiciones iniciales.
In [41]:
# Solución:
def theta_t(a,t):
omega_0 = np.sqrt(g/l)
return theta(a) * np.cos(omega_0 * t) + ((theta(a)/ omega_0)* np.sin(omega_0 * t) )
In [42]:
def pendulo_simple(t = 0):
fig = plt.figure(figsize = (5,5))
ax = fig.add_subplot(1, 1, 1)
x = 2 * np.sin(theta_t( 1, t))
y = - 2 * np.cos(theta_t(1, t))
ax.plot(x, y, 'ko', ms = 10)
ax.plot([0], [0], 'rD')
ax.plot([0, x ], [0, y], 'k-', lw = 1)
ax.set_xlim(xmin = -2.2, xmax = 2.2)
ax.set_ylim(ymin = -2.2, ymax = .2)
fig.canvas.draw()
interact_manual(pendulo_simple, t = (0, 10,.01));
Recuerden el momento lineal se define como
$
p = m v,
$
donde $m$ es la masa y $v$ la velocidad. Y la posición y velocidad para el sistema masa-resorte
se escriben como:
In [22]:
k = 3 #constante elástica [N]/[m]
m = 1 # [kg]
omega_0 = np.sqrt(k/m)
x_0 = .5
x_0_dot = .1
In [23]:
t = np.linspace(0, 50, 300)
In [24]:
x_t = x_0 *np.cos(omega_0 *t) + (x_0_dot/omega_0) * np.sin(omega_0 *t)
x_t_dot = -omega_0 * x_0 * np.sin(omega_0 * t) + x_0_dot * np.cos(omega_0 * t)
In [47]:
plt.figure(figsize = (7, 4))
plt.plot(t, x_t, label = '$x(t)$', lw = 1)
plt.plot(t, x_t_dot, label = '$\dot{x}(t)$', lw = 1)
plt.legend(loc='center left', bbox_to_anchor=(1.01, 0.5), prop={'size': 14})
plt.xlabel('$t$', fontsize = 18)
plt.show()
In [26]:
plt.figure(figsize = (5, 5))
plt.plot(x_t, x_t_dot/omega_0, 'ro', ms = 2)
plt.xlabel('$x(t)$', fontsize = 18)
plt.ylabel('$\dot{x}(t)/\omega_0$', fontsize = 18)
plt.show()
In [27]:
plt.figure(figsize = (5, 5))
plt.scatter(x_t, x_t_dot/omega_0, cmap = 'viridis', c = x_t_dot, s = 8, lw = 0)
plt.xlabel('$x(t)$', fontsize = 18)
plt.ylabel('$\dot{x}(t)/\omega_0$', fontsize = 18)
plt.show()
In [28]:
k = 3 #constante elástica [N]/[m]
m = 1 # [kg]
omega_0 = np.sqrt(k/m)
In [29]:
t = np.linspace(0, 50, 50)
In [30]:
x_0s = np.array([.7, .5, .25, .1])
x_0s_dot = np.array([.2, .1, .05, .01])
cmaps = np.array(['viridis', 'inferno', 'magma', 'plasma'])
In [31]:
plt.figure(figsize = (6, 6))
for indx, x_0 in enumerate(x_0s):
x_t = x_0 *np.cos(omega_0 *t) + (x_0s_dot[indx]/omega_0) * np.sin(omega_0 *t)
x_t_dot = -omega_0 * x_0 * np.sin(omega_0 * t) + x_0s_dot[indx] * np.cos(omega_0 * t)
plt.scatter(x_t, x_t_dot/omega_0, cmap = cmaps[indx],
c = x_t_dot, s = 10,
lw = 0)
plt.xlabel('$x(t)$', fontsize = 18)
plt.ylabel('$\dot{x}(t)/\omega_0$', fontsize = 18)
#plt.legend(loc='center left', bbox_to_anchor=(1.05, 0.5))
Trayectorias del oscilador armónico simple en el espacio fase $(x,\, \dot{x}\,/\omega_0)$ para diferentes valores de la energía.
In [ ]:
In [50]:
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import odeint
%matplotlib inline
In [51]:
from ipywidgets import *
In [52]:
def theta_t(a, b, g, l, t):
omega_0 = np.sqrt(g/l)
return a * np.cos(omega_0 * t) + b * np.sin(omega_0 * t)
In [53]:
def theta_t(a, b, g, l, t):
omega_0 = np.sqrt(g/l)
return a * np.cos(omega_0 * t) + b * np.sin(omega_0 * t)
In [54]:
def pendulo_simple(t = 0):
fig = plt.figure(figsize = (5,5))
ax = fig.add_subplot(1, 1, 1)
x = 2 * np.sin(theta_t(.4, .6, 9.8, 2, t))
y = - 2 * np.cos(theta_t(.4, .6, 9.8, 2, t))
ax.plot(x, y, 'ko', ms = 10)
ax.plot([0], [0], 'rD')
ax.plot([0, x ], [0, y], 'k-', lw = 1)
ax.set_xlim(xmin = -2.2, xmax = 2.2)
ax.set_ylim(ymin = -2.2, ymax = .2)
fig.canvas.draw()
interact_manual(pendulo_simple, t = (0, 10,.01));
In [55]:
colores = np.array(['viridis','inferno','Blues','Greys','Reds','RdPu'])
In [56]:
gravedades = np.array([3.7, 8.87, 9.8, 3.7, 24.8, 10.44, 8.7, 8.87, 11.15])
plt.figure(figsize = (20, 30))
for gv in gravedades:
plt.plot(2 * np.sin(theta_t(.4, .6, gv, 2, t)), - 2 * np.cos(theta_t(.4, .6, gv, 2, t)), '-', lw = 3.4,)
plt.title('Pendulos con diferentes gravedades', fontsize = 16)
plt.show()
In [57]:
k = 3 #constante elástica [N]/[m]
m = 1 # [kg]
omega_0 = np.sqrt(k/m)
In [58]:
t = np.linspace(0, 50, 50)
In [59]:
x_0s = np.array([.7, .5, .25, .1])
x_0s_dot = np.array([.2, .1, .05, .01])
cmaps = np.array(['viridis', 'inferno', 'magma', 'plasma'])
In [60]:
plt.figure(figsize = (6, 6))
for indx, x_0 in enumerate(x_0s):
x_t = x_0 *np.cos(omega_0 *t) + (x_0s_dot[indx]/omega_0) * np.sin(omega_0 *t)
x_t_dot = -omega_0 * x_0 * np.sin(omega_0 * t) + x_0s_dot[indx] * np.cos(omega_0 * t)
plt.scatter(x_t, x_t_dot/omega_0, cmap = cmaps[indx],
c = x_t_dot, s = 10,
lw = 0)
plt.xlabel('$x(t)$', fontsize = 18)
plt.ylabel('$\dot{x}(t)/\omega_0$', fontsize = 18)
#plt.legend(loc='center left', bbox_to_anchor=(1.05, 0.5))
In [ ]: