• Aucun résultat trouvé

Tracé de solution d’équation différentielle

Dans le document Calcul mathématique avec Sage (Page 111-115)

structures de données

4.3 Listes et structures composées

5.1.6 Tracé de solution d’équation différentielle

On peut combiner les commandes précédentes pour tracer des solutions d’équations ou de systèmes différentiels. Pour résoudre symboliquement une équation différentielle ordinaire, on utilise la fonctiondesolve dont l’étude fait l’objet du chapitre 10. Pour résoudre numériquement une équation différentielle,Sagenous fournit plusieurs outils :desolve_rk4(qui utilise la même syntaxe que la fonctiondesolveet qui suffit pour résoudre les équations différentielles ordinaires rencontrées en Licence), odeint(qui provient du moduleSciPy) et enfin ode_solver(qui provient de la librairieGSL dont l’utilisation est détaillée dans la section14.2). Les fonctions desolve_rk4et odeintrenvoient une liste de points qu’il est alors aisé de tracer à l’aide de la commandeline; c’est celles que nous utiliserons dans cette section pour tracer des solutions numériques.

Exemple. (Équation différentielle linéaire, du premier ordre, non résolue) Traçons les courbes intégrales de l’équation différentielle xy0−2y=x3.

sage: x = var('x'); y = function('y') sage: DE = x*diff(y(x), x) == 2*y(x) + x^3 sage: desolve(DE, [y(x),x])

(c + x)*x^2 sage: sol = []

sage: for i in srange(-2, 2, 0.2):

... sol.append(desolve(DE, [y(x), x], ics=[1, i])) ... sol.append(desolve(DE, [y(x), x], ics=[-1, i])) ...

sage: g = plot(sol, x, -2, 2) sage: y = var('y')

sage: g += plot_vector_field((x, 2*y+x^3), (x,-2,2), (y,-1,1)) sage: g.show(ymin=-1, ymax=1)

Pour diminuer le temps de calcul, il serait préférable ici de saisir « à la main » la solution générale de l’équation et de créer une liste de solutions particulières (comme cela est fait dans la correction de l’exercice14) plutôt que de résoudre plusieurs fois de suite l’équation différentielle avec des conditions initiales différentes. On aurait également pu effectuer une résolution numérique de cette équation (à l’aide de la fonction desolve_rk4) pour en tracer les courbes intégrales :

sage: x = var('x'); y = function('y') sage: DE = x*diff(y(x), x) == 2*y(x) + x^3

sage: g = Graphics() # crée un graphique vide sage: for i in srange(-2, 2, 0.2):

... g += line(desolve_rk4(DE, y(x), ics=[1, i],\

... step=0.05, end_points=[0,2]))

... g += line(desolve_rk4(DE, y(x), ics=[-1, i],\

... step=0.05, end_points=[-2,0]))

BR

OUILLON

...

sage: x, y = var('x y')

sage: g += plot_vector_field((x,2*y+x^3), (x,-2,2), (y,-1,1)) sage: g.show(ymin=-1, ymax=1)

-2 -1.5 -1 -0.5 0.5 1 1.5 2

-1 -0.5 0.5 1

(a)Résolution symbolique

-2 -1.5 -1 -0.5 0.5 1 1.5 2

-1 -0.5 0.5 1

(b)Résolution numérique

Figure 5.10– Tracé des courbes intégrales de xy02y=x3.

Comme on le voit sur l’exemple précédent, la fonction desolve_rk4 prend en argument une équation différentielle (ou le membre de droite f de l’équation écrite sous forme résoluey0 =f(y, t)), le nom de la fonction inconnue, la condition initiale, le pas et l’intervalle de résolution. L’argument optionneloutputpermet de préciser la sortie de la fonction : la valeur par défaut'list' renvoie une liste (ce qui est utile si on veut superposer des graphiques comme dans notre exemple),'plot'affiche le tracé de la solution et'slope_field'y ajoute le tracé des pentes des courbes intégrales.

Exercice 14. Tracer les courbes intégrales de l’équation x2y0y= 0.

Donnons à présent un exemple d’utilisation de la fonction odeint du moduleSciPy.

Exemple. (Équation différentielle non linéaire, résolue, du premier ordre) Traçons les courbes intégrales de l’équation y0(t) + cos(y(t)·t) = 0.

sage: import scipy; from scipy import integrate sage: f = lambda y, t: - cos(y * t)

sage: t = srange(0, 5, 0.1); p = Graphics() sage: for k in srange(0, 10, 0.15):

... y = integrate.odeint(f, k, t) ... p += line(zip(t, flatten(y))) ...

sage: t = srange(0, -5, -0.1); q = Graphics() sage: for k in srange(0, 10, 0.15):

... y = integrate.odeint(f, k, t) ... q += line(zip(t, flatten(y))) ...

sage: y = var('y')

sage: v = plot_vector_field((1, -cos(x*y)), (x,-5,5), (y,-2,11))

BR

OUILLON

sage: g = p + q + v; g.show()

