Résolution Numérique D'équations Différentielles: 0 Du (T) DT
Résolution Numérique D'équations Différentielles: 0 Du (T) DT
Résolution Numérique D'équations Différentielles: 0 Du (T) DT
1 Introduction à la solution Uc (t ) si elle passe par ce point M. Par exemple, pour notre problème, en
supposant E(t ) = E0 = 3 V pour t ≥ 0, on a « champ de tangentes » de ce genre :
On s’intéresse à présent au problème de la résolution d’équations différentielles, c’est-à-
Uc (t ) dUc (t )
dire la détermination d’une fonction solution d’une équation faisant intervenir la fonction dt (t ) = f (Uc (t ), t )
et ses dérivées. Parfois, de telles équations peuvent être résolues analytiquement, mais
bien souvent, c’est une tâche impossible, et il faut se résoudre à chercher numériquement
une approximation de la solution, ce qui sera le but de ce chapitre.
C’est un problème qui, lui aussi, trouve de nombreuses applications pratiques dans tous
les domaines des sciences, les systèmes dont l’évolution étant décrite par une ou plusieurs
équations différentielles étant monnaie courante.
Considérons par exemple le circuit électrique suivant (où le générateur est un générateur
de tension parfait), dans l’approximation des régimes quasi-stationnaires : t
R
E(t ) Uc (t )
C Il existe une infinité de solutions à cette équation différentielle (une infinité de courbes
qui soient en tout points tangentes aux vecteurs tracés ci-dessus). Pour sélectionner celle
qui correspond à l’évolution réelle de Uc (t ), il nous faut connaître un point par lequel
passe la courbe, en général une « condition initiale ».
La loi des mailles permet de relier les différentes tensions dans le circuit :
On peut par exemple supposer que la tension Uc (t ) aux bornes du condensateur en
E(t ) = Ur (t ) + Uc (t ) t = 0 est égale à U0 = −1 V. Il ne reste alors qu’une seule et unique solution à l’équation
différentielle, représentée ci-dessous :
Les caractéristiques des dipôles permettent de lier les tensions Ur (t ) et Uc (t ) au courant
I(t ) circulant dans le circuit : Uc (t ) dUc (t )
dt (t ) = f (Uc (t ), t )
dUc (t )
Ur (t ) = R · I(t ) et I(t ) = C ·
dt
Dès lors, pour toute valeur de t et Uc (t ), on peut en déduire la valeur de la dérivée de Bien évidemment, dans le cas présent, le fait que E(t ) soit une constante permet de
Uc (t ). Dans le plan (t , Uc ), cela revient à dire que l’on connaît en tout point M la tangente
25
résoudre analytiquement l’équation différentielle, dont la solution est 2.2 Schéma d’intégration d’Euler explicite
Uc (t ) = E0 + (U0 − E0 ) e−t /RC Un schéma d’intégration est une méthode qui calcule, successivement, les différents y k
à partir des y j (avec j < k) et de la fonction f .
D’autres cas permettent une résolution analytique : lorsque E(t ) est une fonction affine, Il existe de très nombreux schémas d’intégration, qui diffèrent les uns des autres de par
polynomiale, sinusoïdale, etc 1 . Dans le cas général, toutefois, il n’existe pas de méthode leur complexité, leur précision, leur stabilité numérique, etc. Le plus simple de tous ces
universelle pour obtenir une solution analytique (c’est encore plus vrai dans le cas où schémas d’intégration est le schéma dit d’Euler explicite.
l’équation différentielle est non-linéaire).
L’idée est simple. Connaissant on calcule y k à partir de y k−1 via la relation suivante :
On peut voir cette relation entre y k et y k−1 comme liée au développement de Taylor de
t y(t ) au premier ordre en y(t k ) :
t1 t2 t3 t4 t5 t6 t7 t8 t9 t 10
y(t k ) = y(t k−1 ) + y 0 (t k−1 ) × (t k − t k−1 ) + O (t k − t k−1 )2
¡ ¢
Si f est C 1 , alors le schéma régulier d’Euler implicite est consistant d’ordre 1. En effet,
•
l’erreur de consistance e k correspond très précisément au terme que l’on a négligé dans le
développement de Lagrange, O (t k − t k−1 )2 , ce qui en fait une méthode d’ordre 1.
¡ ¢
2 2 2
2.3 Erreur de consistance ¯ e k ¯ É |e k | É M2 × h = n × M2 × h = M2 T −−−−→ 0
¯X ¯ X X
2 2 2n n→∞
Évidemment, supposer que la fonction est un segment entre t k et t k+1 dont la pente est
estimée au seul instant t k ne peut pas donner une solution exacte. L’intégration numérique Le schéma d’intégration d’Euler implicite est donc bien consistant. En diminuant le pas
de notre équation différentielle en utilisant une subdivision régulière du temps de pas h (en augmentant le nombre de subdivisions), on tend donc à s’approcher de la solution
0.5RC (∀k, (t k − t k−1 ) = h = 0.5RC) donne le résultat illustré à la page précédente : bien comme on peut le voir ci-dessous :
qu’on ne soit pas trop loin de la solution, on s’en éloigne quand même quelque peu. y(t )
On définit l’erreur de consistance¯e k , pour un ¯ schéma d’intégration et une équation
différentielle donnés, comme l’écart ¯ y k − y(t k )¯ en supposant que y k−1 était égal à y(t k−1 ). • • • • • •
• • •
• • •
• • •
Une méthode de pas régulier h est dite d’ordre p lorsque e k = O(h p+1 ) lorsque h tend • • •
•
vers 0. • •
n
X •
Elle est dite consistante lorsque e k −−−−→ 0. •
n→∞
k=1 •
•
On souhaite évidemment utiliser des schémas d’intégration consistants, et dans la
mesure du possible avec un ordre le plus grand possible, afin d’éviter les imprécisions. • t
t1 t2 t3 t4 t5 t6 t7 t8 t9 t 10
Attention, l’erreur commise à l’issue de l’intégration numérique sur [t 0 , t 0 + T] ne corres-
pond pas à la somme des erreurs de consistance.
Lorsque l’on utilise un pas h avec une méthode d’ordre p, on effectue T/h pas d’in-
27
2.4 Implémentation 2.5 Méthode de Runge-Kutta point milieu
L’implémentation de la méthode d’Euler explicite est des plus simple. Elle prend trois
Le schéma d’intégration numérique d’Euler explicite est le seul qui soit à connaître. C’est
arguments : la fonction f , la valeur y 0 de la fonction y à l’instant t 0 et la liste des t k (pour
aussi, malheureusement, un des plus inefficaces, exigeant des pas très petits pour que le
0 É k < n) pour lesquels on cherche les y k .
résultat soit de bonne qualité.
Elle retourne une liste des y k (toujours pour 0 É k < n), lesquels sont calculés de proche
De la même façon qu’il existe de nombreuses méthodes pour estimer numériquement
en proche grâce à la relation
l’intégrale d’une fonction, il existe de très nombreux schémas d’intégration. Le schéma
d’intégration d’Euler explicite s’apparente à la méthode des rectangles gauches : la valeur
y k = y k−1 + f (y k−1 , t k−1 ) × (t k − t k−1 )
de la fonction f en t k−1 est utilisée pour tout l’intervalle [t k−1 , t k ].
On a donc : Nous avions vu que la méthode du point milieu donnait une meilleure estimation de
l’intervalle, pour un même pas. On souhaiterait donc estimer la valeur de la pente, pour le
def EulerExplicite(f, y0, listeT) : calcul de y k à partir de y k−1 , non pas en t k−1 , mais en t k,m = (t k−1 + t k )/2.
listeY = [ y0 ]
Seul ennui, on ne sait pas par où passe la fonction y à l’instant t k,m !
for k in range(1, len(listeT)) : On va donc travailler en deux temps :
pas = listeT[k] - listeT[k-1] • on estime un y k,m correspondant à un instant t k,m = (t k−1 + t k )/2, à partir de y k−1
yk = listeY[k-1] + f( listeY[k-1], listeT[k-1] ) * pas grâce au schéma d’intégration d’Euler explicite ;
listeY.append(yk) • on se sert de la pente f (y k,m , t k,m ) pour calculer y k , en repartant du point (t k−1 , y k−1 ).
Un schéma valant mieux qu’un discours, on construit par exemple y 1 à partir de y 0 , puis
return listeY
y 2 à partir de y 1 , de la sorte 3 :
Pour l’utiliser, on crée la fonction f et la liste des instants t k 2 , avant d’appeler la fonction y(t )
EulerExplicite :
def f(y, t) : •
return (Eo-y) / (R*C)
N = 10
pas = 5*R*C/N •
listeT = [ 0.0 + i*pas for i in range(N+1) ]
y0 = -1.0
listeY = EulerExplicite(f, y0, listeT) t
t 1,m t1 t 2,m t2
On peut ensuite afficher le résultat grâce à la commande plot en écrivant par exemple
2. On aurait pu également utiliser numpy.linspace(0.0, 5.0*R*C, N+1) pour construire la liste des instants
tk . 3. Attention, pour plus de lisibilité, les intervalles [t 0 , t 1 ] et [t 1 , t 2 ] sont un peu plus larges que précédemment.
28
Pour déterminer y k à partir de y k−1 , cela revient à écrire : précis. On peut espérer que l’erreur commise lors d’une étape d’intégration soit liée à la
µ
(t k − t k−1 ) (t k−1 + t k )
¶ différence entre la valeur y k fournie par l’intégrateur d’Euler, et la valeur y k fournie par le
y k = y k−1 + f y k−1 + f (y k−1 , t k−1 ) × , × (t k − t k−1 ) schéma de Runge-Kutta, plus précis.
2 2
Pour choisir un nouveau pas h 0 , connaissant err et eps, on peut utiliser
L’implémentation n’est pas beaucoup plus compliquée que pour le schéma d’Euler
explicite, et reprend les deux étapes (calcul de y k,m , puis y k ) : r
eps
h0 = ×h
def RK_Milieu(f, y0, listeT) : err
listeY = [ y0 ]
En effet, de la sorte, si err<eps, le pas va augmenter, et inversement, si err>eps, on
for k in range(1, len(listeT)) :
obtient une diminution du pas.
pas = listeT[k] - listeT[k-1]
ym = listeY[k-1] + f( listeY[k-1], listeT[k-1] ) * (pas/2.0) ) En Python, cela donne 4 , avec une signature légèrement différente pour la fonction par
yk = listeY[k-1] + f( ym, listeT[k-1]+(pas/2.0) ) * pas ) rapport aux précédentes (on passe t 0 et duree plutôt qu’une liste d’instants t k , et également
listeY.append(yk) une erreur acceptable eps) :
Comme on l’a vu, le choix du pas t k − t k−1 est crucial pour obtenir autant de précision # L'erreur est assimilée à la différence entre les estimations
que possible. Cependant, un pas plus petit nécessite, naturellement, davantage de calculs. err = abs(y_E - y_R)
Le choix du pas t k − t k−1 n’est donc pas simple. Par ailleurs, utiliser un pas régulier n’est # Si l'erreur est raisonnable, on a un nouveau point y_k, t_k
pas toujours la meilleure solution possible. En effet, pour certaines valeurs de t , un pas if err < eps :
important peut convenir, tandis que pour d’autres valeurs de t , il conviendrait d’utiliser T.append(T[-1] + h)
des plus petits pas. De la même façon que, lorsque l’on conduit un véhicule sur une route, Y.append(y_R) # On préfère conserver l'estimation de RK
on peut aller (raisonablement) vite dans les lignes droites mais on est contraint de ralentir
pour négocier les virages délicats. # On adapte le pas pour la suite
Aussi peut-on envisager de laisser à l’intégrateur le soin de choisir les pas d’intégration h = 0.95 * math.sqrt(eps/err) * h
h k , potentiellement différents à chaque étape. Pour ce faire, il est besoin de pouvoir
estimer l’erreur err que l’on commet lorsque l’on effectue une étape de l’intégration, afin # On retourne les y_k mais aussi les t_k, choisis par l'algorithme
de le comparer à une erreur « acceptable » eps : si err É eps, on peut augmenter le pas return T, Y
d’intégration, et si au contraire err > eps, la dernière étape effectuée n’est pas acceptable,
et il convient de la refaire avec un pas plus petit.
Pour estimer l’erreur err, on peut calculer la valeur y k de deux façons différentes. Par 4. On remarquera un coefficient 0.95 dans le calcul du pas qui, sans être indispensable, apporte parfois un
exemple, en utilisant le schéma d’Euler et le schéma de Runge-Kutta point milieu, plus peu plus de stabilité numérique.
29
3 Utilisation de scipy (ou un vecteur, un tuple...) des y i et pour second argument t et retourne une liste (ou un
vecteur, un tuple...) contenant les y i0 = f i (y i , t ) correspondant.
3.1 Équations différentielles du premier ordre Par exemple, pour le système
Nous avons décrit dans ce chapitre le principe de quelques schémas d’intégration nu-
mérique dans le but d’illustrer le principe de la résolution numérique d’une équation 0
différentielle. Dans la pratique, on ne réécrit jamais un schéma d’intégration lorsqu’il u (t ) = 2u(t ) + v(t )
s’agit de résoudre une équation différentielle !
v 0 (t ) = −u(t ) + 2v(t )
En effet, comme nous l’avons vu, les méthodes les plus simples ne sont pas les plus
précises ni les plus stables numériquement. Des spécialistes de la question ont passé de
longues heures à mettre au point des algorithmes efficaces (utilisant des schémas d’ordre
élevés, une adaptation du pas si besoin, etc.) et il convient de s’en servir. on écrira
D’autant que cela ne représente aucune difficulté supplémentaire : la fonction odeint du def f(Y, t) :
module scipy.integrate, qui permet de résoudre une équation différentielle du premier u, v = Y # On extrait u et v de Y
ordre de la forme y 0 = f (y, t ), attends très exactement les mêmes arguments que notre return [ 2*u+v, -u+2*v ] # On retourne la liste des dérivées
fonction EulerExplicite par exemple !
Pour le problème qui nous occupe, on écrira donc très simplement : Et pour la résolution proprement dite, sur [0, 1] avec par exemple u(0) = 3 et v(0) = 4 :
3.2 Systèmes d’équations différentielles du premier ordre from matplotlib.pyplot import plot, legend, show
Parfois, on doit résoudre des équations différentielles du premier ordre couplées, par plot(T, Y[:, 0], 'r--', label="u(t)")
exemple un système de type : plot(T, Y[:, 1], 'b', label="v(t)")
0 legend(loc="upper left")
y 1 (t ) = f 1 (y1(t ), y 2 (t ), t ) show()
y 20 (t ) = f 2 (y1(t ), y 2 (t ), t )
Il n’est bien entendu pas possible de résoudre les équations différentielles séparément.
On les résoud donc simultanément, en calculant y 1,k et y 2,k correspondant à un instant
t k à partir, par exemple, des y 1,k−1 , y 2,k−1 et t k−1 (en utilisant le schéma d’Euler explicite
pour chacune des deux estimations, ou tout autre schéma d’intégration).
La fonction odeint permet naturellement de résoudre de tels systèmes, pour peu que
l’on fournisse une fonction f « vectorielle », qui prenne pour premier argument une liste
30
4 Équations différentielles du second ordre On a donc converti une équation différentielle du second ordre en dimension 1 en une
équation différentielle du premier ordre, certes en dimension 2, mais qui pourra être
4.1 Mise en équation résolue par les outils que l’on a déjà vus.
y"(t ) = f y 0 (t ), y(t ), t
¡ ¢
Pour notre problème, on définira donc la fonction f de la sorte si E(t ) = E0 = cste :
def f(Y, t) :
Par exemple, on peut s’intéresser à la détermination de Uc (t ) dans un circuit de type
Uc, DerUc = Y
« RLC série » tel que celui ci-dessous :
return [ DerUc, -(R/L)*DerUc + (1/(L*C))*(Eo-Uc) ]
L Il ne reste alors qu’à choisir les paramètres (par exemple L = 5 mH, C = 1 µF, R = 10 Ω
R
et E(t ) = E0 = 3 V) et les conditions initiales (ici Uc (t 0 ) = −1 V et Uc0 (t 0 ) = I(t 0 )/C = 0), un
E(t ) Uc (t )
intervalle de temps ([0, 500RC] ici) ainsi qu’un nombre de subdivisions (N = 1000), faire
C
appel à odeint et tracer le résultat :
y 0 (t ) y 0 (t )
µ ¶ µ ¶ µ ¶
d y(t )
= =
dt y 0 (t ) y 00 (t ) f (y 0 (t ), y(t ), k
plot(listeT, C * listeY[:,1])
xlabel("Temps (s)")
ylabel("I (A)")
show()
q
1 L
Avec un facteur de qualité Q = R C ' 7.1 on a (fort heureusement) bien obtenu un
régime pseudo-périodique.
32