Modèle discret

Idée derrière la MEF

L’idée de base derrière la méthode des éléments finis est l’approche classique consistant à décomposer un problème compliqué en une multitude de petits problèmes beaucoup plus simples à résoudre :

  1. Pour calculer chaque terme intégral de la formulation faible, nous allons les décomposer sur une partition du domaine d’étude qu’on appelle le maillage.
  2. Sur chaque élément de ce maillage nous allons définir des fonctions simples (polynomiales) qui nous permettront de générer un sous-espace de dimension finie de l’espace fonctionnel auquel appartient notre inconnue (qui, lui, est de dimension infinie).
  3. Nous calculerons alors la projection de la solution de la forme faible dans cet espace discret qui sera alors la meilleure approximation de la solution sur le maillage.

Exemple fil rouge (Running Example)

Pour illustrer les différents aspects abordés dans la suite, on utilisera l’exemple simple donné par la figure suivante :

Représentation de notre problème exemple

Nous avons donc un problème de Poisson avec conditions de Dirichlet et Neumann, dont la formulation forte peut s’écrire :

$$\left\{\begin{aligned} \text{div} \left({\bf grad}\,u \right) + \beta &= 0, ~ \text{dans} ~ \Omega \\ u|_{\Gamma_d} &= 0 \\ \partial_n u|_{\Gamma_n} &= \gamma = 1 \end{aligned}\right.$$

avec $\beta$ définie par morceaux par :

$$\left\{\begin{aligned} \beta &= 1 ~ ~ \text{ dans } ~ ~ \Omega_s \\ \beta &= 0 ~ ~ \text{ dans } ~ ~ \Omega/\Omega_s \end{aligned}\right.$$

Et d’après la section précédente, la formulation faible est :

$$\begin{aligned}&\text{Trouver} ~ u \in \text{H}_0({\bf grad},\Omega) = \left\{ u \in \text{H}({\bf grad},\Omega) : u|_{\Gamma_d} = 0\right\} ~ \text{tel que :}\\\\ &\forall v \in \text{H}_0({\bf grad},\Omega), \iiint_{\Omega} {\bf grad}\,u \cdot{\bf grad}\,v ~\text{d}\Omega - \iiint_{\Omega_s} v ~ \text{d}\Omega - \iint_{\Gamma_n} v ~ \text{d}\Gamma = 0\end{aligned}$$

Soit :

$$\boxed{\begin{aligned}&\text{Trouver} ~ u \in \text{H}_0({\bf grad},\Omega) ~\text{tel que :}\\\\ &\forall v \in \text{H}_0({\bf grad},\Omega), ~ ~ \underbrace{\left({\bf grad}\,u,{\bf grad}\,v\right)_{\Omega} }_{a(u,v)}+ \underbrace{\left(-1,v\right)_{\Omega_s} + \left<-1,v\right>_{\Gamma_n}}_{-L(v)} = 0\end{aligned}}$$

$\rightsquigarrow$ C’est cette dernière que nous résoudrons par la suite.

Sous-sections de Modèle discret

Méthode de Galerkin et éléments finis

Méthode de Galerkin

Nous avons vu dans la section précédente que la forme faible de chaque problème considéré pouvait se mettre sous la forme :

$$\left\{\begin{aligned}~ &\text{Trouver}~ u \in V ~ \text{tel que :}\\ &a(u,v) = L(v),~ ~ \forall\,v \in V\end{aligned}\right.$$

$V$ étant de dimension infinie, un tel problème est particulièrement difficile à résoudre. La méthode de Galerkin consiste à résoudre la formulation faible dans un sous-espace $V_h \subset V$ de dimension finie $n_h$ possédant les mêmes propriétés, soit :

$$\left\{\begin{aligned} ~ &\text{Trouver}~ u_h \in V_h ~ \text{tel que :} \\ &a(u_h,v_h) = L(v_h),~ ~ \forall\,v_h \in V_h\end{aligned}\right.$$

où $u_h$ est une solution approchée de la solution exacte $u$.

L’idée est de résoudre cette formulation à partir d’une base $(\varphi_1,\varphi_2,\dots,\varphi_{n_h})$ de $V_h$. En décomposant $u_h$ dans cette base, on a :

$$u_h = \sum\limits_{j=1}^{n_h} u_j\,\varphi_j$$

Le principe de la méthode de Galerkin est alors d’utiliser les fonctions de base $\varphi_i$ comme fonctions test dans la formulation faible. Ainsi :

$$\begin{aligned}\forall i \in [\![1,n_h]\!]~ ,~ &a\left(\sum\limits_{j=1}^{n_h} u_j\,\varphi_j,\varphi_i\right) = L(\varphi_i) \\ & \sum\limits_{j=1}^{n_h} u_j\,a(\varphi_j,\varphi_i) = L(\varphi_i)\end{aligned} $$

Soit :

$$\boxed{\forall i \in [\![1,n_h]\!]~ ,~ \sum\limits_{j=1}^{n_h} a(\varphi_i,\varphi_j)\,u_j = L(\varphi_i)}$$

En définissant les vecteurs ${\bf U_h} = \left( u_i \right)_{1\leq i \leq n_h}$ et ${\bf B_h} = \big( L(\varphi_i) \big)_{1\leq i \leq n_h}$, et la matrice ${{\bf A_h} = \big( a(\varphi_i,\varphi_j) \big)_{1\leq i,j\leq n_h}}$, le problème peut se mettre sous la forme matricielle :

$$\boxed{{\bf A_h} \, {\bf U_h} = {\bf B_h}}$$

En résolvant ce système linéaire, on obtient alors les composantes $u_i$ de la solution approchée $u_h$ dans la base $(\varphi_i)_{1\leq i\leq n_h}$.

$\rightarrow$ La méthode des éléments finis permet d’appliquer ce principe de résolution.

Qu’est-ce qu’un élément fini ?

On appelle élément fini le triplet $(K,P_K,\Sigma_K)$, où :

  • $K$ est un domaine de l’espace appelé élément géométrique (généralement de forme simple : un segment, un triangle, un quadrangle, un tétraèdre, un hexaèdre, une pyramide, un prisme) ;
  • $P_K$ est un espace fonctionnel de dimension finie $n_K$, défini sur $K$ engendré par ce qu’on appelle les fonctions de base $p_i, 1 \leq i \leq n_K$ ;
  • $\Sigma_K$ est un ensemble de $n_K$ degrés de liberté représentés par $n_K$ fonctionnelles (formes) linéaires $\sigma_i,~ 1 \leq i \leq n_K,$ définies sur l’espace $P_K$ et à valeurs dans $\mathbb{R}$.

De plus, il faut qu’il existe une unique fonction de $P_K$ prenant des valeurs données aux degrés de liberté de $\Sigma_K$ : cette dernière condition définit l’unisolvance de l’élément fini $(K,P_K,\Sigma_K)$.

Nous allons maintenant voir comment mettre en place la méthode basée sur ces éléments.

Maillage

Intéressons nous tout d’abords aux éléments géométriques $K$ obtenus par discrétisation du domaine d’étude $\Omega$, ce qu’on appelle le maillage. Le domaine (polyédrique) est alors partitionné avec le type d’entités élémentaires choisi (triangle, quadrangle, tétraèdre, hexaèdre, etc…).

Le maillage doit être conforme, c’est-à-dire :

  • Les éléments doivent recouvrir la fermeture $\overline{\Omega}$ de $\Omega$.
  • L’intersection de deux éléments est soit l’ensemble vide, soit un sommet, soit une arête partagée.

Nous pouvons illustrer cela sur un exemple :

Maillage conforme Maillage non conforme
Maillage conforme Maillage conforme Maillagenon-conforme Maillagenon-conforme

Dans la suite, nous utiliserons le logiciel libre de maillage par éléments finis Gmsh développé par C. Geuzaine et J-F. Remacle.

Génération d’un maillage

Pour pouvoir discrétiser un problème donné, nous devons tout d’abord définir ses aspects purement géométriques. C’est-à-dire créer toutes les entités élémentaires :

  • les points, qui permettent de définir :
  • les lignes (segments, arcs de cercles, voire courbes), qui permettent de définir :
  • les surfaces (planes ou courbes), qui permettent de définir :
  • les volumes.

Sur notre cas d’étude, on obtient par exemple :

Géométrie de notre exemple Géométrie de notre exemple

Après avoir défini des tailles caractéristiques d’éléments et/ou discrétiser les lignes, on peut mailler notre géométrie. Ci-dessous, deux exemples :

Triangulaire Quadrangulaire
Maillage 1 Maillage 1 Maillage 2 Maillage 2

Pour information, je vous donne en exemple les scripts permettant de générer ces maillages. Par habitude, j’utilise deux fichiers :

  • data.geo : servant à définir les paramètres qui pourront être partagés avec le solveur,
  • poisson.geo : contenant la création de la géométrie.
/* 
	Fichier data.geo contenant les parametres 
*/

// Parametres geometriques
Rd = 1;
Rs = 0.15*Rd;
xs = 0.4*Rd;  
ys = 0.4*Rd;
alphaN = Pi/6;

// Parametres maillage 
finesse = 2;
nec = 4*finesse;
lcd = Rd/nec;
lcs = Rs/nec*2;
neN = 2*nec;
typele = 1;  // <=1 : triangles
             // > 1 : quadrangles
             
// Numeros regions physiques
DISQUE = 1000;
SOURCE = 1001;
DIRICHLET = 2000;
NEUMANN = 2001;
/*
	Fichier poisson.geo contenant la creation de 
	la geometrie de notre petit probleme de Poisson
*/

// Lecture des parametres
Include "data.geo" ;

// Creation des points
Point(1) = {0,0,0,lcd};  // centre domaine
Point(2) = {Rd/Sqrt[2],Rd/Sqrt[2],0,lcd};
Point(3) = {-Rd*Cos[alphaN/2],Rd*Sin[alphaN/2],0,lcd};
Point(4) = {-Rd*Cos[alphaN/2],-Rd*Sin[alphaN/2],0,lcd};
Point(5) = {Rd/Sqrt[2],-Rd/Sqrt[2],0,lcd};
Point(6) = {xs,ys,0,lcs}; // centre Omega_s
Point(7) = {xs+Rs,ys,0,lcs};
Point(8) = {xs,ys+Rs,0,lcs};
Point(9) = {xs-Rs,ys,0,lcs};
Point(10) = {xs,ys-Rs,0,lcs};

// Creation des lignes
Circle(1) = {2,1,3}; 
Circle(2) = {3,1,4};
Circle(3) = {4,1,5}; 
Circle(4) = {5,1,2};
Circle(5) = {7,6,8}; 
Circle(6) = {8,6,9};
Circle(7) = {9,6,10}; 
Circle(8) = {10,6,7};

// Discretisation de la ligne Gamma_n
Transfinite Line {2}  = neN+1 Using Progression 1.0;

// Surfaces
Line Loop(1) = {1,2,3,4};
Line Loop(2) = {5,6,7,8};
Plane Surface(1) = {2};     // Omega_s
Plane Surface(2) = {1,-2};  // Omega

// Maillage en quadrangles (si voulu)
If (typele > 1)  
  Recombine Surface '*';
EndIf

Physical Surface(DISQUE) = {2};
Physical Surface(SOURCE) = {1};
Physical Line(DIRICHLET) = {1,3,4};
Physical Line(NEUMANN) = {2};

// Un peu de cosmetisme
Color Red { Surface{1}; }
Color White { Surface{2}; }
Color Blue { Line{2};}
Color Black { Line{1,3,4,5,6,7,8};}

En plus des fonctions basiques de création des entités élémentaires, Gmsh possède des fonctions plus évoluées : transformations (symétries, translations, rotations, dilatations), extrusions. De plus, il intègre depuis quelques temps un noyau supplémentaire basé sur le moteur CAO OpenCascade permettant de créer directement des objets 2D ou 3D, d’effectuer des opérations booléennes, ou de manipuler des splines.

Remarque

Pour plus d’informations sur le logiciel, vous pouvez :
$\rightarrow$ consulter le site officiel et son wiki ;
$\rightarrow$ suivre un très bon tutoriel fait par B. Thierry (ENSEM, promo 2007).

Exemples

Ci-après, vous trouverez des exemples de maillages utilisés dans le cadre de travaux de mon équipe de recherche au laboratoire GREEN.

En 2D

Machine à courant continu Ventouse magnétique
MCC MCC Electromaimant Electromaimant

En 3D

Accouplements magnétiques (maillages structurés) Machines synchrones à griffes (mix structuré / non-structuré)
Coupleur à Aimants Coupleur à Aimants Machine Geoffrey Machine Geoffrey
Coupleur à induction Coupleur à induction Machine Dominique Machine Dominique

$~$

Les exemples ci-dessus sont issus des thèses de :

  • G. Devornique (ENSEM, promo 2013), pour l’alterno-démarreur synchrone à griffes ;
  • B. Ristagno (ENSEM, promo 2016), pour la machine à courant continu ;
  • D. Giraud (ENSEM, promo 2017), pour la machine synchrone axiale à griffes.
Information

Pour plus d’informations, ou si vous envisagez la possibilité de faire une thèse, n’hésitez pas à me contacter, ainsi que mes collègues : les Professeurs N. Takorabet ou D. Netter.

Autres exemples 3D

On peut également utiliser des maillages beaucoup plus complexes, comme par exemple les deux ci-dessous qui me permettent de calculer des courants induits dans des têtes humaines (par exemple pour des travailleurs opérant à proximité de sources basse fréquence comme des pinces à souder) :

John Doe Jane Doe
John Doe John Doe Jane Doe Jane Doe

$\boldsymbol{\rightarrow}$ Voir même un corps humain complet (oui, j’ai un peu galéré…) :

John en entier (avec tous les organes)
Maillage d’n corps complet Maillage d’n corps complet

Fonctions de base sur éléments nodaux

Maintenant que nous savons créer le maillage (noté $\mathcal{M}_h$), nous allons nous intéresser à la définition des fonctions qui permettront de constituer la base de l’approximation discrète $V_h$ de $V$ (fonctions de base).

Remarque

Par souci de simplicité, nous ne nous intéresserons, dans un premier temps, qu’aux éléments nodaux permettant d’approximer $\text{H}^1_0(\Omega) \left(= \text{H}_0({\bf grad},\Omega)\right).$ On les appelle éléments de Lagrange. Pour clarifier un peu plus les choses, nous ne considérerons tout d’abord que des éléments s’appuyant sur des fonctions de base linéaires (polynômes d’ordre 1) permettant une approximation linéaire par morceaux de la fonction inconnue. On les appelle les éléments $\mathbf{P_1}$ (ou $\mathbf{Q_1}$ pour les quadrangles).

Éléments de référence

En fait, nous allons définir les fonctions de base sur ce qu’on appelle un élément de référence dont la forme géométrique est fixe et prédéfinie.

En 1D

En dimension 1, les éléments sont des segments et l’élément de référence est le segment $[-1,1]$.

En 2D

En dimension 2, nous pouvons donner le triangle et le quadrangle de référence :

  • pour le triangle, c’est celui de sommets : ${\bf n_1}=(0,0)$, ${\bf n_2}=(1,0)$ et ${\bf n_3} = (0,1)$. On peut le paramétrer par : $$\Delta_r = \left\{ (u,v) \in \mathbb{R}^2 : 0 \le u \le 1, 0 \le v\le 1-u\right\}$$
  • pour le quadrangle, c’est celui de sommets : ${\bf n_1} = (-1,-1)$, ${\bf n_2} = (1,-1)$, ${\bf n_3} = (1,1)$ et ${{\bf n_4} =(-1,1)}$. On peut le paramétrer par : $$\text{Q}_r = \left\{ (u,v) \in \mathbb{R}^2 : -1 \le u \le 1, -1 \le v \le 1\right\}$$

Leur représentation graphique est donnée ci-dessous.

Éléments de référence en 2D

En 3D

Nous nous contenterons de donner le tétraèdre et l’hexaèdre de référence :

  • pour le tétraèdre, c’est celui de sommets : ${\bf n_1} = (0,0,0)$, ${\bf n_2} = (1,0,0)$, ${\bf n_3} = (0,1,0)$ et ${{\bf n_4} =(0,0,1)}$. On peut le paramétrer par : $$\text{T}_r = \left\{ (u,v,w) \in \mathbb{R}^3 : 0 \le u \le 1, 0 \le v\le 1-u, 0 \le w\le 1-u-v\right\}$$
  • pour l’hexaèdre, c’est celui de sommets : ${\bf n_1} = (-1,-1,-1)$, ${\bf n_2} = (1,-1,-1)$, ${\bf n_3} = (1,1,-1)$, ${\bf n_4} = (-1,1,-1)$, ${\bf n_5} = (-1,-1,1)$, ${\bf n_6} = (1,-1,1)$, ${\bf n_7} = (1,1,1)$ et ${\bf n_8} = (-1,1,1)$. On peut le paramétrer par : $$\text{H}_r = \left\{ (u,v,w) \in \mathbb{R}^3 : -1 \le u \le 1, -1 \le v \le 1, -1 \le w \le 1\right\}$$

Et leur représentation graphique est donnée ci-dessous.

Éléments de référence en 3D

Fonctions de base sur éléments de référence

Sur ces élément de références, nous pouvons définir des fonctions linéaires valant 1 sur un sommet (un nœud) et 0 sur les autres. Dans ce cas, on fera une approximation linéaire par morceaux de notre fonction inconnue. Ces fonctions seront notées $p_i$ pour $i \in [\![1,n_K]\!]$.

Nous aurons donc autant de fonctions de base que de sommets $n_K$ de l’élément de référence.

Cas du triangle

Dans le cas du triangle de référence, ces fonctions sont données par la table ci-dessous :

Nœud $i$ Fonction de base $p_i (u,v)$
1 $p_1 (u,v) = 1 - u - v$
2 $p_2 (u,v) = u$
3 $p_3 (u,v) = v$

Une représentation graphique est donnée par : Fonctions de base Langrange sur triangle Fonctions de base Langrange sur triangle

On peut également les tracer en surélevé :

$p_1$ $p_2$ $p_3$
phi_1 phi_1 phi_2 phi_2 phi_3 phi_3

Cas du quadrangle

Dans le cas du triangle de référence, ces fonctions sont données par la table ci-dessous :

Nœud $i$ Fonction de base $p_i (u,v)$
1 $\displaystyle p_1 (u,v) = \frac{(1-u)(1-v)}{4}$
2 $\displaystyle p_2 (u,v) = \frac{(1+u)(1-v)}{4}$
3 $\displaystyle p_3 (u,v) = \frac{(1+u)(1+v)}{4}$
4 $\displaystyle p_4 (u,v) = \frac{(1-u)(1+v)}{4}$

Une représentation graphique est donnée par : Fonctions de base Langrange sur quandrangle Fonctions de base Langrange sur quandrangle

On peut également les tracer en surélevé :

$p_1$ $p_2$ $p_3$ $p_4$
phi_1 phi_1 phi_2 phi_2 phi_3 phi_3 phi_4 phi_4

Cas du tétraèdre

Dans le cas du tétraèdre de référence, ces fonctions sont données par la table ci-dessous :

Nœud $i$ Fonction de base $p_i (u,v,w)$
1 $p_1 (u,v,w) = 1 - u - v - w$
2 $p_2 (u,v,w) = u$
3 $p_3 (u,v,w) = v$
4 $p_4 (u,v,w) = w$

Et une représentation graphique de $p_1$ est donnée ci-dessous :

p1 sur tétraèdre p1 sur tétraèdre

Cas de l’hexaèdre

Dans le cas de l’hexaèdre de référence, ces fonctions sont données par la table ci-dessous :

Nœud $i$ Fonction de base $p_i (u,v,w)$
1 $\displaystyle p_1 (u,v,w) = \frac{(1-u)(1-v)(1-w)}{8}$
2 $\displaystyle p_2 (u,v,w) = \frac{(1+u)(1-v)(1-w)}{8}$
3 $\displaystyle p_3 (u,v,w) = \frac{(1+u)(1+v)(1-w)}{8}$
4 $\displaystyle p_4 (u,v,w) = \frac{(1-u)(1+v)(1-w)}{8}$
5 $\displaystyle p_5 (u,v,w) = \frac{(1-u)(1-v)(1+w)}{8}$
6 $\displaystyle p_6 (u,v,w) = \frac{(1+u)(1-v)(1+w)}{8}$
7 $\displaystyle p_7 (u,v,w) = \frac{(1+u)(1+v)(1+w)}{8}$
8 $\displaystyle p_8 (u,v,w) = \frac{(1-u)(1+v)(1+w)}{8}$

Et une représentation graphique de $p_1$ est donnée ci-dessous :

p1 sur hexaèdre p1 sur hexaèdre

Éléments quelconques

Considérons maintenant un élément réel $K$ de $\mathcal{M}_h$, et intéressons nous à la transformation permettant de passer de l’élément de référence associé $K_r$ à cet élément, ainsi que sa réciproque.

Transformations géométriques

Soit ${\bf x}$ un point quelconque de $K$ de coordonnées $(x,y,z)$. Une paramétrisation possible de ${\bf x}$ est :

$${\bf x} = \begin{pmatrix}x\\y\\z\end{pmatrix} = \begin{pmatrix}x(u,v,w)\\y(u,v,w)\\z(u,v,w)\end{pmatrix} ={\bf x}({\bf u}) $$

où ${\bf u} = (u,v,w) \in K_r$ permet de faire correspondre tout point $(x,y,z)$ de $K$ avec un point $(u,v,w)$ de $K_r$ de façon biunivoque (bijective). La transformation inverse est alors notée :

$${\bf u} = {\bf u}({\bf x})$$

Une représentation schématique est donnée ci-dessous :

Passage d’un élément de référence à un quelconque Passage d’un élément de référence à un quelconque

Les formules de différentiation des fonctions composées nous donnent alors :

$$\begin{pmatrix}\partial_u\\\partial_v\\\partial_w\end{pmatrix} = \underbrace{\begin{pmatrix}\partial_u\,x & \partial_u\,y & \partial_u\,z\\ \partial_v\,x & \partial_v\,y & \partial_v\,z\\ \partial_w\,x & \partial_w\,y & \partial_w\,z\end{pmatrix}}_{\displaystyle{\bf J}} \, \begin{pmatrix}\partial_x\\\partial_y\\\partial_z\end{pmatrix} $$$$\begin{pmatrix}\partial_x\\\partial_y\\\partial_z\end{pmatrix} = \underbrace{\begin{pmatrix}\partial_x\,u & \partial_x\,v & \partial_x\,w\\ \partial_y\,u & \partial_y\,v & \partial_y\,w\\ \partial_z\,u & \partial_z\,v & \partial_z\,w\end{pmatrix}}_{\displaystyle{\bf J^{-1}}} \, \begin{pmatrix}\partial_u\\\partial_v\\\partial_w\end{pmatrix} $$

La matrice ${\bf J}$ est appelée matrice jacobienne de transformation. Les relations ci-dessus peuvent s’écrire sous forme plus compacte :

$$\partial_{\bf u} = {\bf J}\cdot\partial_{\bf x},~ ~ \text{avec :}~ ~ {\bf J} = \partial_{\bf u}\,{\bf x}$$$$\partial_{\bf x} = {\bf J^{-1}}\cdot\partial_{\bf u},~ ~ \text{avec :}~ ~ {\bf J^{-1}} = \partial_{\bf x}\,{\bf u}$$

On rappelle au passage la formule de l’inverse :

$${\bf J^{-1}} = \frac{1}{\det {\bf J}}\,{}^{\operatorname {t} }\text{com}\,{\bf J}$$

En pratique, on ne la calcule pas de cette façon. En effet, il est intéressant de remarquer que les colonnes de ${\bf J^{-1}}$ sont les gradients selon les coordonnées réelles ${\bf x}$ des fonctions $u({\bf x}),$ $v({\bf x}),$ et $w({\bf x})$. On les note : ${\bf grad_x}\,u({\bf x}),$ ${\bf grad_x}\,v({\bf x})$ et ${\bf grad_x}\,w({\bf x})$.

Nous pouvons calculer ces termes à partir des lignes de la matrice Jacobienne ${\bf J}$ qui sont ${}^{\operatorname t}\partial_u\,{\bf x},$ ${}^{\operatorname t}\partial_v\,{\bf x}$ et ${}^{\operatorname t}\partial_w\,{\bf x},$ et qui sont plus faciles à calculer.

Rappelons les deux propriétés de la comatrice suivantes :

$$\text{com}\,{}^{\operatorname t}{\bf M} = {}^{\operatorname t}\text{com}\,{\bf M}$$$${\bf M}\,{\bf a}\wedge{\bf M}\,{\bf b} = \text{com}\,{\bf M} \, ({\bf a}\wedge{\bf b})$$

Ainsi, on a :

$$\begin{aligned}{\bf grad_x}\,u({\bf x}) &= {\bf J^{-1}}\,{\bf e_x} \\ &= \frac{1}{\det\,{\bf J}}\,{}^{\operatorname t}\text{com}\,{\bf J}\,{\bf e_x} \\ &= \frac{1}{\det\,{\bf J}}\,\text{com}\,{}^{\operatorname t}{\bf J}\,{\bf e_x}\\ &= \frac{1}{\det\,{\bf J}}\,\text{com}\,{}^{\operatorname t}{\bf J}\,({\bf e_y}\wedge{\bf e_z})\\ &= \frac{1}{\det\,{\bf J}}\, {}^{\operatorname t}{\bf J}\,{\bf e_y}\wedge{}^{\operatorname t}{\bf J}\,{\bf e_z}\\ &= \frac{1}{\det\,{\bf J}}\,\left(\partial_v\,{\bf x}\wedge\partial_w\,{\bf x} \right)\end{aligned}$$

On peut faire de même pour les deux autres colonnes, au final, on obtient :

$$\boxed{\left\{\begin{aligned}{\bf grad_x}\,u({\bf x}) = \frac{1}{\det\,{\bf J}}\,\left(\partial_v\,{\bf x}\wedge\partial_w\,{\bf x} \right)\\[2ex] {\bf grad_x}\,v({\bf x}) = \frac{1}{\det\,{\bf J}}\,\left(\partial_w\,{\bf x}\wedge\partial_u\,{\bf x} \right) \\[2ex] {\bf grad_x}\,w({\bf x}) = \frac{1}{\det\,{\bf J}}\,\left(\partial_u\,{\bf x}\wedge\partial_v\,{\bf x} \right)\end{aligned}\right.}$$

Le déterminant de la matrice jacobienne de transformation ($\det\,{\bf J},$ appelé Jacobien) peut se calculer par :

$$\det\,{\bf J} = \det\,{}^{\operatorname t}{\bf J} = \partial_u\,{\bf x}\cdot(\partial_v\,{\bf x}\wedge\partial_w\,{\bf x})$$

Ce Jacobien est très important car il intervient directement dans les formules d’intégration sur l’élément $K$ qui sont (par la formule de changement de variable) :

$$\iiint_K f({\bf x})\,\text{d}{\bf x} = \iiint_{K_r} f\left({\bf x}({\bf u})\right)\,\det\,{\bf J}\,\text{d}{\bf u}$$

Ci-dessous, vous trouverez une petite application permettant de calculer le Jacobien d’un triangle quelconque (avec l’aimable autorisation de son auteur B. Thierry) :

Déplacez les sommets du triangle pour modifier la valeur du Jacobien. Quand il est négatif cela signifie que le triangle est "retourné" par rapport au triangle de référence


Éléments isoparamétriques

Un élément isoparamétrique est un élément fini dont les fonctions de base nodales (qui permettent l’interpolation des champs scalaires) sont aussi utilisées pour paramétrer l’élément géométrique associé (fonctions d’interpolation géométrique) [Dula94].

Les fonctions de base vues ci-dessus sont définies par morceaux, sur chacun des éléments géométriques qui remplissent le domaine étudié, et permettent alors d’assurer leur continuité aux interfaces entre éléments. Ainsi, il n’y aura pas de discontinuité ni des champs scalaires interpolés, ni des coordonnées après transformation des éléments de référence vers les éléments réels. De telles fonctions de base sont dites conformes.

Considérons un élément fini nodal $(K,P_K,\Sigma_K)$. Si $n_K$ est l’ensemble des nœuds de $K$, de coordonnées ${\bf x_i},~i \in \mathbb{N},$ et si les $p_i({\bf u}),~i \in [\![1,n_K]\!],$ sont ses fonctions de base exprimées dans les coordonnées ${\bf u}$ de l’élément de référence $K_r$ associé à $K$, alors la paramétrisation de $K$ $\left({\bf x} = {\bf x}({\bf u})\right)$ est donnée par :

$$\boxed{{\bf x} = \sum\limits_{i = 1}^{n_K} {\bf x_i}\,p_i({\bf u})}$$

et cet élément est isoparamétrique.

Remarque

Dans ce cas, les fonctions de base permettent de passer de l’élément de référence à un élément réel et ainsi de déterminer la forme de ce dernier. C’est pour cela qu’on les appelle aussi fonctions de forme.

Fonctions de base globales

À l’aide de la transformation géométrique précédente et des fonctions de bases $p_i,~i \in [\![1, n_K]\!]$ définies sur l’élément de référence, nous pouvons définir les fonctions de base globales $\varphi_i,~i \in [\![1, n_h]\!]$ définies sur le maillage complet $\mathcal{M}_h$. Il y en aura autant que de nœuds et chacune sera liée à un nœud particulier. Elle seront non-nulles uniquement sur les éléments contenant le nœud considéré. Cet ensemble d’éléments est appelé le support de la fonction de base.

Finalement, d’après ce qui précède, la fonction de base $\varphi_k$ liée au nœud $k \in [\![1, n_h]\!]$ sera nulle sur tous les nœuds du maillage sauf le nœud $k$ où elle prendra la valeur $1$. Soit, en notant ${\bf x_j}$ les coordonnées du nœud $j$ :

$$\boxed{\forall i,j \in [\![1,n_h]\!], ~ \varphi_i({\bf x_j}) = \delta_{ij}}$$

Une illustration interactive est donnée par l’application suivante (toujours avec l’aimable autorisation de son auteur) :

Application : Cliquez sur un sommet pour faire apparaitre la fonction de forme $\mathbf{P_1}$ associée. Les triangles où la fonction n’est pas nulle forment le support de la fonction de forme.


La famille $(\varphi_i)_{0\le i \le n_h}$ ainsi construite forme une base de $V_h$ qui est donc de dimension $n_h$ égale aux nombre de nœuds du maillage $\mathcal{M}_h$.

Soit $u_h$ une fonction de $V_h$. En la décomposant dans la base obtenue :

$$ u_h = \sum\limits_{i = 1}^{n_h} u_i\,\varphi_i$$

Les coefficients $u_i$ sont en fait les valeurs de la fonctions au nœuds. En effet en appliquant en ${\bf x_j}$ :

$$u_h({\bf x_j}) = \sum\limits_{i = 1}^{n_h} u_i\,\varphi_i({\bf x_j}) = u_j$$

Finalement, une fonction $u_h$ de $V_h$ se décompose donc dans la base $(\varphi_i)_{0\le i \le n_h}$ selon :

$$\boxed{u_h = \sum\limits_{i = 1}^{n_h} u_h({\bf x_i})\,\varphi_i}$$

et elle est entièrement caractérisée par ses $n_h$ valeurs aux nœuds.


Remarques complémentaires importantes

  1. Dans le cas présenté, les fonctions de base de l’élément de référence servent aussi à paramétrer les éléments réels (fonctions d’interpolation géométrique). Cela correspond au cas particulier des éléments isoparamétriques, mais ces deux types de fonctions sont indépendants l’un de l’autre :

    • On pourrait tout à fait utiliser des fonctions de base d’ordre 2 (interpolation quadratique) ou d’ordre 3 (interpolation cubique) avec la transformation géométrique précédente (et les éléments rectilignes précédents). Un exemple fonctionnant sous Onelab vous sera fourni page suivante.
    • On pourrait utiliser des fonctions d’interpolation géométrique d’ordre 2 pour définir des éléments courbes. Le cas isoparamétrique (ou les deux types de fonctions sont d’ordre 2) correspond aux éléments dits $\mathbf{P_2}$ (ou $\mathbf{Q_2}$ si quadrangles).
  2. Les éléments présentés ci-dessus conviennent parfaitement pour représenter des champs scalaires, nous verrons plus tard lesquels utiliser pour les champs vectoriels.

  3. Plus que les fonctions de bases globales, ce sont les fonctions de base sur les éléments de référence et la matrice Jacobienne qui sont utiles pour créer le système à résoudre, c’est ce que nous allons voir de suite.

Assemblage et résolution

Assemblage du système à résoudre

On rappelle l’approximation de la formulation faible à résoudre obtenue par la méthode de Galerkin :

$$\forall i \in [\![1,n_h]\!]~ ,~ \sum\limits_{j=1}^{n_h} a(\varphi_i,\varphi_j)\,u_j = L(\varphi_i)$$

Avec :

$$ a(\varphi_i,\varphi_j) = \iiint_{\Omega} \alpha\,{\bf grad}\,\varphi_i \cdot {\bf grad}\,\varphi_j~\text{d}\Omega$$

Et :

$$\displaystyle L(\varphi_i) = \underbrace{\iiint_{\Omega} \beta\,\varphi_i~\text{d}\Omega}_{\displaystyle\left(\beta,\varphi_i\right)_{\Omega}} + \underbrace{\iint_{\Gamma_n} \alpha\,\gamma\,\varphi_i~\text{d}\Gamma}_{\displaystyle\left<\alpha\,\gamma,\varphi_i\right>_{\Gamma_n}}$$

Cette formulation est équivalente à la forme matricielle :

$${\bf A_h}\,{\bf U_h} = {\bf B_h}$$

avec :

$$\left\{\begin{aligned}&{\bf A_h} = \big(a(\varphi_i,\varphi_j)\big)_{1\le i,j\le n_h} = (A_{ij})_{1\le i,j\le n_h} \\[1ex] &{\bf B_h} = \big(L(\varphi_i)\big)_{1\le i\le n_h} = (B_i)_{1\le i\le n_h} \end{aligned}\right.$$

Calcul de ${\bf A_h}$ (matrice de rigidité ou de raideur)

Nous pourrions calculer les $n_h^2$ termes $A_{ij}$ séparément en effectuant une double boucle sur les nœuds. Cette façon de procéder n’est pas très pertinente car de nombreux termes sont nuls : typiquement, lorsque le nœud $i$ n’appartient pas à un élément du support de $\varphi_j$.

Une méthode plus efficace consiste à boucler sur tous les éléments de $\mathcal{M}_h$ et pour chaque élément $K_q$ calculer sa contribution $a_q(\varphi_k,\varphi_l),$ $(k,l) \in [\![1,n_{K_q}]\!]$ à la matrice globale ${\bf A_h}$ :

$$a_q(\varphi_k,\varphi_l) = \iiint_{K_q} \alpha({\bf x})\,{\bf grad}\,\varphi_k({\bf x}) \cdot {\bf grad}\,\varphi_l({\bf x})~\text{d}{\bf x} $$

D’après notre formule de changement de base :

$$a_q(\varphi_k,\varphi_l) = \iiint_{K_r} \alpha\left({\bf x}({\bf u})\right)\,{\bf grad}\,\varphi_k\left({\bf x}({\bf u})\right) \cdot {\bf grad}\,\varphi_l\left({\bf x}({\bf u})\right)\,\text{det}\,{\bf J_q}~\text{d}{\bf u} $$

En utilisant les relations entre les gradients et la matrice jacobienne de transformation géométrique :

$$a_q(\varphi_k,\varphi_l) = \iiint_{K_r} \alpha\left({\bf x}({\bf u})\right)~ \left({\bf J_q^{-1}}\,{\bf grad}\,p_k({\bf u})\right) \cdot \left({\bf J_q^{-1}}\,{\bf grad}\,p_l({\bf u})\right)\,\text{det}\,{\bf J_q}~\text{d}{\bf u}$$

Finalement :

$$\boxed{a_q(\varphi_k,\varphi_l) = \text{det}\,{\bf J_q} \iiint_{K_r} \alpha\left({\bf x}({\bf u})\right)~ {}^{\operatorname t}\left({\bf grad}\,p_k({\bf u})\right)\,{}^{\operatorname t}({\bf J_q^{-1}})\,{\bf J_q^{-1}}\,{\bf grad}\,p_l({\bf u})~ \text{d}{\bf u}}$$

Nous avons vu comment calculer ${\bf x}({\bf u})$, $\text{det}\,{\bf J_q}$ et ${\bf J_q^{-1}}$ à la page précédente, et les gradients des fonctions de base se déterminent facilement à partir de leurs expressions.

Ainsi, pour calculer les $n_{K_q}$ contributions de l’élément $K_q$, il nous reste plus qu’à savoir comment déterminer l’intégrale sur l’élément de référence $K_r$. Nous le verrons ci-après.

Calcul de ${\bf B_h}$ (second membre)

Intéressons nous maintenant au membre de droite en l’absence de condition de Neumann particulière.

Cas sans condition de Neumann hétérogène

Nous allons procéder de la même manière que pour ${\bf A_h}$ en calculant les contributions $L_q(\varphi_k)$ de chaque élément $K_q$ à ${\bf B_h}$ :

$$\begin{aligned}L_q(\varphi_k) &= \iiint_{K_q} \beta({\bf x})\,\varphi_k({\bf x})\,\text{d}{\bf x} \\ &= \iiint_{K_r} \beta\left({\bf x}({\bf u})\right)\,p_k({\bf u})\,\text{det}\,{\bf J_q}~\text{d}{\bf u}\end{aligned}$$

Finalement :

$$\boxed{L_q(\varphi_k) = \text{det}\,{\bf J_q} \iiint_{K_r} \beta\left({\bf x}({\bf u})\right)\,p_k({\bf u})~\text{d}{\bf u}}$$

Cas avec condition de Neumann hétérogène

Dans le cas d’une condition de Neumann non nulle, nous procédons comme ci-dessus mais en plus nous devons également calculer les contributions $L_q^n(\varphi_k)$ des éléments de la frontière $\Gamma_n$. Ceux-ci sont d’une dimension moindre que les éléments constituant le domaine $\Omega$. Ce seront donc des triangles ou des quadrangles en 3D, ou des segments en 2D.

Pour chaque éléments $K_q^n$ de $\Gamma_n$, nous calculons ainsi :

$$L_q^n(\varphi_k) = \iint_{K_q^n} \alpha({\bf x})\,\gamma({\bf x})\,\varphi_k({\bf x})\,\text{d}{\bf x}$$$$\boxed{L_q^n(\varphi_k) = \text{det}\,{\bf J_q^n} \iint_{K_r^n} \alpha\left({\bf x}({\bf u})\right)\,\gamma\left({\bf x}({\bf u})\right)\,p_k({\bf u})\,\text{d}{\bf u}}$$

où $K_r^n$ est l’élément de référence associé aux éléments du bord du domaine.

Intégration numérique

Pour achever le calcul des coefficients des deux matrices, nous devons calculer les intégrales des différents termes sur le (ou les) élément(s) de référence. Pour cela nous allons utiliser une méthode de quadrature ; et généralement, c’est une formule de quadrature de Gauss.

Ainsi, on aura :

$$\iiint_{K_r} f({\bf u})\,\text{d}{\bf u} \approxeq \sum\limits_{m=1}^{n_g} \omega_m\,f({\bf x_{g_m}})$$

où les ${\bf x_{g_m}}$ sont les coordonnées des $n_g$ points de Gauss choisis et $w_m$ les poids associés.

On notera que le calcul donne même la valeur exacte dans le cas de polynôme (à condition d’avoir le bon nombre de points de Gauss).

Dans la table ci-dessous, sont donnés quelques exemples :

Élément $n_g$ Points de Gauss Poids Exacte pour
Segment $1$ $x_g = 0$ $\omega =2$ degré 1
$2$ $x_{g_1} = -\frac{1}{\sqrt{3}}$, $x_{g_2} = \frac{1}{\sqrt{3}}$ $\omega_1 = \omega_2 = 1$ degré 2
Triangle $1$ ${\bf x_g} = (\frac{1}{3},\frac{1}{3})$ $\omega=\frac{1}{2}$ degré 1
$3$ ${\bf x_{g_1}} = (\frac{1}{6},\frac{1}{6})$, ${\bf x_{g_2}} = (\frac{2}{3},\frac{1}{6})$, ${\bf x_{g_3}} = (\frac{1}{6},\frac{2}{3})$ $\omega_1 = \omega_2 = \omega_3 = \frac{1}{6}$ degré 2
Quadrangle $1$ ${\bf x_g} = (0,0)$ $\omega=4$ degré 1
$4$ ${\bf x_{g_1}} = (\frac{1}{\sqrt{3}},\frac{1}{\sqrt{3}})$, ${\bf x_{g_2}} = (-\frac{1}{\sqrt{3}},\frac{1}{\sqrt{3}})$, ${\bf x_{g_3}} = (\frac{1}{\sqrt{3}},-\frac{1}{\sqrt{3}})$, ${\bf x_{g_4}} = (-\frac{1}{\sqrt{3}},-\frac{1}{\sqrt{3}})$ $\omega_1 = \omega_2$ $= \omega_3$ $= \omega_4$ $= 1$ degré 2
Tétraèdre $1$ ${\bf x_g} = (\frac{1}{4},\frac{1}{4},\frac{1}{4})$ $\omega=\frac{1}{6}$ degré 1
$4$ ${\bf x_{g_1}} = (\alpha,\alpha,\alpha)$, ${\bf x_{g_2}} = (\alpha,\alpha,\beta)$, ${\bf x_{g_3}} = (\alpha,\beta,\alpha)$, ${{\bf x_{g_4}} = (\beta,\alpha,\alpha)}$, avec : ${\alpha = 0,138196601125}$, ${\beta = 0,585410196625}$ $\omega_1 = \omega_2$ $= \omega_3 = \omega_4$ $= \frac{1}{24}$ degré 2

On remarquera que dans tous les cas, la somme des poids est égale à la longueur, l’aire ou le volume de l’élément considéré.

Astuce

Contrairement à ce qu’on pourrait penser, le choix du nombre de points de Gauss n’est pas primordial car l’erreur commise par la méthode d’intégration est faible devant les autres approximations de la méthode. Les seconds choix de la table précédente sont donc tout à fait pertinents (on n’utilisera que des fonctions de bases linéaires, voire quadratiques).

Résolution

Après génération du système linéaire précédent, il ne reste plus qu’à résoudre. Il convient donc de choisir une méthode / un algorithme pouvant résoudre efficacement des systèmes de grande taille mais creux.

Remarque

Pour les différentes méthodes de résolution (avec ou sans pré-conditionnement), je vous renvoie à l’EC d’« Analyse numérique », du tronc commun de S6.

Dans le cadre de ce cours, nous utiliserons GetDP pour définir et résoudre nos problèmes. Ce dernier s’appuie sur la suite PETSc configurée pour appeler le solveur linéaire direct multithreadé MUMPS (avec factorisation LU).

Après résolution, nous avons accès aux valeurs des degrés de liberté (valeurs du champ scalaire recherché) en chaque nœud du maillage. Nous pouvons ensuite calculer ce champ ou ses dérivés à partir de ces valeurs pour les tracer ou calculer tout autre grandeur locale ou globale. C’est ce qu’on appelle le post-traitement (post-processing).

Application à notre exemple (résolution avec GetDP)

Nous allons mettre en application ce qui précède sur notre exemple fil rouge, en écrivant le script GetDP permettant de le résoudre. Ce dernier doit porter le même nom que le fichier *.geo avec l’extension *.pro, ici : poisson.pro. Le déroulement suit les différentes étapes décrites dans les sections ci-avant, soit :

  1. Lien avec le maillage : Où nous chargeons les différents paramètres et groupons les éléments en fonction de leur région d’appartenance.
Include "data.geo" ;

Group{
  Domaine = Region[{DISQUE,SOURCE}];
  Source = Region[{SOURCE}];
  Dirichlet = Region[{DIRICHLET}];
  Neumann = Region[{NEUMANN}];
}
  1. Définition des fonctions :
Function{
  beta[#{Source}] = 1.0;
  gamma[#{Neumann}] = 1.0;
}
  1. Définition du Jacobien et de la méthode d’intégration :
Jacobian{
  { Name Jvol;
    Case {
      { Region All ; Jacobian Vol; }
    }
  }
}

Integration {
  { Name Integ;
    Case { 
      {Type Gauss;
	Case { 
	  { GeoElement Line ; NumberOfPoints 2; }
	  { GeoElement Triangle ; NumberOfPoints 6; }
	  { GeoElement Quadrangle ; NumberOfPoints 4; }
	}
      }
    }
  }
}
  1. Définition des contraintes : permettant de définir les conditions aux limites dans les espaces fonctionnels
Constraint {	
  {Name ConditionDirichlet ;
    Case {      
      {Region Dirichlet ; Type Assign ; Value 0. ;}
    }
  }
}
  1. Définition de l’espace fonctionnel :
FunctionSpace {
  { Name Hgrad ; Type Form0 ; 
    BasisFunction { 
      { Name sn ; NameOfCoef phi ; Function BF_Node ; 
	Support Region[{Domaine,Neumann}]  ; Entity NodesOf[All] ; }
    } 
    Constraint {
      { NameOfCoef phi  ; EntityType NodesOf ; NameOfConstraint ConditionDirichlet ; }
    }
  }
}
  1. Définition de la formulation (faible) :
Formulation {
  { Name Poisson ; Type FemEquation ;
    Quantity {
      { Name u  ; Type Local  ; NameOfSpace Hgrad ; }
    }
   Equation {
      Integral { [ Dof{Grad u}  , {Grad u} ] ;
		In Domaine ; Jacobian Jvol ; Integration Integ ; }
      Integral { [  -beta[] , {u} ] ;
		In Source ; Jacobian Jvol ; Integration Integ ; }     
      Integral { [ -gamma[] , {u} ] ; 
      	In Neumann ; Jacobian Jvol ; Integration Integ ; }
    }
  }
}
  1. Résolution :
Resolution {
  { Name analyse ;
    System {
      { Name Sys ; NameOfFormulation Poisson ; }
    }
    Operation {
      Generate[Sys] ; 
      Solve[Sys] ;
      SaveSolution[Sys] ;
    }
  }
}
  1. Post-traitement : Calcul des grandeurs (PostProcessing) et tracé ou afffichage (PostOperation).
PostProcessing {
  { Name PostProc ; NameOfFormulation Poisson ;
    Quantity {	
      { Name u  ; Value { Term { [ {u} ] ; In Domaine ; Jacobian Jvol ; } } }
      { Name Grad_u  ; Value { Term { [ {Grad u} ] ; In Domaine ; Jacobian Jvol ; } } }
      { Name normu ; Value { Integral { [ Norm[{u}] ]  ; In Domaine ; 
	    Jacobian Jvol ; Integration Integ ;} } } 
    }
  }
}

PostOperation PostOp UsingPost PostProc {
  Print[ Grad_u, OnElementsOf Domaine, File "gradu.pos"] ;
  Print[ u, OnElementsOf Domaine, File "u.pos"] ;
  Print[ normu[Domaine], OnGlobal, File "normu.dat", 
    SendToServer "Modele/Resultats/1Norme (u)", Color "AliceBlue" ];
}


J’ai regroupé l’ensemble des fichiers permettant de résoudre notre exemple dans un petit modèle Onelab pouvant être utilisé directement dans Gmsh.
Vous pouvez même l’exécuter sur votre smartphone avec l’application Onelab (disponible sur les stores officiels) !
Edit (janv. 2026) : Pour ceux qui sont sous Android ou dérivés, l’app n’est malheureusement plus dans le Play Store. Vous pouvez néanmoins télécharger l’apk à partir de ce lien et l’installer directement (je procède comme ça sous GrapheneOS).

J’ai rajouté :

  • une option pour choisir un maillage triangulaire ou quadrangulaire,
  • un paramètre de contrôle du maillage (plus la valeur est grande, plus le maillage est fin),
  • une option pour choisir l’ordre d’interpolation (ordre des fonctions de base) : linéaire, quadratique, ou cubique (dernier cas seulement pour les triangles).

Exemple fil rouge à télécharger (compatible PC et smartphone) :

Modèle Onelab du running example (MAJ : 03 mai 2022)

Éléments finis de Whitney

Contexte

Nous venons de développer complètement le principe de la méthode des éléments finis pour des champs scalaires appartenant à $\text{H}^1(\Omega) \left(= \text{H}({\bf grad},\Omega)\right)$. Pour cela, nous avons utilisé des éléments de Lagrange bien adaptés pour ce type d’inconnues.

Cependant les différents champs constituant le champ électromagnétique sont également des grandeurs vectorielles pouvant appartenir à ${\bf H}({\bf rot},\Omega)$ ou ${\bf H}(\text{div},\Omega)$. Typiquement nous ne pouvons résoudre notre formulation rot-rot avec des éléments de Lagrange tels quels. Nous pourrions choisir de résoudre avec trois champs scalaires pour déterminer notre vecteur inconnu (un par composante), mais cette solution est loin d’être la plus pertinente en terme d’efficacité et d’aspects géométriques (respect de certaines conditions de continuité aux interfaces).

Parmi la grande variété d’éléments finis existants, une famille est très largement utilisée pour modéliser des problèmes électromagnétiques : les éléments finis de Whitney. En fait, ces derniers ont été spécifiquement créés dans ce but [Boss93]. Basés sur les formes différentielles du même nom, ils offrent un cadre idéal pour approximer nos champs en 3D car ils permettent de construire de manière séquentielle les espaces discrets auxquels ils appartiennent. Nous allons donc présenter succinctement ces éléments.

Éléments de Whitney

Contrairement aux éléments précédents, les éléments de Whitney sont initialement définis en 3D et s’appuient sur des degrés de libertés pouvant être reliés aux valeurs aux nœuds (éléments nodaux), mais aussi aux circulations le long des arêtes (éléments d’arête), aux flux au travers des facettes (éléments de facette), et aux intégrales sur les volumes (éléments de volume) des éléments du maillage. Compte tenu de ces différences de nature entre degrés de liberté, on les appelle parfois éléments finis mixtes.

Astuce

Nous verrons dans la partie applicative qu’il est tout a fait possible de traiter des cas 2D. Selon les cas : soit directement, soit en utilisant certaines adaptations (arêtes ou facettes fictives orthogonales au plan d’étude).

Espaces discrets

Le principe de base est de construire successivement les espaces discrets $W^0$, $W^1$, $W^2$ et $W^3$ permettant d’approximer respectivement $\text{H}({\bf grad},\Omega)$, ${\bf H}({\bf rot},\Omega)$, ${\bf H}(\text{div},\Omega)$ et $L^2(\Omega)$, à partir d’une séquence de fonctions de base, liées respectivement aux nœuds $(\mathcal{N_h})$, aux arêtes $(\mathcal{A_h})$, aux facettes $(\mathcal{F_h})$ et aux volumes $(\mathcal{V_h})$ des éléments du maillage $\mathcal{M_h}$.

On peut synthétiser l’ensemble dans la table suivante :

Espace Approxime Fonctions de bases Propriété Degré de liberté Type d’élément
$W^0$ $\text{H}({\bf grad},\Omega)$ $\{s_n,~ n\in\mathcal{N_h}\}$ $s_i({\bf x_j}) = \delta_{ij},~$ ${\forall i,j \in\mathcal{N}_h}$ Valeur nodale Élément nodal
$W^1$ ${\bf H}({\bf rot},\Omega)$ $\{ {\bf s_a},~ a\in \mathcal{A_h}\}$ $\displaystyle \int_j {\bf s_i}\cdot{\bf dl} = \delta_{ij},~$ ${\forall i,j \in\mathcal{A_h}}$ Circulation le long d’une arête Élément d’arête
$W^2$ ${\bf H}(\text{div},\Omega)$ $\{ {\bf s_f},~ f\in \mathcal{F_h}\}$ $\displaystyle \iint_j {\bf s_i}\cdot{\bf n}~ \text{d}S =\delta_{ij},~$ ${\forall i,j \in\mathcal{F}_h}$ Flux à travers une face Élément de facette
$W^3$ $L^2(\Omega)$ $\{s_v,~ v\in\mathcal{V_h}\}$ $\displaystyle \iiint_j s_i~\text{d}V = \delta_{ij},~$ ${\forall i,j \in\mathcal{V}_h}$ Intégrale volumique Élément de volume

En procédant ainsi, on respecte la séquence vue sur les espaces continus, à savoir :

$$W^0 \xrightarrow[]{{\bf grad}} W^1 \xrightarrow[]{{\bf rot}} W^2 \xrightarrow[]{\text{div}} W^3 $$

Et l’ensemble nous permet également d’assurer les continuités aux interfaces :

  • de valeur pour les $s_n$ ;
  • de composante tangentielle pour les ${\bf s_a}$ ;
  • de composante normale pour les ${\bf s_f}$.

Voyons maintenant comment définir ces fonctions de base (sur les éléments de références).

Fonctions de base

Fonctions de base nodales

Puisque $W_0$ est une approximation de $\text{H}({\bf grad},\Omega) = \text{H}^1$, nous pouvons réutiliser les fonctions définies dans les parties précédentes. Nous aurons donc pour tout nœud $n_i = \{i\}$ de $\mathcal{N_h}$ :

$$s_{n_i} = p_i,~ ~ \forall\,i \in [\![1, n_K]\!]$$

Tout ce qui précède reste donc valable. Les fonctions de base nodales des éléments de Whitney sont celles des éléments de Lagrange.

Fonctions de base d’arête

À une arête ${\bf a_{ij}} = \{i\rightarrow j\}$ de $\mathcal{A_h}$, on associe :

$${\bf s_{a_{ij}}} = p_j~{\bf grad}\left(\sum\limits_{r\in \operatorname{N}(j,\overline{i})} p_r \right) - p_i~{\bf grad}\left(\sum\limits_{r\in \operatorname{N}(i,\overline{j})} p_r \right) $$

Où $\operatorname{N}(i,\overline{j})$ représente l’ensemble des nœuds de la facette $f$ contenant le nœud $i$ mais pas le nœud $j$.

Remarque : Dans le cas du tétraèdre, l’expression ci-dessus se ramène à :

$${\bf s_{a_{ij}}} = p_i~{\bf grad}\,p_j - p_j~{\bf grad}\,p_i$$

À titre d’illustration, nous traçons un exemple pour les triangle, quadrangle, tétraèdre et hexaèdre de référence ci-dessous :

${\bf s_{a_{23}}}$ sur tétraèdre ${\bf s_{a_{23}}}$ sur hexaèdre
sa23 tetra sa23 tetra sa23 tetra sa23 tetra

En considérant une facette fictive $f$ orthogonale au plan d’étude, on peut définir nos fonctions de base en 2D, et dans ce cas, on obtient :

${\bf s_{a_{23}}}$ sur triangle ${\bf s_{a_{23}}}$ sur quadrangle
sa23 triangle sa23 triangle sa23 quadrangle sa23 quadrangle

Fonctions de base de facette

À une facette orientée ${\bf f_{ijk}} = \{i,j,k\} = \operatorname{N}({\bf f_{ijk}})$ (si tétrahèdre) ou ${\bf f_{ijkl}} = \{i,j,k,l\} = \operatorname{N}({\bf f_{ijkl}})$ (si hexaèdre) de $\mathcal{F_h}$, on associe :

$${\bf s_{f_{ijk(l)}}} = a~{\large \sum\limits_{q \in \operatorname{N}({\bf f_{ijk(l)}})}} { p_q \left({\bf grad}\,\sum\limits_{r \in \operatorname{N}(q,\overline{q+1})} p_r \right)\wedge\left({\bf grad}\,\sum\limits_{r \in \operatorname{N}(q,\overline{q-1})} p_r \right) }$$

où la liste des nœuds de la facette $\operatorname{N}({\bf f})$ est rendue circulaire, $\operatorname{N}(i,\overline{j})$ conserve sa définition précédente et $a$ est un coefficient tel que : $ a= 2$ si $\dim(\operatorname{N}({\bf f})) = 3$ et $a = 1$ si $\dim(\operatorname{N}({\bf f})) = 4$.

On représente graphiquement ces fonctions de facette en 2D (facette fictive perpendiculaire au plan d’étude) dans la table ci-dessous :

${\bf s_{f_{23\perp}}}$ sur triangle ${\bf s_{f_{23\perp}}}$ sur quadrangle
sa23 triangle sa23 triangle sa23 quadrangle sa23 quadrangle

Fonctions de base de volume

À l’élément $K$, on fait correspondre la fonction de base de volume :

$$s_{v_K} = \frac{1}{\operatorname{vol}(K)}$$

qui est donc constante sur l’élément.

Remarque

Les fonctions de base se généralisent aux éléments de type pyramide et prisme. Pour de plus amples détails voir : [Dula94] et [Geuz01].

Degrés de liberté

Avec les définitions précédentes on peut décomposer tout champ scalaire ou vectoriel selon son espace d’appartenance :

  1. Soit $u \in \text{H}({\bf grad},\Omega)$, son approximation sur $\mathcal{M_h}$ est $u_h \in W^0$ tel que :

    $$u_h = \sum\limits_{n\in\mathcal{N_h}} \sigma_n(u_h)\,s_n = \sum\limits_{n\in\mathcal{N_h}} u_n\,s_n$$

    avec :

    $$u_n = u_h({\bf x_n})$$
  2. Soit ${\bf u} \in \textbf{H}({\bf rot},\Omega)$, son approximation sur $\mathcal{M_h}$ est ${\bf u_h} \in W^1$ tel que :

    $${\bf u_h} = \sum\limits_{a\in\mathcal{A_h}} \sigma_a({\bf u_h})\,{\bf s_a} = \sum\limits_{a\in\mathcal{A_h}} {u_a}\,{\bf s_a}$$

    avec :

    $$u_a = \int_a {\bf u_h}\cdot{\bf dl}$$
  3. Soit ${\bf u} \in \textbf{H}(\text{div},\Omega)$, son approximation sur $\mathcal{M_h}$ est ${\bf u_h} \in W^2$ tel que :

    $${\bf u_h} = \sum\limits_{f\in\mathcal{F_h}} \sigma_f({\bf u_h})\,{\bf s_f} = \sum\limits_{f\in\mathcal{F_h}} {u_f}\,{\bf s_f}$$

    avec :

    $$u_f = \iint_f {\bf u_h}\cdot{\bf n}~\text{d}S$$
  4. Soit $u \in L^2(\Omega)$, son approximation sur $\mathcal{M_h}$ est $u_h \in W^3$ tel que:

    $$u_h = \sum\limits_{v\in\mathcal{V_h}} \sigma_v(u_h)\,s_v = \sum\limits_{v\in\mathcal{V_h}} u_v\,s_v$$

    avec :

    $$u_v = \iiint_v u_h~\text{d}V$$

Ainsi, en décomposant nos approximations dans les bons espaces, on peut appliquer la méthode de Galerkin en utilisant les fonctions de base ci-dessus comme fonctions tests. Par analogie avec les éléments nodaux de la section précédente, on se ramènera donc à la résolution d’un système linaire où le vecteur inconnu ${\bf U_h}$ correspondra aux différents degrés de liberté.

Application des éléments d’arête à la formulation rot-rot

Formulation

On rappelle la formulation faible continue à résoudre :

$$\left\{\begin{aligned}&\text{Trouver}~ {\bf u} \in\textbf{H}_0({\bf rot},\Omega) ~ \text{tel que :} \\ & \left(\alpha\,{\bf rot\,u},{\bf rot\,v}\right)_{\Omega} = - \left(\boldsymbol{\beta},{\bf v}\right)_{\Omega} - \left<\alpha\,\boldsymbol{\gamma},{\bf v}\right>_{\Gamma_n},~ \forall\,{\bf v} \in \textbf{H}_0({\bf rot},\Omega) \end{aligned}\right.$$

Qui devient en discret :

$$\left\{\begin{aligned}&\text{Trouver}~ {\bf u_h} \in W_0^1 ~ \text{tel que :} \\ & \left(\alpha\,{\bf rot\,u_h},{\bf rot\,v_h}\right)_{\Omega} + \left(\boldsymbol{\beta},{\bf v_h}\right)_{\Omega} + \left<\alpha\,\boldsymbol{\gamma},{\bf v_h}\right>_{\Gamma_n} = 0,~ \forall\,{\bf v_h} \in W_0^1\end{aligned}\right.$$

Où $W_0^1 \in W^1$ est obtenu en annulant les degrés de liberté sur les arêtes appartenant à la frontière $\Gamma_d$. On constate que cela implique bien notre condition de bord :

$$\left.{\bf u_h}\wedge{\bf n}\right|_{\Gamma_d} = {\bf 0}~ , ~ \text{sur}~ \Gamma_d$$

La façon de procéder est identique à celle basée sur les éléments nodaux. Nous pouvons calculer les contributions de chaque arête élément par élément et les ajouter à la matrice de raideur globale ${\bf A_h}$, ou au vecteur second membre ${\bf B_h}$. On peut finalement résoudre le système obtenu, mais seulement après avoir implanté une condition de jauge comme expliqué ci-après. En effet, une telle formulation sous forme brute conduit à une matrice ${\bf A_h}$ singulière.

Condition de jauge

Nous savons malheureusement qu’un problème général (en 3D) comme celui-ci n’a pas de solution unique (vient de l’équivalence avec la formulation forte) et que le champ ${\bf u_h}$ solution est défini à un champ de gradient près. Il est alors impossible de résoudre le système obtenu sans avoir ajouté de condition de jauge particulière. Nous allons donc voir comment procéder.

Jauge d’arbre

Dans le domaine continu, pour rendre ${\bf u}$ unique, on peut ajouter une condition du type :

$${\bf u}\cdot{\bf w} = 0$$

Où ${\bf w}$ est un champ de vecteurs dont les lignes de champ ne sont pas fermées et sont telles qu’elles peuvent relier toute paire de points quelconque du domaine d’étude $\Omega$ (par exemple un champ de gradient divergeant).

Dans le domaine discret, nous allons construire un arbre. C’est un ensemble d’arêtes qui relient tous les nœuds du maillage entre eux sans former de chemin fermé. Les arêtes du maillage qui ne sont pas dans l’arbre constituent le co-arbre associé. Un moyen de jauger ${\bf u_h}$ est ainsi d’annuler les composantes sur les arrêtes de l’arbre (condition équivalente à celle continue ci-dessus). Afin de ne pas dénaturer les conditions imposées sur $\Gamma_d$, il convient de commencer à construire l’arbre à partir des arrêtes de cette frontière. Une représentation graphique est donnée ci-dessous :

Exemple d'un arbre (trait bleu) et d'un co-arbre (trait noir) sur des éléments 3D. Les nœuds sont en rouge et la partie grisée appartient à $\Gamma_d$

En rajoutant la condition de jauge d’arbre dans l’espace fonctionnel auquel appartient ${\bf u_h}$ (que nous noterons $W_{0,\text{JA}}^1 \subset W_0^1$), nous pouvons alors résoudre notre formulation faible rot-rot qui s’exprime :

$$\boxed{\left\{\begin{aligned}&\text{Trouver}~ {\bf u_h} \in W_{0,\text{JA}}^1 ~ \text{tel que :} \\ & \left(\alpha\,{\bf rot\,u_h},{\bf rot\,v_h}\right)_{\Omega} + \left(\boldsymbol{\beta},{\bf v_h}\right)_{\Omega} + \left<\alpha\,\boldsymbol{\gamma},{\bf v_h}\right>_{\Gamma_n} = 0,~ \forall\,{\bf v_h} \in W_{0,\text{JA}}^1\end{aligned}\right.}$$

Cette façon de procéder est la plus efficace d’un point de vue numérique car elle permet de réduire la taille du système à résoudre (par annulation des degrés de liberté liés au arêtes de l’arbre). Cependant la solution obtenue perd son sens physique, seul son rotationnel pourra être interprété physiquement. Pour de plus amples compléments, je vous renvoie à [Dula94] .

Jauge de Coulomb

Une autre Jauge possible est d’annuler la divergence de notre inconnue (Jauge de Coulomb) :

$$\text{div}\,{\bf u} = 0$$

Pour obtenir la forme faible de cette condition, considérons un champ scalaire $\mu$ quelconque de $\text{H}({\bf grad},\Omega)$. On a :

$$\iiint_{\Omega}\text{div}({\bf u})\,\mu ~\text{d}V = 0$$

En utilisant la formule de Green en grad-div :

$$\iiint_{\Omega} {\bf u}\cdot{\bf grad}\,\mu ~ \text{d}V - \iiint_{\Omega} \text{div}(\mu\,{\bf u})~ \text{d}V =0$$

En appliquant le théorème de la divergence et en séparant les deux frontières :

$$\iiint_{\Omega} {\bf u}\cdot{\bf grad}\,\mu ~ \text{d}V - \iint_{\Gamma_d} \mu\,{\bf u}\cdot{\bf n}~ \text{d}S - \iint_{\Gamma_n} \mu\,{\bf u}\cdot{\bf n} ~ \text{d}V =0$$

Nous ne considérerons que le cas d’une condition de Neumann homogène sur $\Gamma_n$ $(\boldsymbol{\gamma} = 0)$, soit : $\left.{\bf rot\,u}\wedge{\bf n}\right|_{\Gamma_n} = 0$. On peut donc en déduire : $\left.{\bf u}\cdot{\bf n}\right|_{\Gamma_n} = 0$. En choisissant $\mu = 0$ sur $\Gamma_d$, on annule le second terme surfacique.

Ainsi, notre condition de Jauge est équivalente à :

$$\boxed{\iiint_{\Omega} {\bf u}\cdot{\bf grad}\,\mu ~ \text{d}V = 0~ ,~ ~ \forall \, \mu \in \text{H}_0({\bf grad},\Omega)}$$

Si nous ajoutons uniquement ce terme à la formulation faible initiale, nous nous trouverons face à une formulation avec une fonction inconnue et deux fonctions tests. Pour remédier à cela, nous devons introduire un multiplicateur de Lagrange $\lambda$. Ainsi la formulation variationnelle complète devient :

$$\left\{\begin{aligned}&\text{Trouver}~ {\bf u} \in\textbf{H}_0({\bf rot},\Omega),~ \lambda \in \text{H}_0({\bf grad},\Omega) ~ \text{tels que :} \\ &\left(\alpha\,{\bf rot\,u},{\bf rot\,v}\right)_{\Omega} + \left({\bf grad}\,\lambda,{\bf v}\right)_{\Omega} + \left(\boldsymbol{\beta},{\bf v}\right)_{\Omega} = 0,~ \forall\,{\bf v} \in \textbf{H}_0({\bf rot},\Omega)\\ &\left({\bf u},{\bf grad}\,\mu\right)_{\Omega} = 0, \forall \, \mu \in \text{H}_0({\bf grad},\Omega)\end{aligned}\right.$$

La transcription dans le domaine discret est immédiate :

$$\boxed{\left\{\begin{aligned}&\text{Trouver}~ {\bf u_h} \in W_0^1,~ \lambda_h \in W_0^0~ \text{tels que :} \\ &\left(\alpha\,{\bf rot\,u_h},{\bf rot\,v_h}\right)_{\Omega} + \left({\bf grad}\,\lambda_h,{\bf v_h}\right)_{\Omega} + \left(\boldsymbol{\beta},{\bf v_h}\right)_{\Omega} = 0,~ \forall\,{\bf v_h} \in W_0^1 \\ &\left({\bf u_h},{\bf grad}\,\mu_h\right)_{\Omega} = 0, \forall \, \mu_h \in W_0^0 \end{aligned}\right.}$$

Cette façon de procéder est plus lourde à résoudre : le système est beaucoup plus grand que le précédent car on a rajouté autant de degrés de liberté que de nœuds du maillage. Cependant, elle a le mérite de fournir une solution « plus physique » et plus facilement interprétable.