Explicite PDF
Explicite PDF
Explicite PDF
1. Introduction
Ce document montre comment résoudre numériquement l’équation de diffusion en géométrie
unidirectionnelle, par la méthode des différences finies avec un schéma explicite.
Ce document est une copie du notebook
numerique/diffusion/diffusion-explicite.ipynb
2. Définition du problème
On considère l’équation de diffusion (par exemple diffusion thermique) pour un problème
unidirectionnel. La fonction T (x, t) obéit à l’équation aux dérivées partielles suivante :
∂T ∂2T
=D 2
∂t ∂x (1)
La résolution se fait pour x [a, b]. La condition initiale est supposée donnée par la fonc-
∈
tion T (x, 0) pour x [a, b]. On considère le cas où les conditions limites en x = a et x = b
∈
consistent à imposer les valeurs de T aux bornes :
T (a, t) = Ta, ∀t ≥ 0
T (b, t) = Tb, ∀t ≥ 0
3. Variables réduites
Pour faire la résolution numérique de l’équation de diffusion, il est intéressant d’introduire des
variables réduites, c’est-à-dire des variables sans dimensions. Posons tout d’abord
J x−a
x = b−a
xJ est une abscisse sans dimensions, appartenant à l’intervalle [0, 1]. On a :
∂T ∂T ∂xJ ∂T 1
= =
∂x ∂xJ ∂x ∂xJ b −a
∂2T ∂2T 1
=
∂x 2
∂x (b − a)2
J2
On a :
∂T ∂T ∂tJ ∂T 1
= =
∂t ∂t ∂t J
∂tJ τ
En reportant ces expressions des dérivées partielles dans l’équation de diffusion, on obtient
l’équation de diffusion exprimée avec les variables sans dimensions xJ et tJ, pour la fonction
T (xJ, tJ) :
∂T ∂2T
=
∂tJ
∂xJ2
La condition initiale est donnée par la fonction T (xJ, 0) pour xJ ∈[0, 1]. Les conditions limites
s’écrivent :
4. Différences finies
L’équation de diffusion est :
∂T ∂2T
=D 2 (2)
∂t ∂x
Si les variables x et t sont les variables sans dimensions xJ et tJ définies ci-dessus, on posera
D = 1.
On doit commencer par discrétiser les variables x et t. La discrétisation de x consiste à poser :
b−a
∆x = N − 1
xn = a + n∆x pour n = 0, 1, . . . N − 1
tk = k∆t pour k = 0, 1, 2, . . .
∆t est le pas de
temps.
L’indice n est donc un nombre entier (compris entre 0 et N−1) représentant la variable
d’espace alors que k est un nombre entier positif ou nul représentant le temps.
Une résolution numérique de l’équation de diffusion consiste à rechercher une
approximation de T (xn, tk) pour tout n compris entre
− 0 et N 1 et pour k = 0, 1, . . .. Notons Tn,k
cette approximation.
Considérons le développement de Taylor par rapport à la variable t :
T (xn ∂T
, + ∆t) = T , )+ (xn , )∆t + O((∆t)2)
tk (xn tk ∂t tk
MP2 Licence Creative Commons 3
2 2
La notation O((∆t) ) désigne un terme dont la valeur absolue est inférieure à K(∆t) si ∆t
est assez petit (où K est une constante).
MP2 Licence Creative Commons 4
∂T ∂2T
(∆x)2 ∂ 3T (∆x)3 4
+ O((∆x) )
T (xn + ∆x, tk) = T (xn, tk) + (xn, tk)∆x + 2
(xn, tk) + 3
(xn, tk) 6
∂x
∂T ∂x
∂2T 22
(∆x) ∂x
∂ 3T (∆x)3 4
+ O((∆x) )
T (xn − ∆x, tk) = T (xn, tk) − (xn, tk)∆x + (xn, tk) − (xn, tk) 6
∂x ∂x2 2 ∂x3
La somme de ces deux relations conduit à :
∂2T
T (xn + ∆x, tk) − 2T (xn, tk) + T (xn − ∆x, tk) 2
(xn, tk) = + O((∆x) )
∂x2 (∆x)2
Une expression de la dérivée seconde sous forme de différence finie est donc :
∂2T
Tn+1,k − 2Tn,k + Tn−1,k
2
(xn, tk) ≈
∂x (∆x)2
L’erreur de troncature de cette approximation est O((∆x)2).
On dispose ainsi d’une expression approchée de chaque dérivée partielle sous la forme d’une
différence finie, que l’on reporte dans l’équation de diffusion :
Tn,k+1 − Tn,k Tn+1,k − 2Tn,k + Tn−1,k
=D (3)
∆t (∆x)2
MP2 Licence Creative Commons 5
T0,k = Ta, ∀k ≥ 0
TN−1,k = Tb, ∀k ≥ 0
6. Implémentation
import numpy as np
from matplotlib.pyplot import *
rcParams[’figure.figsize’] = [13, 6]
Les Tn,k (instant k donné) sont stockés dans un tableau à N éléments (n = 0, 1, . . . N−1).
L’itération consiste à calculer le tableau des Tn,k+1 (instant k + 1) à partir du tableau des
Tn,k et à appliquer les conditions limites. Il est nécessaire de créer un nouveau tableau pour
faire ce calcul. La fonction iteration effectue ce calcul et renvoie le nouveau tableau.
def iteration(T,N,alpha,Ta,Tb):
# tableau contenant T(n,k) pour n=0,1,.. N-1
# N : taille du tableau
# alpha
# Ta,Tb : températures aux frontières
T1 = np.zeros(N)
T1[0] = Ta
T1[N-1] =
Tb
for n in range(1,N-1):
T1[n] = T[n] +alpha*(T[n+1]-2*T[n]+T[n-1])
return T1
Il n’est pas nécessaire de garder en mémoire les Tn,k pour tout k. La fonction calcul
effectue les itérations pour t variant de ti à tf . La variable t n’apparaît pas explicitement dans
ce calcul mais elle pourrait apparaître dans un problème où les conditions limites seraient
variables. La fonction renvoie l’instant final (qui peut être différent de tf ), le tableau des Tn,k
pour cet instant et le nombre d’itérations.
def
calcul(T,N,ti,tf,delta_t,alpha,Ta,Tb)
: t = ti
niter = 0
while t<tf:
T = iteration(T,N,alpha,Ta,Tb)
t += delta_t
niter += 1
return (t,T,niter)
Voici un exemple où x ∈ [0, 1] désigne xJ (abscisse sans dimension) et t désigne tJ (temps sans
dimensions). La condition initiale est T (x, 0) = 0 pour x ∈[0, 1]. Les conditions limites sont
T (0, t) = 1 et T (1, t) = 0.
Le choix de ∆x dépend de la pente maximale de la fonction x → T (x, t) sur l’intervalle
[0, 1]. Plus cette pente maximale est grande, plus ∆x doit être petit. Dans le problème de
diffusion étudié ici, la pente est très forte au voisinage de x = 0 pour les instants petits. Le pas
de temps est choisi à 90 % de sa valeur maximale. Essayons avec N = 210 :
MP2 Licence Creative Commons 7
N=2**10
delta_x = 1/(N-1)
x = np.arange(N)*delta_x
T = np.zeros(N)
Ta = 1
Tb = 0
D = 1
delta_t_max = delta_x**2/(2*D) # valeur maximale pour garantir la
stabilité delta_t = 0.9*delta_t_max
alpha = D*delta_t/delta_x**2
(t1,T1,niter1) = calcul(T,N,0,1e-4,delta_t,alpha,Ta,Tb)
figure()
plot(x,T1)
xlabel("x’")
ylabel(’T’)
grid()
xlim(0,1)
Voici le pas de temps qui a été utilisé pour ce calcul et le nombre d’itérations
print((delta_t,niter1))
--> (4.2999286211848885e-07, 233)
L’évolution du profil de température est rapide lorsque t est petit puis devient de plus en plus
lente.
Nous cherchons à présent à calculer l’évolution de tJ = 10−4 à tJ = 10−3. Si ∆x reste
inchangé, la valeur de ∆t ne peut pas être augmentée car elle a été choisie à 90 % de la limite
de stabilité. Or l’intervalle de temps du calcul de tJ = 10−4 à tJ = 10−3 est environ 10 fois plus
grand que le précédent. Il y aura donc 10 fois plus de calculs.
MP2 Licence Creative Commons 8
(t2,T2,niter2) = calcul(T1,N,1e-4,1e-3,delta_t,alpha,Ta,Tb)
figure()
plot(x,T2)
xlabel("x’")
ylabel(’T’)
grid()
xlim(0,1)
print(niter2)
--> 2094
Le temps de calcul est encore acceptable. L’étape suivante consiste à calculer de tJ = 10−3
à tJ = 10−2. Si on ne change pas ∆x, le nombre d’itérations sera 10 fois plus grand que le
précédent. On remarque que la pente maximale de la courbe est plus faible que pour tJ =
10−4. Il devrait donc être possible d’augmenter ∆x afin d’augmenter ∆t, donc de réduire le
nombre d’itérations. Nous avons défini N comme une puissance de 2. Il est donc facile de
réduire la valeur de N en le divisant pas 4, ce qui aura pour effet de réduire le nombre
d’itérations d’un facteur 16.
N_1 = N//4
T2_1 = T2[0::4]
x_1 = x[0::4]
figure()
plot(x_1,T2_1)
xlabel("x’")
ylabel(’T’)
grid()
xlim(0,1)
MP2 Licence Creative Commons 9
Comme on le voit sur cette figure, l’augmentation de ∆x est sans conséquence sur la
bonne représentation de la fonction xJ → T (xJ, tJ). Calculons les nouveaux paramètres du
calcul :
delta_x_1 = 1/(N_1-1)
delta_t_max_1 = delta_x_1**2/(2*D) # valeur maximale pour garantir la stabilité
delta_t_1 = 0.9*delta_t_max_1
alpha_1 = D*delta_t_1/delta_x_1**2
(t3,T3_1,niter3) = calcul(T2_1,N_1,1e-3,1e-2,delta_t_1,alpha_1,Ta,Tb)
figure()
plot(x_1,T3_1)
xlabel("x’")
ylabel(’T’)
grid()
xlim(0,1)
print(niter3)
--> 1301
MP2 Licence Creative Commons 10
(t4,T4_1,niter4) = calcul(T3_1,N_1,1e-2,1e-1,delta_t_1,alpha_1,Ta,Tb)
figure()
plot(x_1,T4_1)
xlabel("x’")
ylabel(’T’)
grid()
xlim(0,1)
print(niter4)
--> 13005
Le régime stationnaire n’est pas encore atteint. Il faut encore calculer de tJ = 10−1 à tJ =
1, ce qui demanderait 10 fois plus d’itérations si on ne change pas ∆x. Il est donc
judicieux de procéder à nouveau à une division de N d’un facteur 4 :
N_2 = N_1//4
T4_2 = T4_1[0::4]
x_2 = x_1[0::4]
figure()
plot(x_2,T4_2)
xlabel("x’")
ylabel(’T’)
grid()
xlim(0,1)
MP2 Licence Creative Commons 11
delta_x_2 = 1/(N_2-1)
delta_t_max_2 = delta_x_2**2/(2*D) # valeur maximale pour garantir la stabilité
delta_t_2 = 0.9*delta_t_max_2
alpha_2 = D*delta_t_2/delta_x_2**2
(t5,T5_2,niter5) = calcul(T4_2,N_2,1e-1,1,delta_t_2,alpha_2,Ta,Tb)
figure()
plot(x_2,T5_2)
xlabel("x’")
ylabel(’T’)
grid()
xlim(0,1)
print(niter5)
--> 7939
Le régime stationnaire est bien atteint à tJ = 1 (un examen plus détaillé montre qu’il est
atteint pratiquement pour tJ = 0,2). On voit ici l’intérêt d’avoir défini des variables xJ et tJ
sans dimensions. Le temps tJ qu’il faut pour atteindre le régime stationnaire est de l’ordre de
1. La durée réelle correspondante est τ .
Pour finir, on trace les courbes de xJ → T (xJ, tJ) obtenues pour les différents instants :
MP2 Licence Creative Commons 12
figure() plot(x,T1,label="t’=
%0.2g"%t1) plot(x,T2,label="t’=
%0.2g"%t2) plot(x_1,T3_1,label="t’=
%0.2g"%t3) plot(x_1,T4_1,label="t’=
%0.2g"%t4) plot(x_2,T5_2,label="t’=
%0.2g"%t5) xlabel("x’")
ylabel(’T’)
grid()
xlim(0,1)
legend(loc=’upper right’)