Vous êtes sur la page 1sur 12

Lycée Malherbe Année scolaire 2018-2019 MPSI - Informatique pour tous

TP no 12 - Equations différentielles :
une première approche (Corrigé)
Pour tout le TP, on note pEq l’équation différentielle

pt2 ` 1qy 1 ` pt ´ 1q2 y “ t3 ´ t2 ` t ` 1


1 Commencez par résoudre analytiquement cette équation.
On commence par résoudre l’équation homogène

pt ´ 1q2
y1 ` y “ 0.
t2 ` 1
En remarquant que
pt ´ 1q2 2t
2
“1´ 2 ,
t `1 t `1
on obtient facilement que les solutions de l’équation homogène sont les
` ` ˘˘
t ÞÑ λ exp ´t ` ln t2 ` 1 “ λpt2 ` 1q expp´tq, λ P R.

On cherche une solution particulière de l’équation avec second membre sous la forme yptq “ at ` b.
On trouve facilement que yptq “ t convient.
On en déduit les solutions sur R de l’équation avec second membre ypptq “ t ` λpt2 ` 1q expp´tq, où λ
est une constante pouvant être précisée par une condition initiale.

2 Déterminer l’unique solution telle que yp´1q “ 8.


9
ypptq “ t ` pt2 ` 1qe´t´1
2

1 Mise en œuvre des méthodes du cours

3 (incontournable !) En remarquant qu’on peut aussi écrire pEq sous la forme

