Le script aborde le modèle d'un pendule simple dont l'équation différentielle du mouvement est décrite par :
\begin{equation} \mathsf{ \frac{d^2 \theta}{dt^2} +\frac{g}{l} sin(\theta) =0 } \end{equation}Plusieurs aspects sont abordés :
Ce script donne lieu à un second script abordant cet oscillateur cette fois l'oscillateur en présence de frottements fluides.
La bibliothèque numpy
est utilisée pour sa collection de fonctions (sin par exemple) et pou générer une liste d'abscisses avec la fonction linspace
.
La bibliothèque matplolib
est utilisée pour tracer des graphiques.
Le module integrate
de la bibliothèque scipy
permet d'intégrer numériquement une équation différentielle.
L'intégration de l'équation différentielle est ici réalisée grâce à la fonction odeint
. Il est ici nécessaire de définir une fonction $\mathsf{f}$ qui dérive un vecteur $\mathsf{X}$ dont les composantes sont $\mathsf{{\theta}}$ et $\mathsf{\frac{d\theta}{dt}} :
Exemple avec l'équation différentielle précédemment décrite : \begin{equation} \mathsf{ f : \begin{pmatrix} \theta \\ \frac{d\theta}{dt} \end{pmatrix} \mapsto \begin{pmatrix} \frac{d\theta}{dt} \\ -\frac{g}{l} sin(\theta) \end{pmatrix} } \end{equation}
Les trois arguments de odeint
sont :
t
.odeint
renvoie un tableau dont la première colonne est la liste des valeurs successives de $\mathsf{\theta}$ et la seconde, celles des valeurs succesives de la dérivée première $\mathsf{\frac{d\theta}{dt}}$.
Pour extraire une partie des données :
[:,0]
(1ère colonne)[:,1]
(2ème colonne)Le script génère des graphiques permettant de comparer la période des oscillations du pendule simple en fonction des conditions initiales :
Manipulation du script
L'utilisateur peut notamment modifier les valeurs des vitesses initiales d'angle ou de vitesse. A noter que pour des vitesses initiales torp élevées, il n'est pas constaté de régime d'oscillations mais un mouvement circulaire non uniforme.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
#Saisie de données (longueur, accélération pesanteur, vitesses initiales en m/s, angle initial en rad)
l=0.2
g=9.8
Ltheta0=[0,0.2,0.4,0.6,0.8,1,1.2]
Lv0=[0,1,2,3,4,8,10]
t = np.linspace(0,1.6,1000)
#%%# Résolution de l'équation différentielle du second ordre sans approximation
def f(X,t):
theta,theta_point = X
return theta_point,-g/l*np.sin(theta)
def angle(theta0,v0):
return odeint(f,[theta0,v0],t)[:,0]
# Retourne la liste des angles (1ère colonne)
def vitesse(theta0,v0):
return odeint(f,[theta0,v0],t)[:,1]
# Retourne la liste des dérivées premières de l'angle (2ème colonne)
#Simulation avec angle initial variable, vitesse initiale nulle
plt.figure(1)
v0=0
for theta0 in Ltheta0 :
plt.plot(t,angle(theta0,v0),label=f'{theta0} rad')
plt.xlabel('temps en s')
plt.ylabel('angle en rad')
plt.title('angle initial variable, vitesse initiale nulle')
plt.grid()
plt.legend()
plt.show()
#Simulation avec angle initial nul, vitesse initiale variable
plt.figure(2)
theta0=0
for v0 in Lv0 :
plt.plot(t,angle(theta0,v0),label=f'{v0} m/s')
plt.xlabel('temps en s')
plt.ylabel('angle en rad')
plt.title('angle initial nul, vitesse initiale variable')
plt.grid()
plt.legend()
plt.show()
Le script génère des graphiques permettant de comparer le résultat de l'intégration numérique de l'équation du mouvement avec l'approximation des petits angles ou sans cette approximation.
Manipulation du script
L'utilisateur peut modifier les valeurs des vitesses initiales.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
#Saisie de données (longueur, accélération pesanteur, vitesses initiales en m/s, angle initial en rad)
l=0.2
g=9.8
Ltheta0=[0,0.2,0.4,0.6,0.8,1,1.2]
Lv0=[0,1,2,3,4,8,10]
t = np.linspace(0,1.6,1000)
# Fonctions pour la résolution SANS approximation
def f(X,t):
theta,theta_point = X
return theta_point,-g/l*np.sin(theta)
def angle(theta0,v0):
return odeint(f,[theta0,v0],t)[:,0]
# Fonctions pour la résolution AVEC approximation
def f_approx(X,t):
theta,theta_point = X
return theta_point,-g/l*theta
def angle_approx(theta0,v0):
return odeint(f_approx,[theta0,v0],t)[:,0]
# Tracés
plt.subplot(211)
plt.title('Comparaison avec ou sans apprxomation des petits angles')
v0=1
plt.plot(t,angle(theta0,v0),label=f'sans approx {v0} m/s')
plt.plot(t,angle_approx(theta0,v0),label=f'avec approx {v0} m/s')
plt.xlabel('temps en s')
plt.ylabel('angle en rad')
plt.grid()
plt.legend()
plt.subplot(212)
v0=12
plt.plot(t,angle(theta0,v0),label=f'sans approx {v0} m/s')
plt.plot(t,angle_approx(theta0,v0),label=f'avec approx {v0} m/s')
plt.xlabel('temps en s')
plt.ylabel('angle en rad')
plt.grid()
plt.legend()
plt.show()
Le script calcule les valeurs de l'énergie cinétique et de l'énergie potentielle à chaque instant. Ces énergies sont sommées pour obtenir l'énergie mécanique.
Manipulation du script
L'utilisateur peut modifier les valeurs des vitesses initiales à comparer.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
#Saisie de données (longueur, accélération pesanteur, vitesses initiales en m/s, angle initial en rad)
l=0.2
g=9.8
Ltheta0=[0,0.2,0.4,0.6,0.8,1,1.2]
Lv0=[0,1,2,3,4,8,10]
t = np.linspace(0,1.6,1000)
# Fonctions pour la résolution SANS approximation
def f(X,t):
theta,theta_point = X
return theta_point,-g/l*np.sin(theta)
def angle(theta0,v0):
return odeint(f,[theta0,v0],t)[:,0]
def vitesse(theta0,v0):
return odeint(f,[theta0,v0],t)[:,1]
def Ec(theta0,v0):
return .5*l**2*vitesse(theta0,v0)**2
def Ep(theta0,v0):
return g*l*(1-np.cos(angle(theta0,v0)))
plt.figure(4)
plt.title('Energie')
# Superposition des tracés d'énergies pour deux vitesses initiales
plt.subplot(211)
v0=1
plt.plot(t,Ec(theta0,v0),label=f'Ec {v0} m/s ')
plt.plot(t,Ep(theta0,v0),label=f'Ep {v0} m/s')
plt.plot(t,Ec(theta0,v0)+Ep(theta0,v0),label=f'Em {v0} m/s')
plt.xlabel('temps en s')
plt.ylabel('Energie')
plt.grid()
plt.legend()
plt.subplot(212)
v0=12
plt.plot(t,Ec(theta0,v0),label=f'Ec {v0} m/s ')
plt.plot(t,Ep(theta0,v0),label=f'Ep {v0} m/s')
plt.plot(t,Ec(theta0,v0)+Ep(theta0,v0),label=f'Em {v0} m/s')
plt.xlabel('temps en s')
plt.ylabel('Energie')
plt.grid()
plt.legend()
plt.show()