Soit une fonction u(x,t) représentant la température dans un problème de diffusion thermique, ou la concentration pour un problème de diffusion de particules. L'équation de diffusion est :
où D est le coefficient de diffusion et s(x,t) représente une source, par exemple une source thermique provenant d'un phénomène de dissipation.
On cherche une solution numérique de cette équation pour une fonction s(x,t) donnée, sur l'intervalle [0,1], à partir de l'instant t=0. La condition initiale est u(x,0). Sur les bords (x=0 et x=1) la condition limite est soit de type Dirichlet :
soit de type Neumann (dérivée imposée) :
Soit N le nombre de points dans l'intervalle [0,1]. On définit le pas de x par
On définit aussi le pas du temps . La discrétisation de u(x,t) est définie par :
où j est un indice variant de 0 à N-1 et n un indice positif ou nul représentant le temps.
Figure pleine pageLa discrétisation du terme de source est
On pose
Pour discrétiser l'équation de diffusion, on peut écrire la différence finie en utilisant les instants n et n+1 pour la dérivée temporelle, et la différence finie à l'instant n pour la dérivée spatiale :
Avec ce schéma, on peut calculer les Ujn+1 à l'instant n+1 connaissant tous les Ujn à l'instant n, de manière explicite. Ce schéma est précis au premier ordre ([1]). Comme montré plus loin, sa stabilité n'est assurée que si le critère suivant est vérifié :
En pratique, cela peut imposer un pas de temps trop petit.
L'implémentation de cette méthode est immédiate. Voici un exemple :
import numpy from matplotlib.pyplot import * N=100 x=numpy.linspace(0,1,N) dx=x[1]-x[0] dx2=dx**2 U=numpy.zeros(N) laplacien=numpy.zeros(N) dt = 3e-5 U[0]=1 U[N-1]=0 D=1.0 for i in range(1000): for k in range(1,N-1): laplacien[k] = (U[k+1]-2*U[k]+U[k-1])/dx2 for k in range(1,N-1): U[k] += dt*D*laplacien[k] figure() plot(x,U) xlabel("x") ylabel("U") grid() alpha=D*dt/dx2
print(alpha) --> 0.29402999999999996figA.pdf
Le nombre de points N et l'intervalle de temps sont choisis assez petits pour satisfaire la condition de stabilité. Pour ces valeurs, l'atteinte du régime stationnaire est très longue (en temps de calcul) car l'intervalle de temps Δt est trop petit. Si on augmente cet intervalle, on sort de la condition de stabilité :
N=100 x=numpy.linspace(0,1,N) dx=x[1]-x[0] dx2=dx**2 U=numpy.zeros(N) laplacien=numpy.zeros(N) dt = 6e-5 U[0]=1 U[N-1]=0 D=1.0 for i in range(1000): for k in range(1,N-1): laplacien[k] = (U[k+1]-2*U[k]+U[k-1])/dx2 for k in range(1,N-1): U[k] += dt*D*laplacien[k] figure() plot(x,U) xlabel("x") ylabel("U") grid() alpha=D*dt/dx2
print(alpha) --> 0.58805999999999992figB.pdf
La dérivée seconde spatiale est discrétisée en écrivant la moyenne de la différence finie évaluée à l'instant n et de celle évaluée à l'instant n+1 :
Ce schéma est précis au second ordre. Contrairement au schéma explicite, il est stable sans condition. En revanche, les à l'instant n+1 sont donnés de manière implicite. Il faut donc à chaque instant n+1 résoudre le système à N équations suivant :
Ce système est tridiagonal. On l'écrit sous la forme :
À chaque étape, on calcule la matrice colonne R et on résout le système . Pour j=0 et j=N-1, l'équation est obtenue par la condition limite.
On peut aussi écrire le membre de droite sous la forme :
ce qui donne la forme matricielle
L'analyse de stabilité de von Neumann ([2][3]) consiste à ignorer les conditions limites et le terme de source, et à rechercher une solution de la forme suivante :
Il s'agit d'une solution dont la variation spatiale est sinusoïdale, avec un nombre d'onde β. Toute solution de l'équation de diffusion sans source et sans condition limite doit tendre vers une valeur uniformément nulle au temps infini. La méthode numérique utilisée est donc stable si |σ|<1 quelque soit la valeur de β.
En reportant cette solution dans le schéma explicite, on obtient :
La valeur absolue maximale de σ est obtenue pour cos(β)=-1. On en déduit la condition de stabilité : .
Pour le schéma de Crank-Nicolson, on obtient :
|σ| est inférieur à 1, donc le schéma est inconditionnellement stable.
La discrétisation de la condition de Dirichlet (en x=0) est immédiate :
On pose donc pour la première équation du système précédent :
De même pour une condition limite de Dirichlet en x=1 on pose
Une condition limite de Neumann en x=0 peut s'écrire :
ce qui donne
Cependant, cette discrétisation de la condition de Neumann est du premier ordre, alors que le schéma de Crank-Nicolson est du second ordre. Pour éviter une perte de précision due aux bords, il est préférable de partir d'une discrétisation du second ordre ([1]) :
Un point fictif d'indice -1 a été introduit. Pour ne pas avoir d'inconnue en trop, on écrit le schéma de Crank-Nicolson au point d'indice 0 tout en éliminant le point fictif avec la condition ci-dessus ([1]). On obtient ainsi :
On obtient de la même manière la condition limite de Neumann en x=1 :
On suppose que le coefficient de diffusion n'est plus uniforme mais constant par morceaux. Exemple : diffusion thermique entre deux plaques de matériaux différents. Soit une frontière entre deux parties située entre les indices j et j+1, les coefficients de diffusion de part et d'autre étant D1 et D2. Pour j-1 et j+1, on écrira le schéma de Crank-Nicolson ci-dessus. En revanche, sur le point à gauche de la frontière (indice j), on écrit une condition d'égalité des flux :
qui se traduit par
et conduit aux coefficients suivants
Un problème de transfert thermique dans une barre comporte un flux de convection latéral, qui conduit à l'équation différentielle suivante :
où le coefficient C (inverse d'un temps) caractérise l'intensité de la convection et Te est la température extérieure.
On pose β=CΔt. Le schéma de Crank-Nicolson correspondant à cette équation est :
c'est-à-dire :
Les matrices A et B étant tridiagonales, une implémentation efficace doit stocker seulement les trois diagonales, dans trois tableaux différents. On écrit donc le schéma de Crank-Nicolson sous la forme :
Les coefficients du schéma sont ainsi stockés dans des tableaux à N éléments a,b,c,d,e,f,s. On remarque toutefois que les éléments a0, cN-1, d0 et fN-1 ne sont pas utilisés.
Le système tridiagonal à résoudre à chaque pas de temps est :
où l'indice du temps a été omis pour alléger la notation. Le second membre du système se calcule de la manière suivante :
Le système tridiagonal s'écrit :
La méthode d'élimination de Gauss-Jordan permet de résoudre ce système de la manière suivante.
Les deux premières équations sont :
b0 est égal à 1 ou -1 suivant le type de condition limite. On divise la première équation par ce coefficient, ce qui conduit à poser :
La première élimination consiste à retrancher l'équation obtenue multipliée par à la seconde :
On pose alors :
On construit par récurrence la suite suivante :
Considérons la kième équation réduite et la suivante :
La réduction de cette dernière équation est :
ce qui justifie la relation de récurrence définie plus haut.
Pour finir, voyons les deux dernières équations :
La dernière équation réduite donne :
c'est-à-dire :
Il reste à calculer les en partant du dernier par la relation :
Les coefficients des diagonales sont stockés dans trois tableaux (à N éléments) a,b et c dès que les conditions limites et les pas sont fixés. Les tableaux β et γ (relations 1 et 2) sont calculés par récurrence avant le départ de la boucle d'itération. À chaque pas de l'itération (à chaque instant), on calcule par récurrence la suite (relation 3) pour k variant de 0 à N-1, et enfin la suite (relation 4) pour k variant de N-1 à 0. En pratique, dans cette dernière boucle, on écrit directement dans le tableau utilisé pour stocker les .