1 `3 2 2
˘
y 1 “ F pt, yq “ t ´ t ` t ` 1 ´ pt ´ 1q y ,
t2 ` 1
trouvez une solution approchée de pEq avec la condition initiale de l’introduction, en utilisant la méthode
d’Euler mise en œuvre avec n “ 100 intervalles sur l’intervalle r´1, 10s.
Votre programme devra utiliser des listes Python : une liste Lt et une liste Ly toutes deux de
taille n ` 1, telles que pour tout k P v0, nw, Lt[k] est le tk du cours, et Ly[k] est le yk du cours.

1 F = lambda t,y : 1/(t**2+1) * (t**3-t**2+t+1-(t-1)**2*y)
2 n=100
3 a=-1
4 b=10
5 T=b-a
6 h=T/n
7 Lt = [ a + k * h for k in range(n+1) ]

1
8 Ly = [8]
9 for k in range(n):
10 Ly.append( Ly[k] + h * F(Lt[k],Ly[k]))
 

4 (incontournable !) Même consigne avec des tableaux numpy : cette fois vous construirez des tableaux
numpy Tt et Ty.
La taille d’un tableau numpy est définie à sa création : pas de append ici ! Le tableau Tt est initia-
lement rempli de 0, avec la commande zeros.

1 import numpy as np
2
3 F = lambda t,y : 1/(t**2+1) * (t**3-t**2+t+1-(t-1)**2*y)
4 n=100
5 a=-1
6 b=10
7 T=b-a
8 h=T/n
9 Tt=np.linspace(a,b,n+1)
10 Ty=np.zeros(n+1)
11 Ty[0]=8
12 for k in range(n):
13 Ty[k+1] = Ty[k] + h * F(Tt[k],Ty[k])
 

5 (incontournable aussi !) Représentez graphiquement la solution obtenue.



1 from euler0_tableaux import *
2
3 import matplotlib.pyplot as plt
4 plt.plot(Tt,Ty,linewidth=4)
5 plt.show()
 

Figure 1 – Solution obtenue par la méthode d’Euler (100 points)

2
6 ‹ Mêmes questions avec les autres méthodes du cours. Superposer les dessins avec le dessin de la
solution exacte.

1 import numpy as np
2
3 F = lambda t,y : 1/(t**2+1) * (t**3-t**2+t+1-(t-1)**2*y)
4 n=20
5 Lt=np.linspace(-1,10,n+1)
6 a=-1 ; b=10 ; T=b-a #longueur de l’intervalle
7 h=T/n
8
9 Ly_euler=np.zeros(n+1)
10 Ly_pointmilieu=np.zeros(n+1)
11 Ly_predcor=np.zeros(n+1)
12 Ly_RK4=np.zeros(n+1)
13
14 y0=8
15 Ly_euler[0]=y0
16 Ly_pointmilieu[0]=y0
17 Ly_predcor[0]=y0
18 Ly_RK4[0]=y0
19
20 for k in range(n):
21 tk = Lt[k]
22
23 yk = Ly_euler[k]
24 Ly_euler[k+1] = yk + h * F(tk,yk)
25
26 yk = Ly_pointmilieu[k]
27 tmp = yk + h/2 * F(tk,yk)
28 Ly_pointmilieu[k+1] = yk + h * F(tk+h/2 , tmp)
29
30 yk = Ly_predcor[k]
31 tmp1 = F(tk , yk )
32 tmp2 = F(tk+h , yk + h * tmp1)
33 Ly_predcor[k+1] = yk + h/2 * ( tmp1 + tmp2 )
34
35 yk = Ly_RK4[k]
36 k1=F(tk,yk)
37 k2=F(tk+h/2,yk+h/2*k1)
38 k3=F(tk+h/2,yk+h/2*k2)
39 k4=F(tk+h,yk+h*k3)
40 Ly_RK4[k+1] = yk + h/6 * (k1+2*k2+2*k3+k4)
41
42 import matplotlib.pyplot as plt
43 plt.plot(Lt,Ly_euler,linewidth=4,label=’Euler’)
44 plt.plot(Lt,Ly_pointmilieu,linewidth=4,label=’points milieux’)
45 plt.plot(Lt,Ly_predcor,linewidth=4,label=’prédiction correction’)
46 plt.plot(Lt,Ly_RK4,linewidth=4,label=’RK4’)
47
48 Lt0=np.linspace(-1,10,200)

3
49 plt.plot(Lt0,(lambda t : t+9/2*(t**2+1)*np.exp(-t-1))(Lt0),linewidth=4,label=’
solution exacte’)
50 plt.legend(loc=4)
51 plt.show()
 

Figure 2 – Comparaison des méthodes de résolution

2 Commandes clé-en-main de Python


Le début de ce TP et le TP précédent montrent qu’on peut programmer par nous-mêmes en quelques
lignes les méthodes numériques performantes données dans le cours. Mais pour gagner en fiabilité, on
utilise en général des fonctions fournies dans des bibliothèques dédiées.
On dispose justement en Python de commandes déjà implémentées permettant de résoudre des
équations différentielles : on utilisera la fonction odeint du module scipy.integrate qui prend pour
arguments dans cet ordre :
— la fonction f telle que l’équation à résoudre est y 1 “ f py, tq (donc ordre des variables différent de
celui du cours, habituellement utilisé en maths, c’est-à-dire F pt, yq “ f py, tq) ;
— la valeur y0 ;
— et la liste ou le tableau des tk
et retourne le tableau des yk (plus précisément un tableau numpy contenant des tableaux numpy de
longueur 1 contenant les yk , ça devrait s’éclaircir au TP suivant, mais ça n’a pas d’importance ici).
Ainsi, avec l’équation pEq, la fonction à passer à odeint est

1 `3 2 2
˘
y 1 “ f py, tq “ F pt, yq “ t ´ t ` t ` 1 ´ pt ´ 1q y .
t2 ` 1

Voici comment la résoudre avec Python (avec la condition initiale de l’introduction).

4

1 import numpy as np
2 import matplotlib.pyplot as plt
3 from scipy.integrate import odeint
4
5 f = lambda y,t : 1/(t**2+1) * (t**3-t**2+t+1-(t-1)**2*y)
6 Lt = np.linspace(-1,10,101)
7 LY = odeint(f, 8, Lt)
8 plt.plot(Lt,LY)
9 plt.show()
 

7 Recopiez et comprenez l’exemple ci-dessus.

8 Tracez différentes courbes intégrales sur l’intervalle r´1, 5s (pour différentes conditions initiales)
obtenues avec odeint, sur un même dessin. Vous pourrez limiter la fenêtre de tracé avec la commande
plt.axis([-1,5,-6,10]). Vous devriez obtenir un dessin comme à gauche sur la figure 3.

Figure 3 – Dessins des courbes intégrales de l’équation px2 ` 1qy 1 ` px ´ 1q2 y “ x3 ´ x2 ` x ` 1, avec
une petit effort sur les couleurs (à gauche) et erreurs de consistance (à droite)


1 import numpy as np
2 import matplotlib.pyplot as plt
3 from scipy.integrate import odeint
4
5 Lt = np.linspace(-1,5,100)
6 plt.axis([-1,5,-6,10])
7
8 f = lambda y,t : 1/(t**2+1) * (t**3-t**2+t+1-(t-1)**2*y)
9
10 for y0 in [-250,-200,-150,-120,-100,-80,-70,-60,-50,
11 -40,-30,-20,-10,-5,0,5,10,20,30,40,50,60,70,80,100,130]:
12 LY = odeint(f, y0, Lt)
13 plt.plot(Lt,LY,linewidth=5)
14
15 plt.plot(Lt,Lt,’k’,linewidth=5)

5
16
17 plt.show()
 

Pour un dessin plus joli utilisant une échelle de couleurs.

1 import numpy as np
2 import matplotlib.pyplot as plt
3 from scipy.integrate import odeint
4
5 Lt = np.linspace(-1,5,100)
6 plt.axis([-1,5,-6,10])
7
8 f = lambda y,t : 1/(t**2+1) * (t**3-t**2+t+1-(t-1)**2*y)
9
10 valeurs_y0=[-250,-200,-150,-120,-100,-80,-70,-60,-50,
11 -40,-30,-20,-10,-5,0,5,10,20,30,40,50,60,70,80,100,130]
12 N = len(valeurs_y0)
13 couleurs=plt.get_cmap(’rainbow’)(np.linspace(0,1,N))
14
15 for i,y0 in enumerate(valeurs_y0):
16 LY = odeint(f , y0, Lt)
17 plt.plot(Lt,LY,color=couleurs[i],linewidth=5)
18
19 plt.plot(Lt,Lt,’k’,linewidth=5)
20
21 plt.show()
 

Figure 4 – Dessins des courbes intégrales de l’équation px2 ` 1qy 1 ` px ´ 1q2 y “ x3 ´ x2 ` x ` 1, en


laissant Python gérer les couleurs

3 Ecriture de fonctions générales


Nous allons écrire des fonctions qui mettent en œuvre les méthodes du cours (au moins la méthode
d’Euler. . . ).

9 Ecrire une fonction euler(F,a,b,y0,n) qui prend en entrée une fonction F , et résoud l’équation

6
différentielle y 1 “ F pt, yq sur l’intervalle ra, bs, avec la condition initiale ypaq “ y0 , en utilisant la méthode
d’Euler en subdivisant l’intervalle en n sous-intervalles.
Votre fonction devra renvoyer un couple de listes Lt,Ly contenant respectivement les tk et les yk , ou
bien un couple de tableaux numpy Tt,Ty.

10 Comparer la solution obtenue pour différentes valeurs de n, avec la solution exacte, pour une
équation différentielle de votre choix.
Le gros du travail a déjà été fait. . . il s’agit juste d’écrire une fonction générique.
On teste avec l’équation différentielle y 1 “ cosptq, et la condition initiale yp0q “ 0. La solution exacte,
définie sur R, est bien sûr yptq “ sinptq.

1 import numpy as np
2 import matplotlib.pyplot as plt
3
4 def euler(F,a,b,y0,n):
5 Tt=np.linspace(a,b,n+1)
6 Ty=np.zeros(n+1)
7 Ty[0]=y0
8 h=(b-a)/n
9 for k in range(n):
10 Ty[k+1] = Ty[k] + h * F(Tt[k],Ty[k])
11 return(Tt,Ty)
12
13 if __name__=="__main__":
14 F = lambda t,y : np.cos(t)
15 for n in [10,20,30,50,80,100,200]:
16 Tt,Ty = euler(F,0,10*np.pi,0,n)
17 plt.plot(Tt,Ty,linewidth=3,label=’Euler,n=’+str(n))
18 plt.plot(Tt,np.sin(Tt),linewidth=5,label=’solution exacte’)
19 plt.legend()
20 plt.show()
 

11 ‹ Ecrivez aussi des fonctions pointmilieu, predcor et RK4.

4 Intervalle de définition des solutions


1
Considérons l’équation différentielle (non linéaire) y 1 “ 2ty 2 , avec la condition intiale yp0q “ .
5

12 Pouvez-vous résoudre analytiquement l’équation différentielle proposée ?


En partant de l’égalité y 1 ptq “ 2t yptq2 , on peut faire passer le yptq2 à gauche (la fonction nulle est
solution et les autres solutions ne s’annulent jamais) et prendre une primitive de chaque côté.
On obtient les solutions (exactes) (K P R)

1
ypptq “ , et yp ” 0.
K ´ t2
Et avec la condition initiale, celle qui nous intéresse est
1
ypptq “ ,
5 ´ t2

7
Figure 5 – La méthode d’Euler pour différentes valeurs de n, comparée à la solution exacte

‰ ? “ ‰ ? ? “ ‰? “
solution sur ´8, ´ 5 , ´ 5, 5 et 5, `8 .

