Content uploaded by Raphael Bulle
Author content
All content in this area was uploaded by Raphael Bulle on Feb 10, 2021
Content may be subject to copyright.
Supplementary materials: Hierarchical a posteriori error
estimation of Bank–Weiser type in the FEniCS Project∗
Raphaël Bulle†Jack S. Hale†Alexei Lozinski‡Stéphane P. A. Bordas†
Franz Chouly§
February 10, 2021
1 Indicative snippet of error estimation for Poisson equation
using Bank–Weiser estimator
We present here a snippet of DOLFIN Python code showing function to compute the error of a
Poisson problem using the Bank–Weiser estimator.
from dolfin import *
import fenics_error_estimation
def estimate(u_h):
"""Bank-Weiser error estimation procedure for the Poisson problem.
Parameters
-----------
u_h: dolfin.Function
Solution of Poisson problem.
Returns
-------
The error estimate on each cell of the mesh.
"""
mesh = u_h.function_space().mesh()
# Higher order space
element_f = FiniteElement("DG", triangle, 2)
# Low order space
element_g = FiniteElement("DG", triangle, 1)
∗Raphaël Bulle would like to acknowledge the support of the ASSIST research project of the University of
Luxembourg. This publication has been prepared in the framework of the DRIVEN project funded by the European
Union’s Horizon 2020 Research and Innovation programme under Grant Agreement No. 811099.
†Institute of Computational Engineering, University of Luxembourg, 6 Avenue de la Fonte, 4362 Esch-sur-Alzette,
Luxembourg (raphael.bulle@uni.lu,stephane.bordas@uni.lu,jack.hale@uni.lu)
‡Laboratoire de Mathématiques de Besançon, UMR CNRS 6623, Université de Bourgogne Franche-Comté, 16
route de Gray, 25030 Besançon Cedex, France (alexei.lozinski@univ-fcomte.fr)
§Université de Bourgogne Franche-Comté, Institut de Mathématiques de Bourgogne, 21078 Dijon, France
(franz.chouly@u-bourgogne.fr)
1
# Construct the Bank-Weiser interpolation operator according to the
# definition of the high and low order spaces.
N = fenics_error_estimation.create_interpolation(element_f, element_g)
V_f = FunctionSpace(mesh, element_f)
e = TrialFunction(V_f)
v = TestFunction(V_f)
f = Constant(0.0)
# Homogeneous zero Dirichlet boundary conditions
bcs = DirichletBC(V_f, Constant(0.0), "on_boundary", "geometric")
# Define the local Bank-Weiser problem on the full higher order space
n = FacetNormal(mesh)
a_e = inner(grad(e), grad(v))*dx
# Residual
L_e = inner(f + div(grad(u_h)), v)*dx + \
inner(jump(grad(u_h), -n), avg(v))*dS
# Local solves on the implied Bank-Weiser space. The solution is returned
# on the full space.
e_h = fenics_error_estimation.estimate(a_e, L_e, N, bcs)
# Estimate of global error
error = norm(e_h, "H10")
# Computation of local error indicator.
V_e = FunctionSpace(mesh, "DG", 0)
v = TestFunction(V_e)
eta_h = Function(V_e, name="eta_h")
# By testing against v in DG_0 this effectively computes
# the estimator on each cell.
eta = assemble(inner(inner(grad(e_h), grad(e_h)), v)*dx)
eta_h.vector()[:] = eta
return eta_h
2
2 Indicative snippet of error estimation for linear elasticity
equations using Poisson estimator
We give here a snippet of DOLFIN Python code showing function to compute the error of a two-
dimensional linear elasticity problem (discretized with Taylor–Hood element) using the Poisson
estimator, based on our implementation of the Bank–Weiser estimator.
import scipy.linalg as sp.linalg
from dolfin import *
import fenics_error_estimation
def estimate(w_h, mu, lmbda):
"""
Parameters
-----------
w_h: dolfin.Function
Solution of the linear elasticity problem.
mu: float
First Lamé coefficient.
lmbda: float
Second Lamé coefficient.
Returns
-------
The error estimate on each cell of the mesh.
"""
mesh = w_h.function_space().mesh()
u_h = w_h.sub(0)
p_h = w_h.sub(1)
# Vectorial high order space.
X_element_f = VectorElement('DG', triangle, 3)
# Scalar high order and low order spaces.
S_element_f = FiniteElement('DG', triangle, 3)
S_element_g = FiniteElement('DG', triangle, 2)
# Construct the scalar projection matrix according to the definition
# of the high and low order spaces.
N_S = create_interpolation(S_element_f, S_element_g)
# Construct the vectorial projection matrix as a block diagonal, each
# block corresponding to a scalar problem.
N_X = sp.linalg.block_diag(N_S, N_S)
f = Constant((0., 0.))
X_f = FunctionSpace(mesh, X_element_f)
e_X = TrialFunction(X_f)
v_X = TestFunction(X_f)
# Homogeneous zero Dirichlet boundary conditions.
3
bcs = DirichletBC(X_f, Constant((0., 0.)), 'on_boundary','geometric')
# Cell residual.
R_T = f + div(2.*mu*sym(grad(u_h))) - grad(p_h)
# Facet residual.
n = FacetNormal(mesh)
R_E = (1./2.)*jump(p_h*Identity(2) - 2.*mu*sym(grad(u_h)), -n)
# Local Poisson problem.
a_X_e = 2.*mu*inner(grad(e_X), grad(v_X))*dx
L_X_e = inner(R_K, v_X)*dx - inner(R_E, avg(v_X))*dS
# Solve Poisson equation locally on implicit Bank--Weiser space.
e_h = fenics_error_estimation.estimate(a_X_e, L_X_e, N_X, bcs)
# Cell residual.
rho_d = 1./(lmbda**(-1)+(2.*mu)**(-1))
r_T = rho_d*(div(u_h) + lmbda**(-1)*p_h)
# Computation of local error indicator.
V_e = FunctionSpace(mesh, 'DG', 0)
v = TestFunction(V_e)
eta_h = Function(V_e)
# By testing against v in DG_0 this effectively computes the estimator
# on each cell.
eta = assemble(2.*mu*inner(inner(grad(e_h), grad(e_h)), v)*dx + \
rho_d**(-1)*inner(inner(eps_h, eps_h), v)*dx)
eta_h.vector()[:] = eta
return eta_h
4