Ce JupyterNotebook présente les codes Python utilisés pour illustrer le phénomène des ondes internes abordé dans le cours Couche Limite Atmosphérique. Trois codes ont été utilisés et sont dérits ci-dessous.
Chaque code fait intervenir une onde interne avec les mêmes propriétés qui sont :
avec $U_m$ prise égale à $1 m/s$ ; $l$ et $m$ les nombres d'onde horizontal et vertical définis par $l=2\pi/d_x$ et $m=2\pi/d_z$ avec $d_x$ et $d_z$ les longueurs caractéristiques que l'on prend toutes deux égales à $10m$.
Ce code permet de tracer une onde interne suivant son vecteur d'onde d'angle $\theta$. On choisit un angle $\theta$ égale à $\frac{\pi}{6}$.
"""
Created on Tue Nov 29 15:04:55 2022
@author: alicelegendre
"""
import matplotlib.pyplot as plt
import numpy as np
#Définition des paramètres
l=1
m=1
Um=1
N=0.001
theta=np.pi/6
K=np.sqrt(l**2+m**2)
w=np.sqrt(N**2*l**2/K**2)
x=np.arange(0,10,0.1)
z=np.arange(0,10,0.1)
def u(temps):
u1=np.zeros((len(x),len(z)))
uz0=np.zeros((len(x)))
for i in range(len(x)):
for j in range(len(z)):
u1[i,j]=Um*np.cos(l*x[i]+m*z[j]-w*temps)
uz0[i]=u1[i,0] #valeur de la vitesse en z=0
return u1, uz0
#Création fonction inclinée
u, uzz0 = u(0)
c, s = np.cos(theta), np.sin(theta)
rot_matrix = np.array(((c, s), (-s, c)))
uIncline = np.array([x, uzz0]).T @ rot_matrix
plt.figure(1)
plt.plot(uIncline[:, 0], uIncline[:, 1],label='Onde interne')
plt.axis('equal') # so angles on the screen look like the real angles
plt.arrow(0, 0, 7.5, 6*np.cos(theta), head_width = 0.1, width = 0.01, color='darkred')
plt.plot([-1,-1],[-1,-1],'darkred',label='K̲')
plt.ylim(0,6)
plt.xlim(0,8)
plt.xlabel('x (m)')
plt.ylabel('z (m)')
plt.legend(loc='upper left')
plt.title('Onde interne suivant son vecteur d\'onde K̲')
Ce code permet de tracer l'évolution temporelle d'une onde interne dans le plan $(x,z)$.
Il utilise le module animation de la bibliothèque matplotlib afin d'obtenir une figure animée pouvant être enregistrée en tant que gif.
"""
Created on Mon Nov 28 10:47:34 2022
@author: alicelegendre
"""
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
# Définition des paramètres
wavelength = 10
l=2*np.pi/wavelength
m=2*np.pi/wavelength
Um=1
dt = 50 #pas de temps
N=0.001 #fréquence de Brunt-Vaisala
K=np.sqrt(l**2+m**2)
w=np.sqrt(N**2*l**2/K**2)
x=np.arange(0,30,0.1)
z=np.arange(0,30,0.1)
# Création de la figure animée
fig = plt.figure()
line, = plt.plot([], [])
plt.xlim(0, 30)
plt.ylim(0, 5)
def init():
line.set_data([], [])
return line,
def animate(i):
t = i * dt
y = Um*np.cos(l*x+m*z[30]-w*t)+z[30]
line.set_data(x, y)
return line,
ani = animation.FuncAnimation(fig, animate, init_func=init, frames=500, interval=1, blit=True, repeat=False)
titre = 'Evolution temporelle d\'une onde interne'
plt.title(titre)
plt.xlabel('x (m)')
plt.ylabel('z (m)')
ani.save(titre+'.gif', writer='pillow')
plt.show()
Ce code permet de tracer la trajectoire d'une onde rencontrant un relief marin.
La forme du relief marin est prise aléatoirement et est codé par un polynôme $P(x)=-0.003x^3+0.0495x^2$.
Afin d'animer l'onde, nous créons plusieurs figures que nous assemblons ensuite pour donner naissance à un gif.
"""
Created on Tue Nov 29 15:52:31 2022
@author: alicelegendre
"""
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
import os
import imageio
#Définition des paramètres
wavelength = 10
l=2*np.pi/wavelength
m=2*np.pi/wavelength
Um=1
N=0.001
K=np.sqrt(l**2+m**2)
w=np.sqrt(N**2*l**2/K**2)
x=np.arange(0,40,0.1)
z=np.arange(0,40,0.1)
#Création des fonctions de vitesse de l'onde et de création du relief
def VIT(temps):
u1=np.zeros((len(x),len(z)))
for i in range(len(x)):
for j in range(len(z)):
u1[i,j]=Um*np.cos(l*x[i]+m*z[j]-w*temps)
return u1
def relief(x):
r=np.zeros((len(x)))
topo=np.zeros((len(x)))
for i in range(-15,len(x)):
r[i]=-0.003*x[i-15]**3+0.0495*x[i-15]**2
if r[i]<0:
topo[i]=0
else :
topo[i]=r[i]
return topo
#Définition de de la vitesse de propagation
hauteur = 30
mean=z[hauteur]
maxU=mean+Um
minU=mean-Um
u=VIT(0)[:,hauteur]+mean
#Création de la trajectoire de l'onde interne rencontrant l'obstacle
OndeInterne=np.zeros((len(u)))
for i in range(len(OndeInterne)):
if i < 70 :
OndeInterne[i]=minU-Um
elif i >= 70 and i < 120 :
OndeInterne[i]=relief(x)[i]
else :
OndeInterne[i]=u[i]
#Ouverture et création d'un dossier de résultats
os.mkdir('/Users/alicelegendre/Desktop/CLAT/PlotOndeInterne')
os.chdir('/Users/alicelegendre/Desktop/CLAT/PlotOndeInterne')
filename=[]
#Affichage de la trajectoire totale
plt.figure(400)
ax = pl.subplot(111)
ax.fill_between(x, relief(x),linewidth=1, facecolor='dimgray')
plt.plot(x,relief(x),'k',label='relief')
plt.plot(x,OndeInterne, 'b', linewidth=2, label='onde interne')
plt.xlabel('x (m)')
plt.ylabel('z (m)')
plt.ylim(0,5)
plt.xlim(0,40)
plt.legend()
plt.title("Onde interne induite par un obstacle")
plt.savefig('OndeInterneTOTALE.png')
pl.show()
#Découpe de la trajectoire totale en figures contenant un point du parcours de l'onde
listX=[]
listY=[]
for j in range(int(len(OndeInterne))):
j2=j
listX.append(x[j2])
listY.append(OndeInterne[j2])
for f in range(len(listX)):
fig = plt.figure(f)
plt.xlim(0,40)
plt.ylim(0,5)
ax = pl.subplot()
ax.fill_between(x, relief(x),linewidth=1, facecolor='dimgray')
plt.plot(x,relief(x),'k',label='relief')
plt.plot(listX[:f], listY[:f],'.b', label='onde interne')
plt.xlabel('x (m)')
plt.ylabel('z (m)')
plt.title("Onde interne induite par un obstacle")
plt.legend()
plt.savefig('OndeInterne%d.png'%f)
filename.append('OndeInterne%d.png'%f)
filename.append('OndeInterneTOTALE.png')
plt.close('all')
#Creation du GIF final
with imageio.get_writer('mygif.gif', mode='I', duration = 0.0000000001) as writer:
for name in filename:
image = imageio.imread(name)
writer.append_data(image)
Décembre 2022, Alice Legendre