13 Comparer la solution exacte avec la solution fournie par odeint et par la méthode d’Euler pour
différentes finesses de subdivision,
? sur l’intervalle r0, 2s. Puis sur l’intervalle r0, 2.1s. Puis sur r0, 2.2s. Puis,
etc. . . toujours plus près de 5.

1 import numpy as np
2 import matplotlib.pyplot as plt
3 from scipy.integrate import odeint
4 from euler_fonction import *
5
6 a,b=0,2.23
7 y0=0.2
8
9 F = lambda t,y : 2*t*y**2
10 f = lambda y,t : F(t,y)
11
12 Tt = np.linspace(a,b,101)
13
14 ### solution exacte
15 Ty = 1/(5-Tt**2)
16 plt.plot(Tt,Ty,label="solution exacte",linewidth=3)
17
18 ### odeint
19 Ty = odeint(f,y0,Tt)
20 plt.plot(Tt,Ty,label="odeint",linewidth=3)
21
22 ### fonction euler
23 for n in [10,20,50,100]:
24 Tt,Ty = euler(F,a,b,y0,n)

8
Figure 6 – Solutions de y 1 “ 2xy. En rouge, la solution avec la condition initiale de l’énoncé.

25 plt.plot(Tt,Ty,label="Euler n="+str(n),linewidth=3)
26
27 plt.legend(loc=2)
28 plt.show()
 

