8.3. FreeFem++ et Maillage en EF#
Marc BUFFAT, dpt mécanique, Université Claude Bernard Lyon 1
Mise à disposition selon les termes de la Licence Creative Commons
Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 2.0 France.
%matplotlib inline
%autosave 300
from numpy import *
import matplotlib.pyplot as plt
from IPython.core.display import HTML
Autosaving every 300 seconds
8.3.1. Génération de maillage#
8.3.1.1. Structure de données en 2D#
Maillage de \(ne\) triangles et \(nn\) sommets
Table de connexion: tableau Tbc de nex3 entiers
Coordonnées des noeuds: tableau X de nnx2 réels
Frontière (noeuds): tableau frt de nn entiers
Région (éléments): tableau reg de ne entiers
8.3.1.1.1. table de connexion#
<img src= »mesh1.png »; style= »width:600px »/>
8.3.1.1.2. Frontière et région#
8.3.1.2. Génération par transformation#
Transformation conforme vers un carre unité
8.3.2. Voronoi#
Mailleur automatique
8.3.3. Mailleur de FreeFem++#
(c) O. Pironneau et Frédéric Hecht Paris VI http://www.freefem.org
8.3.3.1. FreeFem++#
mailleur automatique Voronoi P1 (2D)
solveur matriciel pour des matrices de type elts finis
interpréteur de commande (langage de programmation)
création d’un fichier de commande (extension .edp)
execution: FreeFem++ probleme.edp
8.3.3.2. Syntaxe FreeFem++#
syntaxe proche du C++
fin instruction ;
structure : { .. };
variables: pi=3.1456;
résolution d’EDP
8.3.4. Mailleur Voronoi FreeFem++#
from freefem import mesh
G=mesh("essai.msh")
G.info()
G.plot()
Maillage essai.msh
Nn,Ne= 58 86
Xmin/max Ymin/max= 0.0 1.0 0.0 1.0
surface 0.7500000000000003
8.3.5. Syntaxe FreeFem++#
Langage proche de C++ (instruction terminée par ; , utilisation {} )
On définit un maillage \(T_h\) par la frontière \(\Gamma=\partial \Omega\) du domaine donnée par des courbes paramétrées \(\Gamma_i\):
8.3.5.1. description de la frontiere (sens trigonométrique)#
border nom1(t=t0,t1)
{
x=f1(t);
y=g1(t);
label=1;
};
border nom2(t=t0,t1)
{
x=f2(t);
y=g2(t);
label=2;
};
8.3.5.2. description des frontieres par C.L. (label)#
création et visualisation du maillage
On spécifie le nombre de points sur chaque frontière
mesh Th=buildmesh(nom1(n1)+nom2(n2));
8.3.5.3. sauvegarde du maillage dans un fichier#
savemesh(Th,'nom_fichier.msh');
8.3.6. Exemple de fichier maillage: essai.edp#
// définition des frontières
border aaa(t=0,1){x=t;y=0;label=2;};
border bbb(t=0,0.5){x=1;y=t;label=2;};
border ccc(t=0,0.5){x=1-t;y=0.5;label=2;};
border ddd(t=0.5,1){x=0.5;y=t;label=2;};
border eee(t=0.5,1){x=1-t;y=1;label=2;};
border fff(t=0,1){x=0;y=1-t;label=2;};
// generation du maillage
mesh Th = buildmesh (aaa(6) + bbb(4) + ccc(4) +ddd(4) +
eee(4) + fff(6));
// sauvegarde
savemesh(Th,"essai.msh");
%%bash
FreeFem++ -nw essai.edp
-- FreeFem++ v4.9 ( - git no git)
Load: lg_fem lg_mesh lg_mesh3 eigenvalue
1 : // définition des frontières
2 : border aaa(t=0,1){x=t;y=0;label=2;};
3 : border bbb(t=0,0.5){x=1;y=t;label=2;};
4 : border ccc(t=0,0.5){x=1-t;y=0.5;label=2;};
5 : border ddd(t=0.5,1){x=0.5;y=t;label=2;};
6 : border eee(t=0.5,1){x=1-t;y=1;label=2;};
7 : border fff(t=0,1){x=0;y=1-t;label=2;};
8 : // generation du maillage
9 : mesh Th = buildmesh (aaa(6) + bbb(4) + ccc(4) +ddd(4) + eee(4) + fff(6));
10 : // sauvegarde
11 : savemesh(Th,"essai.msh");
12 : plot(Th);
13 : sizestack + 1024 =1352 ( 328 )
-- mesh: Nb of Triangles = 86, Nb of Vertices 58
number of required edges : 0
times: compile 0.016655s, execution 0.007361s, mpirank:0
CodeAlloc : nb ptr 3707, size :490840 mpirank: 0
Ok: Normal End
8.3.6.1. Exemple#
Maillage d’un cercle de rayon 1 (fichier cercle.edp)
border gamma(t=0,2*pi)
{ x=2*cos(t); y=2*sin(t);}
Th=buildmesh(gamma(20));
savemesh(Th,"cercle.msh");
G=mesh('cercle.msh')
G.plot()
8.3.7. Solveur EF FreeFem++#
Définition du problème
8.3.7.1. Formulation faible#
Trouvez \(u(x,y)\) tel que \(u_\Gamma = 0\)
8.3.7.2. Approximation avec des éléments \(P^1\)#
fespace Vh(Th,P1)
Vh u,v,f=1;
solve Lapace(u,v)= int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v))
- int2d(Th)(f*v) + on(Gamma,u=0);
%%bash
FreeFem++ -nw laplace.edp
-- FreeFem++ v4.9 ( - git no git)
Load: lg_fem lg_mesh lg_mesh3 eigenvalue
1 : // generation maillage cercle
2 : {
3 : verbosity=2;
4 : border gamma(t=0,2*pi)
5 : { x=2*cos(t); y=2*sin(t);}
6 : mesh Th=buildmesh(gamma(20));
7 : savemesh(Th,"cercle.msh");
8 : plot(Th);
9 :
10 : fespace Vh(Th,P1);
11 : Vh u,v,f=1;
12 :
13 : solve Lapace(u,v)= int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v))
14 : - int2d(Th)(f*v) + on(gamma,u=0);
15 : plot(u);
16 : }
17 : sizestack + 1024 =1856 ( 832 )
Nb of common points 1
-- mesh: Nb of Triangles = 68, Nb of Vertices 45
Nb of Vertices 45 , Nb of Triangles 68
Nb of edge on user boundary 20 , Nb of edges on true boundary 20
-- Mesh: Gibbs: old skyline = 501 new skyline = 323
number of required edges : 0
-- construction of the geometry from the 2d mesh
-- Writing the file cercle.msh of type msh NbOfTria = 68 NbOfRefEdge = 20
Plot bound [x,y] -2 -2 max [x,y] 2 2
-- vector function's bound 1 1
-- Change of Mesh 0 0x55efa9285db0
-- size of Matrix 0 Bytes
-- Solve :
min 4.04335e-31 max 0.998382
Plot bound [x,y] -2 -2 max [x,y] 2 2
times: compile 0.083123s, execution 0.153561s, mpirank:0
CodeAlloc : nb ptr 3656, size :490512 mpirank: 0
Ok: Normal End
8.3.7.3. Condition aux limites sur une frontière \(\Gamma_1\)#
Neuman ou Fourier
on(Gamma1,id(u)+a*dnu(u)=g)
Dirichlet
on(Gamma2,u=u0)
8.3.7.4. Formulation faible : intégrale#
int2d(Th)()
int(Gamma) ()
8.3.7.5. Liste des opérateurs#
id(), dx(), dy(), laplace(), dxx(), dyy(), dyx(), dxy()
ATTENTION:
dxy(u)*f = dx(f*dy(u))
laplace(u)*(x+y)=div((x+y)*grad(u))
8.3.7.6. Tracé et sauvegarde de la solution#
plot(Th);
plot(u);
8.3.8. Script Freefem#
8.3.8.1. Structure de données#
La géométrie éléments finis est stockée dans un fichier texte (avec une extension .msh) avec la structure de données suivante (format FreeFEM). Ce fichier contient les informations suivantes par ligne:
\(n_{s}\,\,\,\, n_{t}, \, nn_f \)
\(x_{1}\,\,\, y_{1}\,\,\,\,{nf}_{1}\)
…..
\(x_{i}\,\,\, y_{i}\,\,\,\,{nf}_{i}\)
…..
\(x_{n_{s}}\,\,\,\, y_{n_{s}}\,\,\,\,{nf}_{n_{s}}\)
\(tbc_{1,1}\,\,\, tbc_{1,2}\,\,\,\,\, tbc_{1,3}\,\,\,\,\, e_{1}\)
……
\(tbc_{k,1}\,\,\, tbc_{k,2}\,\,\,\,\, tbc_{k,3}\,\,\,\,\, e_{k}\)
……
\(tbc_{n_{t},1}\,\,\, tbc_{n_{t},2}\,\,\,\,\, tbc_{n_{t},3}\,\,\,\,\, e_{n_{t}}\)
où \(n_{s}\) est le nombre de sommets (noeuds) du maillage, \(n_{t}\) le nombre d’éléments et \(nn_f\) le nombre de noeuds sur la frontière. Pour chaque noeud \(i\) on donne les coordonnées \((x_{i},y_{i})\) ainsi que le numéro de la frontière ou se trouve le noeud \((nf_{i})\) (0 si le noeud est interne). Pour chaque élément \(k\), on a le numéro des 3 sommets \((tbc_{k,1}\,\,\, tbc_{k,2}\,\,\,\,\, tbc_{k,3})\) ainsi que le numéro de région \(e_{k}\).
Le fichier a donc \(1+n_{s}+n_{t}\) lignes.
8.3.8.2. maillage à partir de script généré sous Python#
from freefem import meshFreefem
# SCRIPT FREEFEM++
script="""
border aaa(t=0,1){x=t;y=0;label=2;};
border bbb(t=0,0.5){x=1;y=t;label=2;};
border ccc(t=0,0.5){x=1-t;y=0.5;label=2;};
border ddd(t=0.5,1){x=0.5;y=t;label=2;};
border eee(t=0.5,1){x=1-t;y=1;label=2;};
border fff(t=0,1){x=0;y=1-t;label=2;};
mesh Th = buildmesh (aaa(6) + bbb(4) + ccc(4) +ddd(4) + eee(4) + fff(6));
savemesh(Th,\"essai1.msh\");
"""
G=meshFreefem("essai1",script)
G.plot()
-- FreeFem++ v4.9 ( - git no git)
Load: lg_fem lg_mesh lg_mesh3 eigenvalue
1 :
2 : border aaa(t=0,1){x=t;y=0;label=2;};
3 : border bbb(t=0,0.5){x=1;y=t;label=2;};
4 : border ccc(t=0,0.5){x=1-t;y=0.5;label=2;};
5 : border ddd(t=0.5,1){x=0.5;y=t;label=2;};
6 : border eee(t=0.5,1){x=1-t;y=1;label=2;};
7 : border fff(t=0,1){x=0;y=1-t;label=2;};
8 : mesh Th = buildmesh (aaa(6) + bbb(4) + ccc(4) +ddd(4) + eee(4) + fff(6));
9 : savemesh(Th,"essai1.msh");
10 : sizestack + 1024 =1352 ( 328 )
-- mesh: Nb of Triangles = 86, Nb of Vertices 58
number of required edges : 0
times: compile 0.015369s, execution 0.009033s, mpirank:0
CodeAlloc : nb ptr 3705, size :490400 mpirank: 0
Ok: Normal End
script="""
border aa(t=0,2*pi) { x=2*cos(t); y=2*sin(t); label=1; };
border bb(t=0,2) {
if(t<=1) {
x= t-0.5;
y= 0.17735*sqrt(t)-0.075597*t-0.212836*(t^2)+0.17363*(t^3)-0.06254*(t^4);\
} else {
x= 2-t-0.5;
y= -(0.17735*sqrt(2-t)-0.075597*(2-t)-0.212836*((2-t)^2)+0.17363*((2-t)^3) - 0.06254*(2-t)^4);\
};
label=2; }
mesh Th=buildmesh(aa(40)+bb(41));
savemesh(Th,"naca.msh");
"""
G=meshFreefem("naca",script)
plt.figure(figsize=(14,8))
G.plot(front=False)
-- FreeFem++ v4.9 ( - git no git)
Load: lg_fem lg_mesh lg_mesh3 eigenvalue
1 :
2 : border aa(t=0,2*pi) { x=2*cos(t); y=2*sin(t); label=1; };
3 : border bb(t=0,2) {
4 : if(t<=1) {
5 : x= t-0.5;
6 : y= 0.17735*sqrt(t)-0.075597*t-0.212836*(t^2)+0.17363*(t^3)-0.06254*(t^4);} else {
7 : x= 2-t-0.5;
8 : y= -(0.17735*sqrt(2-t)-0.075597*(2-t)-0.212836*((2-t)^2)+0.17363*((2-t)^3) - 0.06254*(2-t)^4);};
9 : label=2; }
10 : mesh Th=buildmesh(aa(40)+bb(41));
11 : savemesh(Th,"naca.msh");
12 : sizestack + 1024 =1288 ( 264 )
-- mesh: Nb of Triangles = 1099, Nb of Vertices 590
number of required edges : 0
times: compile 0.01279s, execution 0.06644s, mpirank:0
CodeAlloc : nb ptr 3685, size :487584 mpirank: 0
Ok: Normal End
script="""
real a=2.,b=1.;
border Gamma(t=0,2*pi) { x = a * cos(t); y = b*sin(t); label=1; }
border Gamma2(t=0,2*pi) { x = 0.5 * cos(t); y = 0.5*sin(-t); label=2; }
// maillage
mesh Th=buildmesh(Gamma(40)+Gamma2(80));
savemesh(Th,"ellipse2.msh");
"""
G=meshFreefem("ellipse2",script)
plt.figure(figsize=(14,8))
G.plot(front=False)
-- FreeFem++ v4.9 ( - git no git)
Load: lg_fem lg_mesh lg_mesh3 eigenvalue
1 :
2 : real a=2.,b=1.;
3 : border Gamma(t=0,2*pi) { x = a * cos(t); y = b*sin(t); label=1; }
4 : border Gamma2(t=0,2*pi) { x = 0.5 * cos(t); y = 0.5*sin(-t); label=2; }
5 : // maillage
6 : mesh Th=buildmesh(Gamma(40)+Gamma2(80));
7 : savemesh(Th,"ellipse2.msh");
8 : sizestack + 1024 =1304 ( 280 )
-- mesh: Nb of Triangles = 762, Nb of Vertices 441
number of required edges : 0
times: compile 0.012498s, execution 0.052331s, mpirank:0
CodeAlloc : nb ptr 3619, size :486112 mpirank: 0
Ok: Normal End
8.3.9. Exemple: déformation d’une membrane#
from freefem import Freefem,readres
# execution script FreeFem avec lecture du resultat
script="""
real theta=4.*pi/3.;real a=2.,b=1.; func Z=0.;
border Gamma1(t=0,theta) { x = a * cos(t); y = b*sin(t); label=1; }
border Gamma2(t=theta,2*pi) { x = a * cos(t); y = b*sin(t); label=2; }
// maillage
mesh Th=buildmesh(Gamma1(40)+Gamma2(20));
savemesh(Th,"membrane.msh");
// solveur
fespace Vh(Th,P1);
Vh phi,w, f=1;
solve Laplace(phi,w)=int2d(Th)(dx(phi)*dx(w) + dy(phi)*dy(w)) - int2d(Th)(f*w) + on(Gamma2,phi=0) + on(Gamma1,phi=Z);
// ecriture resultat
{ ofstream ff("membrane.res");
ff<<phi[].n<<endl;
for(int i=0; i<phi[].n;i++) ff<<phi[][i]<<endl;
}
"""
Freefem("membrane",script,True)
G=mesh("membrane.msh")
G.info()
U=readres("membrane.res")
plt.figure(figsize=(16,8))
plt.subplot(1,2,1)
G.plot(False)
plt.subplot(1,2,2)
plt.axis('equal')
G.isosurf(U,"deformation")
Maillage membrane.msh
Nn,Ne= 235 408
Xmin/max Ymin/max= -1.99999929654 2.0 -0.999999665197 0.9999999163
surface 6.27170743614086
lecture resultat 235 235