FreeFem++ Tutorial 1
FreeFem++ Tutorial 1
Atsushi Suzuki1
1 Cybermedia Center, Osaka University
1 / 70
Numerical simulation with finite element method
I mathematical modeling
I discretization of time for evolution problem
I discretization scheme for the space
I mesh generation / adaptive mesh refinement
I stiffness matrix from finite elements and variational
formulation
I linear solver ⇐ CG, GMRES, direct solver: UMFPACK, MUMPS
FreeFem++ provides vast amounts of tools
I nonlinear solver
I optimization solver
2 / 70
Outline I
Weak formulation for partial differential equations with 2nd
order derivatives
Poisson equation with mixed boundary conditions
Stokes equations with mixed boundary conditions
magneto-static problem with Dirichlet boundary conditions
P1/P2 finite elements and numerical quadrature
Z Z Z
(−∂12
− ∂22 )u v dx
= (∂1 u∂1 v+∂2 u∂2 v) dx − (∂1 u n1 +∂2 u n2 )v ds
Ω Ω ∂Ω
Z Z
= ∇u · ∇v dx − ∇u · n v ds
Ω ΓD ∪ΓN
Z Z
v = 0 on ΓD ⇒ = ∇u · ∇v dx − hv ds
Ω ΓN
Find u ∈ V (g) s.t.
Z Z Z
∇u · ∇vdx = f vdx + h vds ∀v ∈ V (0)
Ω Ω ΓN
P span[ϕ1 , . . . , ϕN ] = Vh ⊂ V
finite element basis,
uh ∈ Vh ⇒ uh = 1≤i≤N ui ϕi
Dirichlet data : u(Pj ) = g(Pj ) Pj ∈ ΓD
FindZuh ∈ Vh (g) s.t. Z Z
∇uh · ∇vh dx = f vh dx + h vh ds ∀vh ∈ Vh (0).
Ω Ω ΓN
example1.edp varf+matrix
mesh Th=square(20,20);
fespace Vh(Th,P1);
Vh uh,vh;
func f=5.0/4.0*pi*pi*sin(pi*x)*sin(pi*y/2.0);
func g=sin(pi*x)*sin(pi*y/2.0);
func h=(-pi)/2.0*sin(pi*x);
solve poisson(uh,vh)=
int2d(Th)(dx(uh)*dx(vh)+dy(uh)*dy(vh))
- int2d(Th)(f*vh) - int1d(Th,1)(h*vh)
+ on(2,3,4,uh=g); // boundary 1 : (x,0)
plot(uh);
8 / 70
Stokes equations and a weak formulation : 1/3
Ω = (0, 1) × (0, 1)
−2∇ · D(u) + ∇p = f in Ω
∇ · u = 0 in Ω
u = g on ΓD ,
2D(u)n − n p = h on ΓN .
strain rate tensor : [D(u)]i j = 21 (∂i uj + ∂j ui ).
I V (g) = {v ∈ H 1 (Ω)2 ; v = g on ΓD }, V = V (0)
I Q = L2 (Ω)
weak formulation : Find (u, p) ∈ V (g) × Q s.t.
Z Z Z Z
2D(u) : D(v) dx − ∇ · v p dx = f · v dx + h · v dx ∀v ∈ V,
Ω Ω Ω ΓN
Z
− ∇ · u q dx = 0 ∀q ∈ Q.
Ω
9 / 70
Stokes equations and a weak formulation : 2/3
10 / 70
Stokes equations and a weak formulation : 3/3
Z Z Z
P P P
i (∂i p) vi dx = − p∂
i i iv dx + i p ni vi
Ω Ω ∂Ω
Z Z
= − p∇ · v + pn · v
Ω ∂Ω
On the boundary ∂Ω = ΓD ∪ ΓN ,
Z
(2D(u)n − n p) · v ds
ΓD ∪ΓN
Z Z
= (2D(u)n − n p) · v ds + (2D(u)n − n p) · v ds
ΓD ΓN
Z
= h · v ds. ⇐ V = {v ∈ H 1 (Ω)2 ; v = 0 on ∂Ω}.
ΓN
Remark
−2[∇ · D(u)]i = − j ∂j (∂i uj + ∂j ui ) = − j ∂j2 ui = −[4u]i .
P P
11 / 70
FreeFem++ script to solve Stokes equations by P2/P1
Find (u, p) ∈ Vh (g) × Qh s.t.
a(u, v) + b(v, p) + b(u, q) = (f, v) ∀(v, q) ∈ Vh × Qh .
example2.edp
fespace Vh(Th,P2),Qh(Th,P1);
func f1=5.0/8.0*pi*pi*sin(pi*x)*sin(pi*y/2.0)+2.0*x;
func f2=5.0/4.0*pi*pi*cos(pi*x)*cos(pi*y/2.0)+2.0*y;
func g1=sin(pi*x)*sin(pi*y/2.0)/2.0;
func g2=cos(pi*x)*cos(pi*y/2.0);
func h1=3.0/4.0*pi*sin(pi*x)*cos(pi*y/2.0);
func h2=pi*cos(pi*x)*sin(pi*y/2.0)+x*x+y*y;
Vh u1,u2,v1,v2; Qh p,q;
macro d12(u1,u2) (dy(u1) + dx(u2))/2.0 //
real epsln=1.0e-6;
solve stokes(u1,u2,p, v1,v2,q) =
int2d(Th)(2.0*(dx(u1)*dx(v1)+dy(u2)*dy(v2)+
2.0*d12(u1,u2)*d12(v1,v2))
-p*dx(v1)-p*dy(v2)-dx(u1)*q-dy(u2)*q)
- int2d(Th)(f1*v1+f2*v1) - int1d(Th,1)(h1*v1+h2*v1)
+ on(2,3,4,u1=g1,u2=g2);
plot([u1,u2],p,wait=1,value=true,coef=0.1);
12 / 70
stationary Navier-Stokes equations and a weak formulation
Ω = (0, 1) × (0, 1)
−2ν∇ · D(u) + u · ∇u + ∇p = f in Ω
∇ · u = 0 in Ω
u = g on ∂Ω
I V (g) = {v ∈ H 1 (Ω)2 ; v = gR on ∂Ω}, V = V (0)
I Q = L2 (Ω) = {p ∈ L2 (Ω) ;
Ω p dx = 0}
outflow
0
bi/tri-linear
Z forms and weak formulation :
a(u, v) = 2νD(u) : D(v) dx u, v ∈ H 1 (Ω)2
Ω Z
a1 (u, v, w) = (u · ∇v) · w u, v, w ∈ H 1 (Ω)2
Z Ω
b(v, p) = − ∇ · v p dx v ∈ H 1 (Ω)2 , p ∈ L2 (Ω)
Ω
Find (u, p) ∈ V (g) × Q s.t.
a(u, v) + a1 (u, u, v) + b(v, p) = (f, v) ∀v ∈ V,
b(u, q) = 0 ∀q ∈ Q.
13 / 70
magneto-static problem with Dirichlet b.c. : 1/2
constraints on the external force: ∇ · f = 0 in Ω ⊂ R3 .
∇ × (∇ × u) = f in Ω,
∇·u=0 in Ω,
u×n=0 on ∂Ω.
H0 (curl ; Ω) = {u ∈ L2 (Ω)3 ; ∇ × u ∈ L2 (Ω)3 ; u × n = 0}
find (u, p) ∈ H0 (curl ; Ω) × H01 (Ω)
(∇ × u, ∇ × v) + (v, ∇p) = (f, v) ∀v ∈ H0 (curl ; Ω)
(u, ∇q) = 0 ∀v ∈ H01 (Ω)
has a unique solution.
I ∇ · f = 0 ⇒ p = 0.
I (∇×·, ∇×·) : coercive on W .
W = H0 (curl ; Ω) ∩ {u ∈ H(div; Ω) ; div u = 0}.
I H0 (curl ; Ω) = gradH 1 (Ω) ⊕ W .
0
14 / 70
magneto-static problem with Dirichlet b.c. : 2/2
vector valued Sobolev space:
H(curl ; Ω) = {u ∈ L2 (Ω)3 ; ∇ × u ∈ L2 (Ω)3 }.
with essential boundary conditions on ∂Ω:
H0 (curl ; Ω) = {u ∈ L2 (Ω)3 ; ∇ × u ∈ L2 (Ω)3 ; u × n = 0}.
Z Z ∂1 u1 v1
∇ × u · vdx = ∂2 × u2 · v2 dx
Ω Ω ∂3 u3 v3
Z (∂2 u3 − ∂3 u2 )v1 +
= (∂3 u1 − ∂1 u3 )v2 + dx
Ω (∂1 u2 − ∂2 u1 )v3
Z (u3 ∂2 v1 − u2 ∂3 v1 )+ Z (n2 u3 − n3 u2 )v1 +
= − (u1 ∂3 v2 − u3 ∂1 v2 )+ dx + (n3 u1 − n1 u3 )v2 + ds
Ω (u2 ∂1 v3 − u1 ∂2 v3 ) ∂Ω (n1 u2 − n2 u1 )v3
Z Z
= u · ∇ × vdx + (n × u) · vds
Ω ∂Ω
15 / 70
stiffness matrix of magneto-static problem by FreeFem++
load "msh3"
load "Dissection"
defaulttoDissection;
mesh3 Th=cube(20,20,20);
fespace VQh(Th, [Edge03d, P1]); // Nedelec element
VQh [u1, u2, u3, p], [v1, v2, v3, q];
varf aa([u1, u2, u3, p], [v1, v2, v3, q]) =
int3d(Th)((dy(u3)-dz(u2)) * (dy(v3)-dz(v2)) +
(dz(u1)-dx(u3)) * (dz(v1)-dx(v3)) +
(dx(u2)-dy(u1)) * (dx(v2)-dy(v1)) +
dx(p)*v1+dy(p)*v2+dz(p)*v3 +
dx(q)*u1+dy(q)*u2+dz(q)*u3);
matrix A = aa(VQh, VQh, solver=sparsesolver,
tolpivot=1.0e-2,strategy=102);
Nédélec element of degree 0 and P1
N0 (K) = (P0 (K))3 ⊕ [x × (P0 (K))3 ], P1 (K)
fespace VQh(Th,[Edge03d,P1]);
16 / 70
P1 finite element and sparse matrix
Th : triangulation of a domain Ω, triangular element K ∈ Th
piecewise linear element : ϕi |K (x1 , x2 ) = a0 + a1 x1 + a2 x2
ϕi |K (Pj ) = δi j
Z X Z
[A]i j = a(ϕj , ϕi ) = ∇ϕj · ∇ϕi dx = ∇ϕj · ∇ϕi dx.
Ω K∈Th K
1
15 18 15 18
19 19
11 11
12 16 12 16
17 17
6 6
7 13 7 13
8 14 8 14
1 1
9 9
2 10 2 10
3 3
4 5 4 5
17 / 70
P2 finite element
Th : triangulation of a domain Ω, triangular element K ∈ Th
piecewise quadratic element : 6 DOF on element K.
ϕi |K (x1 , x2 ) = a0 + a1 x1 + a2 x2 + a3 x21 + a4 x1 x2 + a5 x22
ϕi |K (Pj ) = δi j 1
P1
5
6 λ3 λ2
3 λ1 P3
2 4 P2
( 6−21 √
15 6− 15 9+2 15
, 21
√
, 21√ ) 155− 15
1200
√
|K| ×3 λ 3 P λ 2
6+ 15 6+ 15 9−2 15 155+ 15
( 21 , 21 , 21 ) 1200 |K| ×3
P2 λ1 P3
Remark
it is not good idea to use interpolation of continuous function to
finite element space, for verification of convergence order.
|Πh u − uh |1,Ω may be smaller (in extreme cases, super convergence)
19 / 70
treatment of Neumann data around mixed boundary
Neumann data is evaluated by line integral with FEM basis ϕi .
Z
h ϕi ds
ΓN
Dirichlet
Neumann
Q
20 / 70
advantages of finite element formulation : 1/2
21 / 70
Outline
Weak formulation for partial differential equations with 2nd
order derivatives
P span[ϕ1 , . . . , ϕN ] = Vh ⊂ V
finite element basis,
uh ∈ Vh ⇒ uh = 1≤i≤N ui ϕi
finite element nodes {Pj }N j=1 , ϕi (Pj ) = δi j Lagrange element
ΛD ⊂ Λ = {1, . . . , N } : index of node on the Dirichlet boundary
X
Vh (g) = {uh ∈ Vh ; uh = ui ϕi , uk = gk (k ∈ ΛD )}
Find uh ∈ Vh (g) s.t.
a(uh , vh ) = F (vh ) ∀vh ∈ Vh (0).
Find {uj }, uk = gk (k ∈ ΛD ) s.t.
X X X
a( u j ϕj , vi ϕi ) = F ( vi ϕi ) ∀{vi }, vk = 0(k ∈ ΛD )
j i i
23 / 70
discretization and matrix formulation : 2/2
{uj }j∈Λ\ΛD s.t.
FindX X
a(ϕj , ϕi )uj = F (ϕi ) − a(ϕk , ϕi )gk ∀i ∈ Λ \ ΛD
j∈Λ\ΛD k∈ΛD
25 / 70
FreeFem++ script to solve Poisson eq. using matrix
Find uh ∈ Vh (g) s.t. a(uh , vh ) = F (vh ) ∀vh ∈ Vh (0).
example3.edp solve
Vh u,v;
varf aa(u,v)=int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))
+on(2,3,4,u=g);
varf external(u,v)=int2d(Th)(f*v)+int1d(Th,1)(h*v)
+on(2,3,4,u=g);
real tgv=1.0e+30;
matrix A = aa(Vh,Vh,tgv=tgv,solver=CG);
real[int] ff = external(0,Vh,tgv=tgv);
u[] = A^-1 * ff; // u : fem unknown, u[] : vector
plot(u);
useful liner solver; solver=
CG iterative solver for SPD matrix
GMRES iterative solver for nonsingular matrix
UMFPACK direct solver for nonsingular matrix
sparsesolver other solvers called by dynamic link
26 / 70
penalty method to solve inhomogeneous Dirichlet problem
modification of diagonal entries of A where index k ∈ ΛD
penalization parameter τ = 1/ε; tgv
τ uk τ gk , k ∈ Λ D
=
ui fi
[A]i j = a(ϕj , ϕi )
X X
τ uk + ak j uj = τ gk ⇔ uk − gk = ε(− ak j uj ),
j6=k j6=k
X
ai j uj = fi ∀i ∈ {1, . . . , N } \ ΛD .
j
k
l
28 / 70
conjugate gradient method
A~u = f~.
preconditioner Q ∼ A−1
Krylov subsp. : Kn (Q~r 0 , QA)=span[Q~r 0 , QAQ~r ,0. . . , (QA)n−1 Q~r 0 ]
Find ~u n ∈ Kn (Q~r 0 , QA) + ~u 0 s.t.
(A~u n − f~, ~v ) = 0 ∀~v ∈ Kn (Q~r 0 , QA).
Preconditioned CG method
~u 0 : initial step for CG.
~r 0 = f~ − A~u 0
p~ 0 = Q~r 0 .
loop n = 0, 1, . . .
αn = (Q~r n , ~r n )/(A~ p n , p~ n ),
~u n+1 n
= ~u + αn p~ , n
~r n+1 = ~r n − αn A~ p n,
if ||~r n+1 || < exit loop.
βn = (Q~r n+1 , ~r n+1 )/(Q~r n , ~r n ),
p~ n+1 = Q~r n+1 + βn p~ n .
LinearCG(opA,u,f,precon=opQ,nbiter=100,eps=1.0e-10)
29 / 70
GMRES method : 1/2
Krylov subspace : Kn (~r 0 , A) = span[~r 0 , A~r 0 , . . . , An−1~r 0 ]
Find ~u n ∈ Kn (~r 0 , A) + ~u 0 s.t.
||A~u n − f~|| ≤ ||A~v n − f~|| ∀~v ∈ Kn (~r 0 , A) + ~u 0 .
Vm : Arnoldi basis generated by Gram-Schmidt orthogonization
for Krylov vectors.
~u = Vm ~y , ~y ∈ Rm J(~y ) := ||AVm ~y − ~r0 ||
T
= ||Vm+1 (AVm ~y − ~r0 )||
T T
= ||(Vm+1 AVm )~y − (Vm+1 ~r0 )||
= ||H̄m ~y − β~e1 || . (β = ||~r0 ||)
32 / 70
Outline
Weak formulation for partial differential equations with 2nd
order derivatives
36 / 70
mesh adaptation
fespace XXMh(Th,[P2,P2,P1]);
XXMh [u1,u2,p];
real lerr=0.01;
Th=adaptmesh(Th, [u1,u2], p, err=lerr, nbvx=100000);
[u1,u2,p]=[u1,u2,p]; // interpolation on the new mesh
38 / 70
Outline
Weak formulation for partial differential equations with 2nd
order derivatives
quadrature qf5pT
44 / 70
procedure and CG built-in function : 1/2
int n = 20; example5.edp varf+matrix
mesh Th=square(n,n);
fespace Vh(Th,P1); Vh u,v;
func f = 5.0/4.0*pi*pi*sin(pi*x)*sin(pi*y/2.0);
func h = (-pi)/2.0*sin(pi*x);
func g = sin(pi*x)*sin(pi*y/2.0);
varf aa(u,v) = int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))
+ on(2,3,4,u=1.0);
varf external(u,v) = int2d(Th)(f*v) + int1d(Th,1)(h*v);
real tgv=1.0e+30;
matrix A;
real[int] bc = aa(0, Vh, tgv=tgv);
func real[int] opA(real[int] &pp)
{
pp = bc ? 0.0 : pp; // SpMV operation only for inner
real[int] qq = A * pp;// node without Dirichlet bdry.
pp = bc ? 0.0 : qq;
return pp;
}
45 / 70
procedure and CG built-in function : 2/2
func real[int] opQ(real[int] &pp) // diagonal scaling
{
for (int i = 0; i < pp.n; i++) {
pp(i) = pp(i) / A(i, i);
}
pp = bc ? 0.0 : pp;
return pp;
}
46 / 70
Outline
Weak formulation for partial differential equations with 2nd
order derivatives
Ω2
Ω1
Jacobi-Schwarz algorithm
u01 , u02 : given
loop n = 0, 1, 2, · · ·
−4un+1 1 = f in Ω1 −4un+1
2 = f in Ω2
un+1
1 = 0 on ∂Ω1 ∩ ∂Ω un+1
2 = 0 on ∂Ω2 ∩ ∂Ω
un+1
1 = un2 on ∂Ω1 ∩ Ω̄2 un+1
2 = un1 on ∂Ω2 ∩ Ω̄1
48 / 70
Restricted Additive Schwarz algorithm : 1/2
partition
P of unity
u = 2i=1 Ei (χi ui )
I Ei : extension from Ωi to Ω
I χi : partition of unity function in Ω̄i
loop n = 0, 1, 2, · · ·
−4win+1 = f in Ωi
win+1 = 0 on ∂Ωi ∩ ∂Ω
win+1 = un on ∂Ωi ∩ Ω̄j
P2 n+1
un+1 = i=1 Ei (χi wi )
by substituting 4un that satisfies un = 0 on ∂Ωi ∩ ∂Ω
−4win+1 + 4un = f + 4un in Ωi
win+1 − un = 0 on ∂Ωi ∩ ∂Ω, win+1 − un = 0 on ∂Ωi ∩ Ω̄j
49 / 70
Restricted Additive Schwarz algorithm : 2/2
Restricted additive Schwarz (RAS) algorithm
u01 , u02 : given
loop n = 0, 1, 2, · · ·
rn = f + 4un
−4vin+1 = rn in Ωi
vin+1 = 0 on ∂Ωi
2
X
u n+1 n
=u + Ei (χi vin+1 )
i=1
50 / 70
Additive Schwarz algorithm
loop n = 0, 1, 2, · · ·
−4win+1 = f in Ωi
win+1 = 0 on ∂Ωi ∩ ∂Ω
win+1 = un on ∂Ωi ∩ Ω̄j
P2 n+1
un+1 = i=1 Ei (wi )
51 / 70
Schwarz methods as preconditioner
ASM preconditioner
M
X
−1
MASM = RpT (Rp ARpT )−1 Rp
p=1
−1
ASM does not converge as fixed point iteration, but MASM is
symmetric and works well as a preconditioner for CG method.
RAS preconditioner
M
X
−1
MRAS = RpT Dp (Rp ARpT )−1 Rp
p=1
−1
RAS does converge but MRAS is not symmetric and then works
as a preconditioner for GMRES method.
convergence of ASM, RAS: slow for many subdomains
⇒ coarse space
52 / 70
2-level Schwarz methods with a coarse space
coarse space by Nicolaides
Dp : discrete representation
PM of the partition of unity
R TD R = I ,
p=1 p p p N
R0 = Z T .
2-level ASM preconditioner
M
X
−1
MASM,2 = R0T (R0 AR0T )−1 R0 + RpT (Rp ARpT )−1 Rp
p=1
53 / 70
FreeFem++ script for a 3D domain computation
Subdomain problems : solved by a direct solver example6.edp
54 / 70
Outline
Weak formulation for partial differential equations with 2nd
order derivatives
Γ4 ω Γ2
Γ1
∂u
+ u · ∇u − 2ν∇ · D(u) + ∇p = 0 in Ω
∂t
∇ · u = 0 in Ω
u = g on ∂Ω
boundary conditions:
Poiseuille flow on Γ4 : u = (1 − y 2 , 0).
u·n=0
slip boundary condition on Γ1 ∪ Γ3 :
(2νD(u)n − np) · t = 0
no-slip boundary condition on ω : u = 0
outflow boundary condition on Γ2 : 2νD(u)n − np = 0
56 / 70
slip boundary conditions and function space
Γ3
Γ4 ω Γ2
Γ1
u·n=0
slip boundary condition on Γ1 ∪ Γ3 :
(2ν D(u)n − n p) · t = 0
I V (g) = {v ∈ H 1 (Ω)2 ; v = g on Γ4 ∪ ω, v · n = 0 on Γ1 ∪ Γ3 },
Z I Q = L2 (Ω). Z non-slip
57 / 70
characteristic line and material derivative
u(x1 , x2 , t) : Ω × (0, T ] → R2 , given velocity field.
φ(x1 , x2 , t) : Ω × (0, T ] → R.
X(t) : (0, T ] → R2 , characteristic curve :
dX
(t) = u(X(t), t), X(0) = X0
dt
d d ∂
φ(X(t), t) =∇φ(X(t), t) · X(t) + φ(X(t), t)
dt dt ∂t
∂
=∇φ(X(t), t) · u(X(t), t) + φ(X(t), t)
∂t
Dφ ∂
material derivative : = φ + u · ∇φ.
Dt ∂t
approximation by difference
Dφ(X(t), t) φ(X(t), t) − φ(X(t − ∆t), t − ∆t)
∼
Dt ∆t
58 / 70
characteristic Galerkin method to discretized material derivative
approximation by Euler method : L3
L2
X n (x) = x − u(x, tn ) 5L L
6
59 / 70
FreeFem++ script using characteristic Galerkin method
FreeFem++ provides convect to compute (un ◦ X n , ·).
real nu=1.0/Re; example7.edp
real alpha=1.0/dt;
int i;
problem NS([u1,u2,p],[v1,v2,q],solver=UMFPACK,init=i) =
int2d(Th)(alpha*(u1*v1 + u2*v2)
+2.0*nu*(dx(u1)*dx(v1)+2.0*d12(u1,u2)*d12(v1,v2)
+dy(u2)*dy(v2))
- p * div(v1, v2) - q * div(u1, u2))
- int2d(Th)(alpha*( convect([up1,up2],-dt,up1)*v1
+convect([up1,up2],-dt,up2)*v2) )
+ on(1,3,u2=0)+on(4,u1=1.0-y*y,u2=0)+on(5,u1=0,u2=0);
60 / 70
FreeFem++ script for mesh generation around a cylinder
Delaunay triangulation from nodes given on the boundary
boundary segments are oriented and should be connected.
int n1 = 30;
int n2 = 60;
border ba(t=0,1.0){x=t*10.0-1.0;y=-1.0;label=1;};
border bb(t=0,1.0){x=9.0;y=2.0*t-1.0;label=2;};
border bc(t=0,1.0){x=9.0-10.0*t;y=1.0;label=3;};
border bd(t=0,1.0){x=-1.0;y=1.0-2.0*t;label=4;};
border cc(t=0,2*pi){x=cos(t)*0.25+0.75;
y=sin(t)*0.25;label=5;};
mesh Th=buildmesh(ba(n2)+bb(n1)+bc(n2)+bd(n1)+cc(-n1));
plot(Th);
61 / 70
stream line for visualization of flow around a cylinder : 1/2
∂2 ψ
stream function ψ : Ω → R, u = .
−∂1 ψ
boundary conditions for the stream line:
Z y Z y
y3
inlet: y − = u1 (x1 , t)dt = ∂2 ψ(x1 , t)dt = ψ(x1 , y) − ψ(x1 , 0)
3 0 0
y3 y3
ψ(x1 , y) = ψ(x1 , 0) + y − =y− .
3 3
Z x Z x
slip: 0 = u2 (t, ± 1)dt = −∂1 ψ(t, ±1)dt = ψ(x1 , ±1) − ψ(x, ±1)
x1 x1
ψ(x, ±1) = ψ(x1 , ±1) = ψ(x1 , 0) ± 2/3 = ±2/3.
Z θ Z θ
cylinder: 0 = u · n dθ = −∂1 ψ r sin θ + ∂2 ψ r cos θ
−π −π
Zθ
∂
= ψ(r, θ)dθ.
−π ∂θ
center from inlet: u2 = 0 ⇒ same as slip wall ,
ψ|ω = ψ(x1 , 0) = 0. 62 / 70
stream line for visualization of flow around a cylinder : 2/2
Γ3
Γ4 ω Γ2
Γ1
slip boundary condition on Γ1 ∪ Γ3 , outflow on Γ2 .
63 / 70
Outline
Weak formulation for partial differential equations with 2nd
order derivatives
Γ4 : ∂n θ = 0, u1 = 0 Γ2 : ∂n θ = 0, u1 = 0
Γ1 : θ = θ0 + ∆θ, u2 = 0
Rayleigh-Bénard equations
∂u
ρ + u · ∇u − 2∇ · µ0 D(u) + ∇p = −ρ g~e2 in Ω ,
∂t
∇ · u = 0 in Ω ,
∂θ
+ u · ∇θ − ∇ · (κθ) = 0 in Ω .
∂t
~e2 : unit normal of y-direction
d : height of the box, g : gravity acceleration,
κ : thermal diffusivity, µ0 : viscosity
65 / 70
thermal convection in a box : 2/2
Boussinesq approximation : ρ = ρ0 {1 − α(θ − θ0 )}, θ0 = 0.
ρ0 : representative density, α : thermal expansion coefficient.
non-dimensional Rayleigh-Bénard equations
1 ∂u
+ u · ∇u − 2∇ · D(u) + ∇p = Raθ~e2 in Ω ,
P r ∂t
∇ · u = 0 in Ω ,
∂θ
+ u · ∇θ − 4θ = 0 in Ω
∂t
u · n = 0 on ∂Ω ,
θ = 1 on Γ1 ,
θ = 0 on Γ3 ,
µ0 ∂n θ = 0 on Γ2 ∪ Γ4 .
I Pr = : Prandtl number,
κρ0
ρ0 gα∆θd3
I Ra = : Rayleigh number.
κµ0
66 / 70
a weak form to solve time-dependent Rayleigh-Bénard eqs.
I velocity : V = {v ∈ H 1 (Ω)2 ; v · n = 0 Ron ∂Ω},
I pressure : Q = L2 (Ω) = {p ∈ L2 (Ω) ;
0 Ω p dx = 0},
I temperature : ΨD = {θ ∈ H 1 (Ω) ; θ = 1 on Γ1 , θ = 0 on Γ3 }.
bilinear forms:
R R
a0 (u, v) = RΩ 2D(u) : D(v), b(v, p) = − Ω ∇ · v p,
c0 (θ, ψ) = Ω ∇θ · ∇ψ.
using Characteristic Galerkin method: example8.edp
n n
(u , θ ) ∈ V × ΨD : from previous time step
Find (un+1 , pn+1 , θn+1 ) ∈ V × Q × ΨD s.t.
n+1
− un ◦ X n
1 u
, v + a0 (un+1 , v) + b(v, pn+1 ) = Ra(θn~e2 , v)
Pr ∆t
∀v ∈ V,
b(un+1 , q) = 0 ∀q ∈ Q,
θn+1 − θn ◦ X n
, ψ + c0 (θn+1 , ψ) = 0 ∀ψ ∈ Ψ0 .
∆t
67 / 70
a weak form to solve stationary Rayleigh-Bénard eqs.
trilinear forms and bilinear form for the Navier-Stokes eqs.
I a1 (u, v, w) = 1
R
P r Ω (u · ∇v) · w
R
Ω (u · ∇θ) · ψ
I c1 (u, θ, ψ) =
loop n = 0, 1 . . .
Find (δu, δp, δθ) ∈ V × Q × Ψ0 s.t.
a0 (δu, v) + b(v, δp) + b(δu, q) + a1 (δu,un , v) + a1 (un , δu, v)
−Ra(δθ~e2 , v) = A(un , pn ; v, q) − Ra(θn~e2 , v) ∀(v, q) ∈ V × Q
c0 (δθ, ψ) + c1 (un , δθ, ψ) + c1 (δu, θn , ψ) = c0 (θn , ψ) + c1 (un , θn , ψ)
∀ψ ∈ Ψ0
if ||(δu, δp, δθ)||V ×Q×Ψ ≤ ε then break
un+1 = un − δu, pn+1 = pn − δp, θn+1 = θn − δθ.
loop end.
initial data ⇐ stationary solution by time-dependent problem.
68 / 70
Application of finite element method to fluid problems
Time-dependent Navier-Stokes equations
I material derivative is approximated by Characteristic
Galerkin method
I functional space of pressure depends on boundary
conditions of flow, e.g., inflow, non-slip, slip, and outflow.
69 / 70
References
FreeFem++:
I F. Hecht, FreeFem++ manual, 3rd ed., 2015.
I K. Ohtsuka, T. Takaishi, Finite element analysis by
mathematical programming language FreeFem++ (in
Japanese), Industrial and Applied Mathematics Series
Vol.4, Kyoritsu, 2014.
I I. Danaila, F. Hecht, O. Pironneau, Simulation numérique
en C++, Dunod, 2003.
Finite element theory:
I D. Braess, Finite elements – Theory, fast solvers and
application in solid mechanics, 3rd ed., Cambridge Univ.
Press, 2007.
I A. Ern, J.-L. Guermond, Theory and practice of finite
elements, Springer Verlag, New-York, 2004.
I M. Tabata, Numerical solution of partial differential
equations II (in Japanese), Iwanami Shoten, 1994.
70 / 70
example1.edp 1/1
// example 1 : poisson-mixedBC.edp [slide page 8]
// finite element solution of Poisson equation with mixed boundary condition
// for RIIT Tutorial at Kyushu University, 25 Nov.2016, Atsushi Suzuki
int n = 20;
mesh Th=square(n,n);
fespace Vh(Th,P1);
Vh uh,vh;
real err, hh;
solve poisson(uh,vh) =
int2d(Th)( dx(uh)*dx(vh)+dy(uh)*dy(vh) )
- int2d(Th)( f*vh )
- int1d(Th,1) (h * vh)
+ on(2,3,4,uh=g);
cout << "DOF=" << uh[].n << "\t h=" << hh << " err-H1=" << err << endl;
plot(uh,wait=1);
example2.edp 1/2
// example 2 : stokes-mixedBC.edp [slide page 12]
// error estimation for finite element solution of Stokes equations
// with P2/P1 or P1b/P1 element
// for RITT Tutorial at Kyushu University, 25 Nov.2016, Atsushi Suzuki
int n1 = 20;
int n2 = n1 * 2;
mesh Th1=square(n1,n1);
mesh Th2=square(n2,n2);
// fespace Vh1(Th1,P1),Qh1(Th1,P1);
// fespace Vh2(Th2,P1),Qh2(Th2,P1);
// fespace Vh1(Th1,P2),Qh1(Th1,P0);
// fespace Vh2(Th2,P2),Qh2(Th2,P0);
// external force
func f1 = 5.0/8.0 * pi * pi * sin(pi * x) * sin(pi * y / 2.0) + 2.0 * x;
func f2 = 5.0/4.0 * pi * pi * cos(pi * x) * cos(pi * y / 2.0) + 2.0 * y;
func h1 = 3.0/4.0 * pi * sin(pi * x) * cos(pi * y / 2.0);
func h2 = pi * cos(pi * x) * sin(pi * y / 2.0) + x * x + y * y;
func sol1 = sin(pi * x) * sin(pi * y / 2.0) / 2.0;
func sol2 = cos(pi * x) * cos(pi * y / 2.0);
func solp = x * x + y * y;
// stokes problem
solve stokes1(u11,u12,p1, v11,v12,q1) =
int2d(Th1)(
2.0*(d11(u11)*d11(v11)+2.0*d12(u11,u12)*d12(v11,v12)+d22(u12)*d22(v12))
- p1*dx(v11) - p1*dy(v12)
- dx(u11)*q1 - dy(u12)*q1)
- int2d(Th1)(f1*v11+f2*v12) - int1d(Th1,1)(h1*v11+h2*v12)
+ on(2,3,4,u11=sol1,u12=sol2);
real meanp,err1,err2,hh1,hh2;
plot([u11,u12],p1,wait=1,value=true,coef=0.1);
plot([u21,u22],p2,wait=1,value=true,coef=0.1);
example2.edp 2/2
err2 = sqrt(err2);
cout << "coarse mesh: h=" << hh1 << " err-H1/L2=" << err1 << endl;
cout << "fine mesh: h=" << hh2 << " err-H1/L2=" << err2 << endl;
cout << "O(h)=" << log(err1/err2)/log(hh1/hh2) << endl;
example3.edp 1/1
// example 3 : poisson-matrix.edp [slide page 26]
// finite element solution of Poisson equation with mixed boundary condition
// with P1 element
// for RIIT Tutorial at Kyushu University, 25 Nov.2016, Atsushi Suzuki
int n = 20;
mesh Th=square(n,n);
fespace Vh(Th,P1);
Vh u,v;
real err, hh;
cout << "DOF=" << u[].n << "\t h=" << hh << " err-H1=" << err << endl;
example4.edp 1/2
// example 4 : cavityNewton.edp [slide page 36]
// stational Navier-Stokes equations in a cavity by Newton iteration
// P2/P1 element
// for RIIT Tutorial at Kyushu University, 25 Nov.2016, Atsushi Suzuki
// based on examples++-tutorial/cavityNewtow.edp
mesh Th=square(40,40);
fespace Xh(Th,P2);
fespace Mh(Th,P1);
fespace XXMh(Th,[P2,P2,P1]);
XXMh [u1,u2,p], [v1,v2,q];
Mh psi,phi;
problem streamlines(psi,phi,solver=UMFPACK) =
int2d(Th)( dx(psi)*dx(phi) + dy(psi)*dy(phi))
+ int2d(Th)( -phi*(dy(u1)-dx(u2)))
+ on(1,2,3,4,psi=0);
streamlines;
plot(psi,wait=1);
real nu=1.0;
XXMh [up1,up2,pp];
varf vDNS ([u1,u2,p],[v1,v2,q]) =
int2d(Th)(nu * 2.0*(d11(u1)*d11(v1)+2.0*d12(u1,u2)*d12(v1,v2)+d22(u2)*d22(v2))
- p * div(v1, v2) - q * div(u1, u2)
- p * q * epsln
+ Ugrad(u1,u2,up1,up2)’*[v1,v2] //’
+ Ugrad(up1,up2,u1,u2)’*[v1,v2]) //’
+ on(1,2,3,4,u1=0,u2=0);
int n = 20;
mesh Th=square(n,n);
fespace Vh(Th,P1);
Vh u,v;
real err, hh;
real tgv=1.0e+30;
matrix A;
real[int] bc = aa(0, Vh, tgv=tgv);
cout << "DOF=" << u[].n << "\t h=" << hh << " err-H1=" << err << endl;
Schwarz3d.edp 1/5
// example6 : Schwarz3d [slide page 54]
// Schwarz preconiditoner for Krylov method
// for RIIT Tutorial at Kyushu University, 25 Nov.2016, Atsushi Suzuki
// based on FreeFem++ manual, section 10 and
// scripts in An Introduction to Domain Decomposition Methods --
// Algorithms, Theory, and Parallel Implementation,
// V. Dolean, P Jolivet, F. Nataf, SIAM 2015, ISBN 978-1-611974-05-8
load "medit";
load "metis";
include "cube.idp"
bool flagRAS=false;
int sizeoverlaps=1; // size of overlap
int[int] NN=[50,50,50]; //
bool withmetis=true;
int npart= 8;
func bool SubdomainsPartitionUnity(mesh3 & Th, int nnpart, real[int] & partdof,
int sizeoverlaps,
mesh3[int] & Tha,
matrix[int] & Rih, matrix[int] & Dih)
{
fespace Vh(Th,P1);
fespace Ph(Th,P0);
mesh3 Thi=Th;
fespace Vhi(Thi,P1); // FreeFem++ trick, formal definition
Vhi[int] pun(nnpart), dum(nnpart); // local fem functions Vh sun=0, unssd=s0;
Vh sun = 0, unssd = 0, demo = 0;
Ph part;
part[]=partdof;
for(int i=0;i<nnpart;++i) {
Ph suppi= abs(part - i) < 0.1; // boolean 1 in the subdomain 0 elsewhere
AddLayers(Th,suppi[],sizeoverlaps); // partitions by adding layers
Thi=Tha[i]=trunc(Th,suppi>0,label=10,split=1); // mesh interfaces label 10
Rih[i]=interpolate(Vhi,Vh,inside=true); // Restriction operator : Vh to Vhi
pun[i][] = 1.0;
sun[] += Rih[i]’*pun[i][]; // ’
}
for(int i=0;i<nnpart;++i) {
Thi=Tha[i];
// medit("Thi"+i,Thi);
pun[i]= pun[i]/sun;
Dih[i]=pun[i][]; //diagonal matrix built from a vector if(verbosity > 1)
dum[i] = (pun[i] == 1.0 ? 0.0 : pun[i]);
demo[] += Rih[i]’*dum[i][];
}
Schwarz3d.edp 2/5
plot(demo,cmm="overlapped skelton",wait=1);
return true;
}
Ph part;
Vh sun=0,unssd=0;
Ph xx=x,yy=y;
if (withmetis) {
int[int] nupart(Thg.nt);
metisdual(nupart,Thg,npart);
for(int n=0;n<nupart.n; n++)
part[][n]=nupart[n];
}
//plot(part,fill=1,cmm="subdomains",wait=false);
mesh3[int] aTh(npart);
matrix[int] Rih(npart);
matrix[int] Dih(npart);
matrix[int] aA(npart);
real[int] partdof(npart);
Vh[int] Z(npart); // coarse space : only used as set of arrays
matrix E;
//plot(part,fill=1,cmm="subdomains",wait=1);
Vh un;
un = 0.0;
LinearCG(opA, un[], rhsglobal[], nbiter=200, precon=opASM,
eps=1.0e-10,verbosity=50);
un = 0.0;
LinearCG(opA, un[], rhsglobal[], nbiter=200, precon=opASM2,
eps=1.0e-10,verbosity=50);
un = 0.0;
Schwarz3d.edp 5/5
LinearCG(opA, un[], rhsglobal[], nbiter=200, precon=opASMQ,
eps=1.0e-10,verbosity=50);
plot(un,value=1,fill=1,wait=1,cmm="solution by CG-ASM",dim=3);
un = un - uglob;
plot(un,value=1,fill=1,wait=1,cmm="error of CG-ASM",dim=3);
}
example7.edp 1/2
// example 7 : NS-cylinder.edp [slide page 60]
// Navier-Stokes flow around a cylinder
// P2/P1 element with Characteristic Galerkin
// for RIIT Tutorial at Kyushu University, 25 Nov.2016, Atsushi Suzuki
int n1 = 30;
int n2 = 60;
real nu = 1.0/400.0;
real dt = 0.05;
real alpha = 1.0/dt;
int timestepmax = 400;
border ba(t=0,1.0){x=t*10.0-1.0;y=-1.0;label=1;};
border bb(t=0,1.0){x=9.0;y=2.0*t-1.0;label=2;};
border bc(t=0,1.0){x=9.0-10.0*t;y=1.0;label=3;};
border bd(t=0,1.0){x=-1.0;y=1.0-2.0*t;label=4;};
border cc(t=0,2*pi){x=cos(t)*0.25+0.75;y=sin(t)*0.25;label=5;};
mesh Th=buildmesh(ba(n2)+bb(n1)+bc(n2)+bd(n1)+cc(-n1));
plot(Th);
fespace Xh(Th,[P2,P2,P1]);
fespace Vh(Th,P2);
fespace Qh(Th,P1);
Xh [u1,u2,p], [v1,v2,q];
Vh up1, up2;
Qh pp;
macro d11(u1) dx(u1) //
macro d22(u2) dy(u2) //
macro d12(u1,u2) (dy(u1) + dx(u2))/2.0 //
macro div(u1,u2) (dx(u1) + dy(u2)) //
Qh psi,phi;
func stinflow=y-y*y*y/3.0;
problem streamlines(psi,phi,solver=UMFPACK) =
int2d(Th)( dx(psi)*dx(phi) + dy(psi)*dy(phi))
+ int2d(Th)( phi*(dy(u1)-dx(u2)))
+ on(1,psi=(-2.0/3.0))
+ on(4,psi=stinflow)
+ on(3,psi=(2.0/3.0))
+ on(5,psi=0.0);
streamlines;
plot(psi,wait=1);
problem Stokes([u1,u2,p],[v1,v2,q],solver=UMFPACK) =
int2d(Th)(
+ 2.0*nu * (d11(u1)*d11(v1)+2.0*d12(u1,u2)*d12(v1,v2)+d22(u2)*d22(v2))
- p * div(v1, v2) - q * div(u1, u2)) //
+ on(1,3,u2=0)
+ on(4,u1=1.0-y*y,u2=0)
+ on(5,u1=0,u2=0);
int i;
problem NS([u1,u2,p],[v1,v2,q],solver=UMFPACK,init=i) =
int2d(Th)( alpha * (u1*v1 + u2*v2)
+ 2.0*nu * (d11(u1)*d11(v1)+2.0*d12(u1,u2)*d12(v1,v2)+d22(u2)*d22(v2))
- p * div(v1, v2) - q * div(u1, u2))
- int2d(Th)( alpha * (convect([up1,up2],-dt,up1)*v1
+convect([up1,up2],-dt,up2)*v2) )
+ on(1,3,u2=0)
+ on(4,u1=1.0-y*y,u2=0)
+ on(5,u1=0,u2=0);
plot(Th,wait=1);
Stokes;
for (i = 0; i < timestepmax; i++) {
up1 = u1;
example7.edp 2/2
up2 = u2;
pp = p;
NS;
streamlines;
plot(psi, nbiso=30,wait=0);
if (i % 20 == 0) {
plot([up1,up2],pp,wait=0,value=true,coef=0.1);
}
}
example8.edp 1/2
// example 8 : RayleighBenard.edp [slide page 69]
// Rayleigh-Benard thermal convection in a box
// P2/P1/P2 element with Characteristic Galerkin
// time evolution data will be stored in "rb.data" for Rayleigh-Benard-stat.edp
// for RIIT Tutorial at Kyushu University, 25 Nov.2016, Atsushi Suzuki
int n1 = 80;
int n2 = 20;
real Pr = 0.71;
real Ra = 1500.0;
real dt = 0.01;
real alpha = 1.0/(dt * Pr);
int timestepmax = 600;
mesh Th=square(n1,n2,[x*4.0,y]);
fespace Xh(Th,[P2,P2,P1]);
fespace Vh(Th,P2);
fespace Qh(Th,P1);
problem Heat(th,psi,solver=UMFPACK,init=i) =
int2d(Th)(alpha * (th * psi)
+ dx(th) * dx(psi) + dy(th) * dy(psi))
- int2d(Th)(alpha * convect([up1, up2], -dt, thp) * psi)
+ on(1,th=1)
+ on(3,th=0);
problem streamlines(ss,rr,solver=UMFPACK) =
int2d(Th)( dx(ss)*dx(rr) + dy(ss)*dy(rr))
+ int2d(Th)( rr*(dy(u1)-dx(u2)))
+ on(1,2,3,4,ss=0.0);
plot(Th,wait=1);
int n1 = 80;
int n2 = 20;
real Pr = 0.71;
real Ra = 1500.0;
int timestepmax = 600;
mesh Th=square(n1,n2,[x*4.0,y]);
fespace Wh(Th,[P2,P2,P1,P2]);
fespace Vh(Th,P2);
fespace Qh(Th,P1);
problem streamlines(ss,rr,solver=UMFPACK) =
int2d(Th)( dx(ss)*dx(rr) + dy(ss)*dy(rr))
+ int2d(Th)( rr*(dy(up1)-dx(up2)))
+ on(1,2,3,4,ss=0.0);
plot(Th,wait=1);
// read stationary data computed by RayleighBenrad.edp
{
ifstream file("rb.data", binary);
example9.edp 2/2
for (int i = 0; i < up1[].n; i++) {
file >> up1[](i);
}
for (int i = 0; i < up2[].n; i++) {
file >> up2[](i);
}
for (int i = 0; i < pp[].n; i++) {
file >> pp[](i);
}
for (int i = 0; i < thp[].n; i++) {
file >> thp[](i);
}
}