La solution exacte et la solution de odeint sont toujours confondues. Les fonctions pré-existantes sont
décidément bien faites !
?
Notre fonction Euler “cale” de plus en plus quand on s’approche de 5.

14 Que donne la fonction odeint comme solution sur l’intervalle r0, 3s ?



1 import numpy as np
2 import matplotlib.pyplot as plt
3 from scipy.integrate import odeint
4 from euler_fonction import *
5
6 a,b=0,3
7 y0=0.2
8
9 F = lambda t,y : 2*t*y**2
10 f = lambda y,t : F(t,y)
11
12 Tt = np.linspace(a,b,101)
13 Ty = odeint(f,y0,Tt)
14 plt.plot(Tt,Ty,linewidth=3)
15
16 plt.show()
 

1 Excess work done on this call (perhaps wrong Dfun type).
2 Run with full_output = 1 to get quantitative information.
3 lsoda-- at current t (=r1), mxstep (=i1) steps
4 taken on this call before reaching tout

9
Figure 7 – Solutions au voisinage du point à problème

5 in above message, i1 = 500


6 in above message, r1 = 0.2236066347348D+01
?
La solution n’est pas définie en 5. Il est normal que les méthodes ne fonctionnent pas quand on veut
aller jusqu’à 3 (quand on franchit l’asymptote. . . ).

Figure 8 – Résolution d’une équation différentielle à problème (avec odeint à gauche ; avec ma fonction
euler à droite)

10
15 Que donne votre fonction euler sur l’intervalle r0, 3s ?
On obtient un warning, et un dessin aberrant.

1 from euler_fonction import *
2 Tt,Ty = euler(lambda t,y:2*t*y**2,0,3,0.2,100)
3 plt.plot(Tt,Ty,linewidth=3)
4 plt.show()
 

