Vous êtes sur la page 1sur 20

TP3 Equation du transport

1- Déterminons la solution exacte.


Nous considérons le problème suivant:

∂t u + c∂x u = 0, x ∈]0, L[, t ∈]0, T [,


u(0, t) = e−t , t ∈]0, T [,
u(x, 0) = 0, x ∈]0, L[.

c ∈ R+ est une constante.


Déterminons la solution de ce problème.

Nous allons nous baser sur la méthode des caractéristiques pour résoudre cette équation aux
dérivées partielles.
On cherche une fonction
u : (x, t) ∈ R × R+ ↦ u(x, t) ∈ R
qui satisfait :

∂t u(x, t) + c∂x u(x, t) = 0 (1)

Nous cherchons ainsi une courbe caractéristique ∑ = (x(t), t) le long de laquelle notre
équation aux dérivées partielles du 1er ordre se réduit à une équation différentielle ordinaire.
Ainsi, toute solution de (1) est constante le long de ∑.

∂u ′ ∂u
On pose u(x(t), t) = 0 et dx
dt = c1 (c1 une constante réelle) donc ∂x x (t) + ∂t × 1 = 0.

∑ est une courbe caractéristique de (1) si x′ (t) = c donc x(t) = c1 t + x0 .


On a u(x0 , 0) = u0 (x0 ) = u(x, t) or x(t) = c1 t + x0 et donc x0 = x − ct.
On en conclut l'expression u(x, t) = (x − ct).

Nous distinguons alors deux cas possibles pour définir la solution exacte:

Le premier cas, lorsque xc >0:

u(x, t) = u0 (x − ct) = 0
et le second cas lorsque xc < 0:
x x
u(x, t) = g(t0 ) = g(t − ) = exp( − t)
c c

2- Écrivons le schéma aux différences finies décentrées


permettant de calculer numériquement la solution de (1)
= L/N et pour pas de temps: ∆t.
Prenons pour pas de discrétisation : ∆x
On pose: xi = i∆x avec i ∈ Z et tn = n∆t.

On a:
∥u(⋅, t)∥2 = ∥u0 ∥2
et on cherche une solution approchée qu'on notera un n
i tel que: ui ≃ u(i∆x, n∆t).
+∞
On a: ∥u∥l2 (Z) = en (u) = h ∑i=0 ∣uni ∣2 .

On veut construire un schéma numérique qui permette de calculer un+1


i à partir de un
i et
uni−1 et qui vérifie en (u) ≤ en−1 (u).

On a:

un+1 − uni ∂u
i
≃ (xi , tn )
∆t ∂t

et

uni+1 − uni−1 ∂u
≃ (xi , tn )
2∆x ∂x
Ainsi:

∂u u(xi+1 , tn ) − u(xi−1 , tn )
(xi , tn ) = + O(∆x2 )
∂x 2∆x
uni − uni−1 u(xi , tn ) − u(xi−1 , tn ) ∂u
= = (xi , tn ) + O(∆t)
∆t ∆t ∂x
On obtient le schéma numérique décentré suivant:
un+1 − uni uni − uni−1 c∆t n
i
+c = 0 ⟹ un+1
i = u n
i − (ui − uni−1 )
∆t ∆x ∆x

3- Stabilité du schéma numérique.


Pour étudier la stabilité L2 du schéma, on procède par analyse de Fourier:

Un schéma à deux niveaux peut s'écrire de la manière suivante :

k k
∑ cm un+1
j+m = ∑ dm unj+m
m=−k m=−k

où k ∈ N, cm et dm sont des constantes. On suppose que un ∈ L2 (Z).

On définit à présent : v n : R → R par v n (x) = unj pour x ∈ [(j − 12 )△x, (j + 12 )△x].

Alors v n∈ L2 (R) et sa transformée de Fourier est définie par : Fv n (ξ) =



∫−∞ v n (x)exp(−iξx)dx.

Et d'après le théorème de Plancherel, on a : ∥Fv n ∥L2 (Z) = △x∥un ∥l2 (R) .

Donc, l'étude de la stabilité l2 de ce schéma correspond à l'étude de la continuité de


l'application v 0 → Fv n dans L2 (R).

On a : v n (x + m△x) = unj+m pour x ∈ [(j − 12 )△x, (j + 12 )△x].

Or, F[v n (x + m△x)](ξ) = exp(−iξm△x)F[v n (x)](ξ).

Ainsi, par la transformée de Fourier le schéma peut s'écrire :

k k
∑ cm Fv n+1 iξm△x
(ξ)e = ∑ dm Fv n (ξ)eiξm△x
m=−k m=−k

Ainsi

Fv n+1 (ξ) = g(ξ, △x, △t)Fv n (ξ)

où g est le coefficient d'amplification donné par :


k
∑m=−k dm exp(−iξm△x)
g(ξ, △x, △t) = k
∑m=−k cm exp(−iξm△x)

Ainsi par transformation de Fourier, le schéma décentré à gauche peut s'écrire :

c∆t
Fv n+ (ξ) = (1 − c (1 − exp(−iξ∆x))Fv n (ξ)
∆x
Le critère de Von Neumann nécessaire et suffisant pour la stabilité en norme L2 (Z) d'un
schéma à deux niveaux est :

sup ∣g(ξ, △x, △t)∣ ≤ 1 + M △t


ξ∈R

où M est indépendant de △x et △t.

Le coefficient d'amplification pour ce schéma décentré à gauche est donc g(ξ; ∆x, ∆t) =
(1 − ∆x (1
c c∆t − cos(ξ∆x)).

On a ∣g(ξ; ∆x, ∆t)∣2 = (1 − ∆x (1


c∆t
− cos(ξ∆x)))2 + ( c∆t 2 2
∆x ) sin(ξ∆x) = 1 − 2 ∆x (1 −
c∆t

∆x )(1 − cos(ξ∆x)).
c∆t

Et 1 − cos(ξ∆x) ≥ 0, puisque c∆t


∆x > 0, on distingue les cas suivants:

si c∆t
∆x ≤ 1 donc supξ∈R ∣g(ξ; ∆x, ∆t)∣ = 1,

si c∆t
∆x > 1 donc supξ∈R ∣g(ξ; ∆x, ∆t)∣ = 1 − 2 c∆t
∆x (1 − ∆x ).
c∆t

On en déduit que le schéma upwind est stable dans L2 si c∆t


∆x ≤ 1.
∣c∣∆t
Le schéma decentré à gauche est stable dans L∞ si ∆x ≤ 1.

Il peut se réecrire de la manière suivante :

c∆x n c∆t n
un+1 = ui−1 + (1 − )u
i
∆t ∆x i
Sous cette forme le schéma décentré à gauche est une combinaison convexe si la condition
C.F.L (0 ≤ ∣c∣∆t ≤ ∆x) est satisfaite. Il vérifie le principe du maximum discret, ce dernier a
pour conséquence un contrôle des oscillations numériques.

On dit qu'un schéma est précis d'ordre p en x et précis d'ordre q en t si l'erreur de troncature
est de l'ordre O((∆x)p + (∆t)q ).

L'erreur de troncature correspond à l'écart entre l'équation approchée et l'équation exacte,


calculée pour la solution exacte u(x, t). Dans notre cas, on a:

∣c∣ ∂2u
ErrT = (−∆x + ∣c∣∆t) 2 + O((∆x)2 + (∆t)2 )
2 ∂x
Donc, le schéma est précis d'ordre 1 seulement ainsi il converge.

4- Description du Programme Rust : Schéma aux


différences finies de type Upwind
Le programme Rust est composé d'un fichier, main.rs, qui contient le code source du
programme. Ce fichier est composé d'une fonction sol_exacte(x: f64, t: f64) qui
permet de calculer la solution exacte de l'équation du transport. Elle prend en paramètres les
variables x, t.

fn sol_exacte(x: f64, t: f64) -> f64 {


let exp=f64::exp;
if x>c*t {
return 0.;
}
if x<c*t {
return exp(-t+x/c);
}
return 0.;
}

La fonction sol_exacte(x: f64, t: f64) est appelée dans le main() qui permet de
calculer la solution numérique de l'équation du transport.

La première étape est l'initialisation des variables nx , length , tmax , c , h , cfl , dt qui
correspondent respectivement au nombre de points de discrétisation, la longueur de la barre,
le temps final, la vitesse de propagation, la taille d'un pas de discrétisation, le nombre de
Courant, et le pas de temps.

On pose dt = h *cfl / c pour assurer la stabilité du schéma numérique.


( cfl = c* dt / h )
On initialise les vecteurs xi , uex , unow_d , unext_d qui correspondent respectivement
aux points de discrétisation, la solution exacte, la solution numérique au temps n, la solution
numérique au temps n+1.
La taille de ces vecteurs est nx+1 car nous avons nx points de discrétisation donc il nous
faut un point de plus pour calculer la solution numérique au temps n+1 à partir de la solution
numérique au temps n.

La boucle suivante :

for i in 0..nx + 1 {
unow_d[i] = sol_exacte(xi[i], 0.);
}

permet d'initialiser la solution numérique au temps n avec la solution exacte au temps n=0.
(car nous voulons dans la boucle while calculer la solution numérique au temps n+1 à partir de
la solution numérique au temps n)

Tant que le paramètre temps t est inférieur au temps final tmax , on calcule la solution
numérique au temps n+1 à partir de la solution numérique au temps n et parallèlement la
solution exacte au temps n+1 à partir de la solution exacte au temps n.

while t < tmax {

uex[0] = sol_exacte(0., t);


for i in 1..nx + 1 {
unext_d[i] = unow_d[i] - c * dt / h * (unow_d[i] - unow_d[i - 1]);
uex[i]=sol_exacte(xi[i],t);
}
unext_d[0] = sol_exacte(0., t);
t += dt;
ic += 1;
unow_d = unext_d.clone();

Les lignes uex[0] = sol_exacte(0., t); et unext_d[0] = sol_exacte(0., t);


permettent d'imposer la condition de bord.
On incrémente le paramètre temps t de dt à chaque itération de la boucle while.

Un exemple de résultat obtenu avec le programme Rust pour les paramètres suivants:
nx = 1000
length = 1.0
tmax = 0.5
c = 1.0
cfl = 0.5
dt = length / nx = 0.0005

Le graphe ci-dessous représente la solution exacte en bleu et la solution numérique en rouge.

On remarque que la solution numérique est proche de la solution exacte.

On rappelle que la condition C.F.L est vérifiée si cfl est inférieur à 1.

Pour vérifier que le schéma est instable lorsque la condition de cfl n’est pas vérifiée, on
peut mettre cfl = 1.5 au lieu de cfl = 0.5 dans le programme Rust.

On obtient alors le graphe ci-dessous :


L'instabilité du schéma correspond sur le graphique à la divergence de la courbe de la
solution numérique.

5- Vérifions numériquement la convergence du schéma.


Pour calculer la norme L1 et L2, on va utiliser la fonction norme_l1 et norme_l2 qui sont
définies dans le fichier main.rs . Ces fonctions prennent en paramètre les vecteurs uex et
unow_d qui correspondent respectivement à la solution exacte et la solution numérique. Elles
retournent la norme L1 et L2 de la solution numérique par rapport à la solution exacte.
fn norme_l1(uex: &Vec<f64>, unow_d: &Vec<f64>) -> f64 {
let mut somme = 0.;
for i in 0..uex.len() {
somme += (uex[i] - unow_d[i]).abs();
}
somme / uex.len() as f64
}

fn norme_l2(uex: &Vec<f64>, unow_d: &Vec<f64>) -> f64 {


let mut somme = 0.;
for i in 0..uex.len() {
somme += (uex[i] - unow_d[i]).powi(2);
}
(somme / uex.len() as f64).sqrt()
}

L'objectif de cette question est de vérifier la convergence du schéma numérique en calculant


la norme L1 et L2 de la solution numérique par rapport à la solution exacte pour diverses
finesses de maillage.
Pour cela, nous allons tracer le graphe de la norme L1 et L2 de u_ex et unow_d en fonction
du nombre de points de discrétisation nx .

On crée dans un premier temps un vecteur nx_tab qui contiendra les valeurs de nx pour
lesquelles on veut calculer la norme L1 et L2.

On crée ensuite un vecteur norme_l1_tab qui contiendra les valeurs de la norme L1 et un


vecteur norme_l2_tab qui contiendra les valeurs de la norme L2.

let nx_array = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000];

let abs: Vec<f64> = [1., 2. , 3., 4., 5., 6., 7., 8., 9.].to_vec();

let mut normel1_tab: Vec<f64> = vec![0.; nx_array.len()];


let mut normel2_tab: Vec<f64> = vec![0.; nx_array.len()];

Ensuite, dans une boucle qui parcourt tous les éléments du tableau nx_array on calcule
u_ex et unow_d pour chaque nombre de points de discrétisation. On calcule ensuite la
norme L1 et L2 de u_ex et unow_d et on les stocke dans les vecteurs dédiés.

normel1_tab[ic_nx] = norme_l1(&unow_d, &uex);


normel2_tab[ic_nx] = norme_l2(&unow_d, &uex);
( ic_nx est un compteur qu'on incrémente à chaque itération de la boucle while.)

plot1d(&abs, &normel1_tab, &normel2_tab);

( abs est un vecteur qui permet de tracer le graphe, il contient les abscisses.)

On appelle ensuite la fonction plot1d qui prend en paramètre les vecteurs temp et
normel1_tab et normel2_tab et qui trace le graphe de la norme L1 et L2 en fonction du
nombre de points de discrétisation nx .

Voici le graphe obtenu :

On constate que la norme L1 tracée en bleu et la norme L2 en rouge de la solution numérique


convergent vers 0 lorsque le nombre de points de discrétisation augmente. Nous pouvons
interpréter ce résultat comme une preuve de la convergence du schéma numérique.

6- Vérifions numériquement l'instabilité inconditionnelle du


schéma centré.
Nous allons vérifier numériquement que le schéma centré est inconditionnellement instable.

Le programme est sensiblement le même que pour le schéma décentré nous ajoutons dans le
while la boucle for suivante qui va cette fois jusqu'à nx au lieu de nx+1 :

for i in 1..nx {
unext_c[i] = unow_c[i] - c * dt / (2. * h) * (unow_c[i + 1] - unow_c[i - 1]);
uex[i]=sol_exacte(xi[i],t,c);
}

On obtient alors les graphe ci-dessous avec comme paramètres de simulation:

let length = 1.;


let tmax = 0.5;
let c = 1.5;
let nx = 100;

Pour cfl = 0.5 :


Pour cfl = 1. :
Pour cfl = 1.5 :
Le schéma centré est inconditionnellement instable.
En effet, on observe que la solution numérique diverge peu importe la valeur de cfl .

7- Schéma de Lax-Wendrof. Quelle est sa condition de


stabilité L2 ? La vérifier numériquement. Vérifier aussi
numériquement que ce schéma n’est pas stable dans L∞ .
Pour programmer le schéma de Lax-Wendrof. Le principe est similaire aux schémas
précédents.

Dans le while qui parcourt tous les points de discrétisation nx on souhaite calculer unext_l
et unow_l .
On ajoute donc la boucle for suivante, elle va de 1 à nx (car on a besoin de calculer
unow_l[i + 1] ):
for i in 1..nx {
unext_l[i] = unow_l[i] - c * dt / (2. * h) * (unow_l[i + 1] - unow_l[i - 1])
+ c * c * dt * dt / (2. * h * h) * (unow_l[i + 1] - 2. * unow_[i] + unow_l[i - 1]);
uex[i] = sol_exacte(xi[i], t, c);
}

Le schéma de Lax-Wendrof défini par :

△t △t2 2 n
un+1
i = uni − n n
c(ui+1 − ui−1 ) + 2
c (ui+1 − 2uni + uni−1 )
2△x 2△x

j une approximation de de u(xj , tn ), on note


est un schéma à deux niveaux. En effet pour un
un = (unj )j∈Z le vecteur des valeurs de u aux noeuds du maillage et EΔ ∈ RN ×N la
matrice qui à un associe un+1 .

Pour le schéma de Lax-Wendrof, le coefficient d'amplification est le suivant :

△t △t2 2
g(ξ, △x, △t) = 1 − c sin(ξ△x) + 2
c (cos(ξ△x) − 1)2
2△x 2△x
On rappelle que le critère de Von Neumann nécessaire et suffisant pour la stabilité en norme
L2 (Z) d'un schéma à deux niveaux est :

sup ∣g(ξ, △x, △t)∣ ≤ 1 + M △t


ξ∈R

où M est indépendant de △x et △t.


2 2
△t △t 2 △t
Dans notre cas, si c △x ≥ 1, on a : supξ∈R ∣g(ξ, △x, △t)∣ = 1 + 4c2 △x 2 (c △x2 − 1).

△t
Et si c △x < 1, on a : supξ∈R ∣g(ξ, △x, △t)∣ = 1.
△t
On en conclut donc que le schéma de Lax-Wendrof est stable en norme L2 (Z) si c △x < 1.

Vérifions numériquement la stabilité L2 du schéma de Lax-Wendrof.

On trace la solution exacte et la solution approchée pour deux conditions CFL différentes
( nx=100 et tmax=0.5 ):

△t
Pour c △x = 0.5 nous avons :
△t
et pour c △x = 1.5 nous avons :
△t
On constate que pour c △x = 0.5, la solution approchée est stable, en revanche pour l'autre
C.F.L. elle diverge. Ceci conforte notre analyse théorique.

À présent pour vérifier numériquement que le schéma n'est pas stable en norme L∞ on crée
une fonction norme_linf . Cette fonction prend en paramètres uex et unow_l qui sont les
vecteurs de la solution exacte et de la solution approchée. Elle renvoie la norme L∞ de la
différence entre ces deux vecteurs.
fn linf_norm(uex: &[f64], unow_l: &[f64]) -> f64 {
let mut m = 0.;
for i in 0..uex.len() {
let err = (uex[i] - unow_l[i]).abs();
if err > m {
m = err;
}
}
m
}

On utilise le même procédé que pour les deux normes L1 et L2 pour récupérer les valeurs de
la norme L∞ pour différentes valeurs de nx .

Enfin, on trace la norme L∞ de la différence entre la solution exacte et la solution approchée


pour des conditions CFL différentes ( nx=1000 et tmax=0.5 ):

△t
Pour c △x = 0.5 nous avons :
△t
Pour c △x = 1. nous avons :

△t
Pour c △x = 1.5 nous avons :
On observe que peu importe la condition C.F.L utilisée, la norme L∞ de la différence entre la
solution exacte et la solution approchée diverge. Ceci confirme que le schéma de Lax-
Wendrof n'est pas stable en norme L∞ .

Vous aimerez peut-être aussi