Tracer une fonction avec python (vagues n°1)

Donc, c’est parti pour la série d’articles sur la simulation des vagues. Ce premier article vise à présenter succintement les outils informatique qu’on va manipuler, à savoir python et quelques bibliothèques. Sur votre machine, il faut commencer par installer :

  1. python (merci, Capt’ain obvious !)

  2. numpy (ça, c’est pour tout ce qui va être “numérique”)

  3. matplotlib (ça, c’est pour tout ce qui va être lié à l’affichage des courbes, etc)

    <troll> Une fois que ça c’est fait, vous pouvez déjà rendre votre license Matlab si vous l’avez achetée, ça sert plus à rien [0]. Ça sera une bonne chose de faite.</troll>

Aujourd’hui, on va faire quelque chose de très simple : afficher un cosinus qui avance (on peut se dire dans sa tête que c’est une vague, pour se motiver un peu :p). C’est simple, mais hyper important de savoir le faire (sinon, c’est mort pour la suite…)

Définition du domaine

La première chose à faire, est de se donner un domaine d’étude. Pour simplifier un peu, on va se donner plusieurs hypothèses que l’on gardera ensuite. On simule des vagues loin, très très loin des côtes. Donc y’a pas d’interaction entre notre vague et les côtes. Ensuite, pour simplifier encore plus, on va travailler seulement en deux dimmensions. C’est à dire que la vague peut être vue comme une fonction du style $y = f(x)$.

Sous ces hypothèses, on se donne un point de référence dans l’océan et on dit que c’est l’origine. On se donne ensuite une taille de domaine $L$, et on centre ce domaine autour du point qu’on s’est donné. Donc, avant ce point, on est du côté négatif du domaine et après du côté positif. Bien. Comment faire ça en python. C’est hyper simple. On va par exemple dire qu’on étudie les vagues sur un domaine de 10 mètres (donc $L = 10$). Numériquement, il est impossible de représenter tous les points du domaine. On ne peut étudier qu’un nombre finis de points. On va regarder $N$ points, espacés régulièrement.

>>> from pylab import *
>>> L = 10
>>> N = 256
>>> x = linspace(-L/2, L/2, N)

Et voilà, c’est tout. La fonction linspace(a, b, N) se charge de découper l’intervale $[a, b]$ en $N$ points. Exactement ce que l’on voulait. [1]

J’ai pris un $N$ qui était égal à une puissance de deux, c’est pas un hasard. On verra plus tard pourquoi ce choix. En attendant, prenez ce que vous voulez…

Calculer et afficher le cosinus

Donc, maintenant que l’on a notre domaine d’étude, on peut calculer un cosinus sur ce domaine, par exemple. Disons que nous voulons avoir $p$ périodes sur le domaine qu’on s’est fixé. Le nombre d’onde est alors $k = \frac{2\pi}{L}p$. Et en python, ça donne :

>>> p = 5 # c’est à dire, on veut 5 périodes.
>>> k = 2*pi/L * p #pi est défini dans l’import pylab qu’on a fait avant
>>> y = cos(k*x)

On a calculé notre joli cosinus, y’a plus qu’à l’afficher.

>>> plot(x, y)
>>> show()

Et là, sous vos yeux éballis, apparait une magnifique figure telle que celle-ci :

votre joli cosinus

Whouahou. Mais vous savez ce qui serait encore plus cool ? C’est que ce cosinus se déplace en fonction du temps. Qu’à cela ne tienne.

Évolution temporelle

Tout à l’heure, on s’est donné un domaine d’étude. C’était un domaine spatial. Maintenant, on va faire pareil, mais avec le temps. Par exemple, on va faire avancer la vague entre l’instant initial $t = 0$ et l’instant final $t = T_f$. Où $T_f$ est la valeur que vous voulez, par exemple $20$, pour faire un truc de 20 secondes disons. Il faut encore discrétiser car on ne peut pas travailler sur une infinité de temps. Il faut que ça soit fini. Donc disons qu’on veuille afficher la vague toutes les 0.1 secondes, alors on va avoir un pas de temps de $dt = 0.1$. On construit donc un tableau qui va contenir tous les instants que l’on veut calculer, $0, 0.1, 0.2, … $. En python, ça donne :

>>> Tf = 20
>>> dt = 0.1
>>> times = arange(0, Tf, dt)

La fonction arange() fonctionne comme le built-in range() de python, mais supporte également les valeurs réelles, c’est pour ça qu’on l’utilise ici.

Maintenent, on se donne une vitesse. À quelle vitesse voulez vous faire avancer votre vague ? Moi, j’ai envie de la faire avancer de 0.5 mètre par seconde. Donc ça donne une vitesse $c = 0.5$. Si je calcule $y = cos(kx - ct)$, ça va donc me donner ma vague de toute à l’heure, mais translatée en fonction de $t$ et de la vitesse $c$ que je me suis donnée. Donc grosso modo, ce qu’il nous reste à faire, c’est pour chaque instant $t$ (stocké dans le tableau times), calculer la position de notre vague et l’afficher. Pour se faire, le code python est le suivant :

>>> c = 0.1 #notre vitesse
>>> y = cos(x*k) # à t = 0
>>> mywave = plot(x, y)[0] #ça retourne une liste, on ne prend que le plot
>>> for t in times:
...     y = cos(k*x - c*t) #la nouvelle position de la vague
...     mywave.set_ydata(y) #on met à jour le plot
...     pause(dt)
>>>

Donc là, on commence par générer le plot à l’instant $t = 0$. Ensuite, pour chaque instant $t$ contenu dans times, on calcule la nouvelle position de notre vague, on met à jour le plot. La fonction pause() nous permet deux choses, d’une raffraichir le plot et de deux, attendre un peu (sinon, ça irait à tout vitesse, et on verrait rien…)

Voici ce que vous devriez obtenir :

Fin

Vous pouvez vous amuser à faire des trucs sympa en superposant par exemple des cosinus et des sinus avec différents nombre d’ondes et différentes vitesses. Ça peut donner un truc amusant, voyez plutôt.

Je m’arrête ici pour aujourd’hui. On a vu pas mal de choses :

  • comment se définir un domaine physique
  • comment se définir un domaine temporel
  • comment afficher une courbe
  • comment afficher une courbe qui évolue dans le temps.

Cet article était essentiel, je pense, pour être sûr de savoir afficher une fonction et de faire une petite animation. (Parce que, quand on calculera notre vraie vague, on sera bien content de savoir le faire pour voir le résultat !)

PS : je vais aussi donner à chaque fois que possible un petit fichier python à télécharger qui résume le code. Voici celui d’aujourd’hui.

PPS : la suite est ici.

[0]Peut être faut-il aussi ajouter scipy, histoire d’être complet. Mais, nous, on n’en a pas besoin.
[1]Je vais me faire huer par tous les pythonistes, mais oui ; j’ai fait un import *. Je justifie cela en disant que je le fais dans mon shell Ipython, juste pour ne pas me taper chaque import de fonction dès que j’en ai besoin dans l’article. Évidement, dans un programme ou un module ou partout ailleurs que le shell ou dans cet article, c’est à bannir (sauf si vous voulez passer quinze ans à debugguer votre code, mais c’est votre problème après…)
Published In sciences
Tags: vaguesvagues-sériepython

blogroll

social