1 intervalle3.py:2: RuntimeWarning: overflow encountered in double_scalars
2 Tt,Ty = euler(lambda t,y:2*t*y**2,0,3,0.2,100)

5 Qualité des solutions ‹


Pour terminer, brève étude expérimentale d’erreur de consistance des différentes méthodes.

16 ‹ Représentez sur un même dessin, les logarithmes des erreurs de consistance de chaque méthode en
fonction de ´ logphq où h est le pas de la subdivision, lors de la résolution de l’équation pEq (condition
initiale p´1, 8q, intervalle r´1, 5s).
Vous devriez obtenir un dessin comme à droite sur la figure 3.
9
La solution exacte de condition initiale p´1, 8q est ypptq “ t ` p1 ` t2 q expp´t ´ 1q.
2
Si l’erreur de consistance ephq est de l’ordre de hα avec α ą 0, alors la courbe de log pephqq en fonction
de ´ logphq est une droite de pente ´α.
Et pour que les points en abscisse soient bien espacés, on choisit des valeurs de x régulièrement
espacées, et on trace la courbe sur les points h “ e´x .
Ce sont les courbes pour les différentes méthodes qu’on représente sur le dessin suivant, décalées
verticalement pour qu’elles partent du même point d’ordonnée nulle, afin de pouvoir comparer les pentes.

1 import numpy as np
2 import matplotlib.pyplot as plt
3
4 F = lambda t,y : 1/(t**2+1) * (t**3-t**2+t+1-(t-1)**2*y)
5
6 #erreurs de consistance e(h) pour les différentes méthodes, en fonction de h
7 Le_euler=[]
8 Le_pointmilieu=[]
9 Le_predcor=[]
10 Le_RK4=[]
11
12 #solution exacte
13 z=lambda t : t+9/2*(t**2+1)*np.exp(-t-1)
14
15 N=40
16 Lx = np.linspace(1,6,N)
17 Lh = np.exp(-Lx)
18
19 for h in Lh:
20 Tt=np.arange(-1,5,h)
21 n=len(Tt)-1
22

11
23 e_euler, e_pointmilieu, e_predcor, e_RK4 = 0,0,0,0
24
25 for k in range(n):
26 tk=Tt[k]
27 zk=z(tk) # ^y(t_k)
28 zkp1=z(Tt[k+1]) # ^y(t_{k+1})
29
30 e_euler += abs ( zkp1 - ( zk + h * F(tk,zk) ) )
31
32 tmp = zk + h/2 * F(tk,zk)
33 e_pointmilieu += abs ( zkp1 - ( zk + h * F(tk+h/2 , tmp)) )
34
35 tmp1 = F(tk , zk )
36 tmp2 = F(tk+h , zk + h * tmp1 )
37 e_predcor += abs ( zkp1 - ( zk + h/2 * ( tmp1 + tmp2 ) ) )
38
39 k1=F(tk,zk)
40 k2=F(tk+h/2,zk+h/2*k1)
41 k3=F(tk+h/2,zk+h/2*k2)
42 k4=F(tk+h,zk+h*k3)
43 e_RK4 += abs ( zkp1 - ( zk + h/6 * (k1+2*k2+2*k3+k4) ) )
44
45 Le_euler.append(e_euler)
46 Le_pointmilieu.append(e_pointmilieu)
47 Le_predcor.append(e_predcor)
48 Le_RK4.append(e_RK4)
49
50
51 plt.plot(Lx,np.log(np.array(Le_euler))-np.log(Le_euler[0]),
52 label=’méthode d\’Euler’, linewidth=3)
53 plt.plot(Lx,np.log(np.array(Le_pointmilieu))-np.log(Le_pointmilieu[0]),
54 label=’méthode du point-milieu’, linewidth=3)
55 plt.plot(Lx,np.log(np.array(Le_predcor))-np.log(Le_predcor[0]),
56 label=’méthode de prédiction-correction’, linewidth=3)
57 plt.plot(Lx,np.log(np.array(Le_RK4))-np.log(Le_RK4[0]),
58 label=’méthode RK4’, linewidth=3)
59
60 plt.legend(loc=3)
61 plt.show()
 

12

Vous aimerez peut-être aussi