La fonction odeint prend en argument le second membre de l’équation différentielle (écrite sous forme résolue), une ou plusieurs conditions initiales, et enfin l’intervalle de résolution ; elle renvoie ensuite un tableau du type numpy.ndarrayque l’on aplatit à l’aide de la commandeflatten1 déjà vue au § 4.3.2 et que l’on réunit avec le tableau t grâce à la commande zip avant d’effectuer le tracé de la solution approchée. Pour ajouter le champ des vecteurs tangents aux courbes intégrales, on a utilisé la commande plot_vector_field.

-4 -2 2 4

-2 2 4 6 8 10

Figure 5.11– Tracé des courbes intégrales de y0(t) + cos(y(t)·t) = 0.

Exemple. (Modèle proie-prédateur de Lokta-Volterra) On souhaite représen-ter graphiquement l’évolution d’une population de proies et de prédateurs évoluant suivant un système d’équations du type Lokta-Volterra :

(du

dt =aubuv,

dv

dt =−cv+dbuv.

u désigne le nombre de proies (par ex. des lapins), v le nombre de prédateurs (par ex. des renards). De plus,a,b,c,dsont des paramètres qui décrivent l’évolution des populations :acaractérise la croissance naturelle du nombre de lapins en l’absence de renards,b la décroissance du nombre de lapins due à la présence de prédateurs,c la décroissance du nombre de renards en l’absence de proies, enfindindique combien il faut de lapins pour qu’apparaisse un nouveau renard.

1. On aurait pu utiliser également la fonctionraveldeNumPyqui évite de créer un nouvel objet liste et donc optimise l’utilisation de la mémoire.

BR

OUILLON

sage: import scipy; from scipy import integrate sage: a, b, c, d = 1., 0.1, 1.5, 0.75

sage: def dX_dt(X, t=0): # Renvoie l'augmentation des populations ... return [a*X[0] - b*X[0]*X[1], -c*X[1] + d*b*X[0]*X[1]]

...

sage: t = srange(0, 15, .01) # échelle de temps sage: X0 = [10, 5] # conditions initiales : 10 lapins et 5 renards sage: X = integrate.odeint(dX_dt, X0, t) # résolution numérique sage: lapins, renards = X.T # raccourcis de X.transpose() sage: p = line(zip(t, lapins), color='red') # tracé du nb de lapins sage: p += text("Lapins",(12,37), fontsize=10, color='red')

sage: p += line(zip(t, renards), color='blue')# idem pr les renards sage: p += text("Renards",(12,7), fontsize=10, color='blue')

sage: p.axes_labels(["temps", "population"]); p.show(gridlines=True) ...

sage: ### Deuxième graphique :

sage: n = 11; L = srange(6, 18, 12 / n); R = srange(3, 9, 6 / n) sage: CI = zip(L, R) # liste des conditions initiales sage: def g(x,y):

... v = vector(dX_dt([x, y])) # pour un tracé plus lisible, ... return v/v.norm() # on norme le champ de vecteurs ...

sage: x, y = var('x, y')

sage: q = plot_vector_field(g(x, y), (x, 0, 60), (y, 0, 36)) sage: for j in range(n):

... X = integrate.odeint(dX_dt, CI[j], t) # résolution ... q += line(X, color=hue(.8-float(j)/(1.8*n))) # graphique ...

Figure 5.12– Étude d’un système proies-prédateurs.

Exercice 15. (Modèle proie-prédateur) Réécrire le script précédent en utili-santdesolve_system_rk4à la place deodeint.

BR

OUILLON

Exercice 16. (Un système différentiel autonome) Tracer les courbes inté-grales du système différentiel suivant :

x˙ =y,

y˙= 0.5y−xy3.

Exercice 17. (Écoulement autour d’un cylindre avec effet Magnus) On superpose à un écoulement simple autour d’un cylindre de rayona, un vortex de paramètreα, ce qui modifie la composante orthoradiale de vitesse. On se place dans un repère centré sur le cylindre, et on travaille en coordonnées cylindriques dans le planz= 0, autrement dit en coordonnées polaires. Les composantes de la vitesse sont alors :

vr=v0cos(ϑ) 1−a2 r2

!

; et vϑ=−v0sin(ϑ) 1 +a2 r2

!

+ 2αav0 r .

Les lignes de courant (confondues avec les trajectoires, car l’écoulement est stationnaire) sont parallèles à la vitesse. On cherche une expression paramétrée des lignes de champs ; il faut alors résoudre le système différentiel :

dr

dt =vr et dt = vϑ

r .

On utilise des coordonnées non dimensionnées, c’est-à-dire rapportées àa, rayon du cylindre, ce qui revient à supposer a = 1. Tracer les lignes de courant de cet écoulement pourα∈ {0.1; 0.5; 1; 1.25}.

L’utilisation de l’effet Magnus a été proposé pour mettre au point des systèmes de propulsion composés de gros cylindres verticaux en rotation capables de produire une poussée longitudinale lorsque le vent est sur le côté du navire (ce fut le cas du navire Baden-Baden mis au point par Anton Flettner qui traversa l’Atlantique en 1926).

Dans le document Calcul mathématique avec Sage (Page 111-115)