Fenics Tutorial
Fenics Tutorial
Patrick Farrell
Oxford
May 2017
I C++/Python library
I Began in 2003
I Thousands of downloads/month
I Developers all over the world
I Licensed under the GNU LGPL
http://fenicsproject.org/
−∆u = f in Ω
u = 0 on ∂Ω
In weak form, the equation is: find u ∈ H01 (Ω) such that
Z Z
∇u · ∇v dx = f v dx
Ω Ω
Vh ⊂ V
for all vh ∈ Vh .
We construct a test problem for which we can easily check the answer. We
first define the exact solution by
u(x, y) = 1 + x2 + 2y 2
u = Function(V)
v = TestFunction(V)
f = Constant(-6.0)
g = 1 + x**2 + 2*y**2
bc = DirichletBC(V, g, DomainBoundary())
solve(F == 0, u, bc)
File("poisson.pvd") << u
P. E. Farrell (Oxford) Practical I May 2017 8 / 20
Step by step: the first line
The first argument specifies the family of element, while the third
argument is the degree of the basis functions on the element.
Another way:
g = Expression("1 + x[0]*x[0] + 2*x[1]*x[1]",
element=V.ufl_element())
The Expression class is very flexible and can be used to create complex
user-defined expressions: looking up information from a database or the
internet, solving a local problem for material parameters, etc.
Note that the above line does not yet apply the boundary condition to all
functions in the function space. (It gets enforced strongly during solve.)
Other examples:
"near(x[0], 0.0)"
"near(x[0], 0.0) || near(x[1], 1.0)"
or (more efficiently) as
f = Constant(-6.0)
We now have all the objects we need in order to specify the form:
F = inner(grad(u), grad(v))*dx - f*v*dx
Here dx is a type of class Measure that means ”integrate over the whole
volume”. There are other measures: for example, ds means ”integrate
over exterior facets”.
Nice!
u = Function(V)
v = TestFunction(V)
f = Constant(-6.0)
g = 1 + x**2 + 2*y**2
bc = DirichletBC(V, g, DomainBoundary())
solve(F == 0, u, bc)
File("poisson.pvd") << u
P. E. Farrell (Oxford) Practical I May 2017 19 / 20
FEniCS 01 Challenge!
Patrick Farrell
Oxford
May 2017
We want to construct
g = BoundaryData(degree=5)
Patrick Farrell
Oxford
May 2017
−∆u = f in Ω
αu + ∇u · n = 0 on ∂Ω
−∆u = f in Ω
αu + ∇u · n = 0 on ∂Ω
=⇒ ∇u · ∇v dx + αuv ds = f v dx
Ω ∂Ω Ω
Z Z Z
∇u · ∇v dx + αuv ds = f v dx
Ω ∂Ω Ω
F = (
inner(grad(u), grad(v))*dx
+ inner(alpha*u, v)*ds
- inner(f, v)*dx
)
−∆u = f in Ω
αu + ∇u · n = 0 on ∂Ω|x = 0
u=g on ∂Ω|x > 0
Patrick Farrell
Oxford
May 2017
−∆u = f in Ω
∇u · n = β(c4 − u4 ) on ∂Ω,
Linear PDEs
The coefficients do not depend on the solution.
Linear PDEs
The coefficients do not depend on the solution.
Semilinear PDEs
The coefficients of the highest-order derivatives do not depend on the
solution.
Linear PDEs
The coefficients do not depend on the solution.
Semilinear PDEs
The coefficients of the highest-order derivatives do not depend on the
solution.
Quasilinear PDEs
The coefficients of the highest-order derivatives depend on lower-order
derivatives of the solution.
Linear PDEs
The coefficients do not depend on the solution.
Semilinear PDEs
The coefficients of the highest-order derivatives do not depend on the
solution.
Quasilinear PDEs
The coefficients of the highest-order derivatives depend on lower-order
derivatives of the solution.
F = (
inner(grad(u), grad(v))*dx
- inner(beta*(c**4 - u**4), v)*ds
- inner(f, v)*dx
)
I Set u = u + δu.
Computational challenge
Main cost: solving the linearized system.
Computational challenge
Main cost: solving the linearized system.
Fast convergence
Converges quadratically if close to a regular solution.
Computational challenge
Main cost: solving the linearized system.
Fast convergence
Converges quadratically if close to a regular solution.
Divergence
Can diverge if initialized far from a solution.
Computational challenge
Main cost: solving the linearized system.
Fast convergence
Converges quadratically if close to a regular solution.
Divergence
Can diverge if initialized far from a solution.
Multiple solutions
Can converge to different solutions from different initial guesses.
P. E. Farrell (Oxford) Practical IV May 2017 6/8
Using Newton’s method in FEniCS
solve(F == 0, u, bcs)
solve(F == 0, u, bcs)
Hint:
(x, y) = SpatialCoordinate(mesh)
Patrick Farrell
Oxford
May 2017
where
1
γ(u) = (2 + |∇u|2 )(p−2)/2
2
This particular choice of γ defines the p-Laplace equation.
Continuation
I Solve the problem for easy p (here, p = 2).
I While not finished:
I Use solution for p as initial guess for p = p + ∆p.
I Increment p.
F = ...
Patrick Farrell
Oxford
May 2017
We will solve the simplest extension of the Poisson problem into the time
domain, the heat equation:
∂u
− ∆u = f in Ω for t > 0
∂t
u = g on ∂Ω for t > 0
u = u0 in Ω at t = 0
The solution u = u(x, t), the right-hand side f = f (x, t) and the boundary
value g = g(x, t) may vary in space (x = (x0 , x1 , ...)) and time (t). The
initial value u0 is a function of space only.
There are many discretizations in time, each with different stability and
efficiency properties. We will implement BDF2, a multistep scheme. Given
∂u
= h(u, t),
∂t
we will solve for un with
4 1 2
un − un−1 + un−2 = ∆th(un , tn ).
3 3 3
Algorithm?
Initialization
To use a multistep method you need several past solutions, but we are
only given one initial condition.
Solution: use another scheme of the same order to compute the first few
solutions. We will use Crank-Nicolson. We will solve for un with
un + un−1 tn + tn−1
un − un−1 = ∆th( , ).
2 2
∆t tn + tn−1 ∆t
un − ∆un = ∆tf ( ) + un−1 + ∆un−1 .
2 2 2
Algorithm
We also need to discretise this in space. With the finite element method,
this yields the variational problem: find un ∈ Vh such that
Z Z
2
un v dx + ∆t ∇un · ∇v dx =
Ω 3
Z Ω Z Z
2 4 1
∆t f (tn )v dx + un−1 v dx − un−2 v dx
3 Ω 3 Ω 3 Ω
mesh = Mesh("klein.xml.gz")
V = FunctionSpace(mesh, "CG", 1)
u = Function(V) # u_n
u_prevs = [Function(V), Function(V)] # u_{n-1}, u_{n-2}
v = TestFunction(V)
# Initial condition
g = interpolate(Expression("sin(x[2])*cos(x[1])", degree=2), V)
F_cn = (
u*v*dx
- u_prevs[0]*v*dx
- dt*rhs(0.5*u + 0.5*u_prevs[0], v)
)
F_bdf = (
u*v*dx
- 4.0/3.0 * u_prevs[0]*v*dx
+ 1.0/3.0 * u_prevs[1]*v*dx
- 2.0/3.0 * dt*rhs(u, v)
)
ntimestep += 1
output << (u, float(t))
if t >= T: break
P. E. Farrell (Oxford) Practical VI May 2017 12 / 13
FEniCS 06 Challenge!
Then change the code to use BDF4. (Initialize with Crank-Nicolson and
BDF3.)
Patrick Farrell
Oxford
May 2017
−∇ · (2ν(u) − p I) = f in Ω
∇ · u = 0 in Ω
1
∇u + (∇u)T and with boundary conditions
where (u) = 2
u = 0 on ∂ΩD
−(2ν − p I) · n = p0 n on ∂ΩN
ν = ν(u)
Step 1
Multiply by test functions (v, q) ∈ W and integrate first equation by parts:
Z Z Z
2ν(u) · ∇v dx− p∇ · v dx − (2ν(u) − p I) · n · v ds = 0
Ω ZΩ ∂Ω
∇ · u q dx = 0
Ω
Step 2
Add the equations and incorporate the boundary conditions: find
(u, p) ∈ W = V0 × Q such that
Z Z Z Z
2ν(u) · ∇v dx − p∇ · v dx − ∇ · u q dx + p0 v · n ds = 0
Ω Ω Ω ∂ΩN
You can define functions on mixed spaces and split into components:
w = Function(W)
(u, p) = split(w)
dx: integration over cells; ds: integration over exterior (boundary) facets.
P. E. Farrell (Oxford) Practical VII May 2017 8 / 11
Stokes implementation
# Define mesh and geometry
mesh = Mesh("dolphin.xml")
n = FacetNormal(mesh)
# Solve problem
solve(F == 0, w, bcs)
# Plot solutions
(u, p) = w.split()
File("velocity.pvd") << u
File("pressure.pvd") << p
u and p point to parts of w’s memory. Use this in your mixed form.
−∇ · (2ν(u) − p I) = 0 in Ω
∇ · u = 0 in Ω
−(2ν(u) − p I) · n = p0 n on ∂ΩN = {(x0 , x1 )| x0 = 0 or x0 = 1}
p 0 = 1 − x0
u = 0 on ∂ΩD = ∂Ω\∂ΩN
Patrick Farrell
Oxford
May 2017
−∇ · P = B in Ω
u=g on ΓD
P ·n=T on ΓN
for all v ∈ V̂ .
Vector-valued Constants:
g = Constant((0, 0, -9.81)) # accel. due to gravity
Defining subdomains/boundaries:
MyBoundary = CompiledSubDomain("near(x[0], 0.0) && on_boundar
Marking boundaries:
my_boundary_1 = MyBoundary1()
my_boundary_2 = MyBoundary2()
boundaries = FacetFunction("size_t", mesh)
boundaries.set_all(0)
my_boundary_1.mark(boundaries, 1)
my_boundary_2.mark(boundaries, 2)
ds = Measure("ds", subdomain_data=boundaries)
F = ...*ds(0) + ...*ds(1)
g = −9.81m/s2
T = 5000 N/m2
Patrick Farrell
Oxford
May 2017
−∇2 u = f,
u = 0 on ∂Ω.
−∇2 u = f,
u = 0 on ∂Ω.
Let
Step 1
−∇2 u ≥ f
u ≥ ψ.
Step 1
−∇2 u ≥ f
u ≥ ψ.
Step 2
−∇2 u − λ = f
u − ψ ≥ 0, λ ≥ 0, λ(u − ψ) = 0.
Step 1
−∇2 u ≥ f
u ≥ ψ.
Step 2
−∇2 u − λ = f
u − ψ ≥ 0, λ ≥ 0, λ(u − ψ) = 0.
Step 3
−∇2 u − λ = f
λ − max(λ − (u − ψ), 0) = 0.
Solve the Poisson obstacle problem with Ω = [−1, 1]2 , f = −10 and
−0.2 if x ∈ [−1, −0.5),
−0.4 if x ∈ [−0.5, 0),
ψ(x, y) =
−0.6 if x ∈ [0, 0.5),
−0.8 if x ∈ [0.5, 1].
Patrick Farrell
Oxford
May 2017
−∆u = λu in Ω,
u = 0 on ∂Ω.
a = assemble(inner(grad(u), grad(v))*dx)
Three cases:
a = assemble(inner(grad(u), grad(v))*dx)
Three cases:
a = assemble(inner(grad(u), grad(v))*dx)
Three cases:
a = assemble(inner(grad(u), grad(v))*dx)
Three cases:
u = TrialFunction(V)
v = TestFunction(V)
a = inner(grad(u), grad(v))*dx
asm = SystemAssembler(a, dummy, bc)
A = PETScMatrix(); asm.assemble(A)
b = inner(u, v)*dx
asm = SystemAssembler(b, dummy) # no bc
B = PETScMatrix(); asm.assemble(B)
bc.zero(B)
solver = SLEPcEigenSolver(A, B)
solver.parameters["solver"] = "krylov-schur"
solver.parameters["spectrum"] = "target magnitude"
solver.parameters["problem_type"] = "gen_hermitian"
solver.parameters["spectral_transform"] = "shift-and-invert"
solver.parameters["spectral_shift"] = 10.
solver.solve(1)
eigenmodes = File("eigenmodes.pvd")
eigenfunction = Function(V, name="Eigenfunction")
for i in range(solver.get_number_converged()):
(r, _, rv, _) = solver.get_eigenpair(i)
eigenfunction.vector().zero()
eigenfunction.vector().axpy(1, rv)
eigenmodes << eigenfunction
Solve the eigenvalue problem for the Laplacian on the L-shaped domain.
Patrick Farrell
Oxford
May 2017
Z Z
1 2 α
min (u − ud ) dx + m2 dx
u,m 2 Ω 2 Ω
subject to
−∆u = m in Ω
u = 0 on ∂Ω
min J (u, m)
u,m
subject to:
F(u, m) = 0,
with
I the objective functional J .
I the parameter m.
I the PDE operator F with solution u ∈ U, parametrised by m ∈ M.
dL dL dL
= 0, = 0, = 0.
du dλ dm
Z Z Z
1 2 α 2
L(u, λ, m) = (u − ud ) dx + m dx + ∇λ · ∇u − λm dx
2 Ω 2 Ω Ω
L = (0.5*inner(u-ud, u-ud)*dx
+ 0.5*alpha*inner(m, m)*dx
+ inner(grad(u), grad(lmbda))*dx
- m*lmbda*dx)
−∇2 u = m
−∇2 λ = u − ud
αm = λ
F = derivative(L, z, TestFunction(Z))
We consider the following optimal control problem, after Ito and Kunisch:
1 α
min ku − ud k2L2 (Ω) + kmk2L2 (Ω)
u,m 2 2
2 3
subject to −∇ u + u − u = 0 on Ω,
∇u · n = m on Γ.
This Ginzburg-Landau PDE arises in superconductivity. Solve this optimal
control problem with Ω = [0, 1] × [0, 2], α = 10−7 , ud = 3.
Choose a
Sources of inspiration:
(1) Your research (preferred)!
(2) The PDE coffee table book.
(3) SIAM News.