I have created a mesh in gmsh
for the Haut Glacier d’Arolla (TC - Benchmark experiments for higher-order and full-Stokes ice sheet models (ISMIP–HOM)) and converted to .xml
format for use in FEniCS
using dolfin-convert
.
I decided to test my mesh by solving the following Poisson problem.
After solving the discretized problem, checking that the solution is reasonable by visualizing in ParaView
I then check the H1 semi-norm of the solution, defined as
in two ways. First by using the assemble
command in dolfin
, the numerical value returned is nan
. There is an alternative way to compute the H1 semi-norm. That is
Where A is the finite element stiffness matrix. u^TA u evaluates to a reasonable nonnegative finite number.
I have included the full code below., but of course you will not be able to test without the mesh.
I am hoping to get insight into why this would be the case, what goes on internally in FEniCS
when one assembles a finite element system matrix, such as A, with Dirichlet conditions that causes the discrepancy that I am seeing.
import dolfin as dl
import numpy as np
# mesh of PDE domain
meshdir = "../"
meshname = "Arolla2"
mesh = dl.Mesh(meshdir+meshname+".xml")
boundary_markers = dl.MeshFunction("size_t", mesh,\
meshdir+meshname+"_facet_region.xml")
# discrete function spaces
P1 = dl.FiniteElement("CG", mesh.ufl_cell(), 1)
Vh = dl.FunctionSpace(mesh, P1)
# Homogeneous Dirichlet conditions
bc = [dl.DirichletBC(Vh, dl.Constant(0.0), boundary_markers, 1),\
dl.DirichletBC(Vh, dl.Constant(0.0), boundary_markers, 2)]
# Right hand side forcing term
f = dl.Constant(1.0)
vh = dl.TestFunction(Vh)
uh = dl.TrialFunction(Vh)
a = dl.inner(dl.grad(uh), dl.grad(vh))*dl.dx
L = f*vh*dl.dx
A, b = dl.assemble_system(a, L, bc)
Asolver = dl.PETScKrylovSolver()
dl.PETScOptions.set("ksp_monitor")
dl.PETScOptions.set("ksp_monitor_true_residual")
dl.PETScOptions.set("ksp_type", "cg")
dl.PETScOptions.set("ksp_rtol", "1.e-12")
dl.PETScOptions.set("ksp_atol", "1.e-12")
Asolver.set_from_options()
Asolver.set_operator(A)
u = dl.Function(Vh)
Asolver.solve(u.vector(), b)
# for the determined solution,
# compute sqrt(int_(Omega) ||grad(u)||^2 dV)
u_H1norm_1 = np.sqrt(dl.assemble(dl.inner(dl.grad(u), dl.grad(u))*dl.dx(mesh)))
print("||u||_H^1(Omega)^2 = %1.3e (directly assembled)" %(u_H1norm_1))
# vector to hold the product of the solution with
# the finite element system matrix A
Au = dl.Vector()
A.init_vector(Au, 0)
# Au = A*u
A.mult(u.vector(), Au)
# sqrt(u^T Au)
u_H1norm_2 = np.sqrt(Au.inner(u.vector()))
print("||u||_H^1(Omega) = %1.3e (from assembled operators)" \
%(u_H1norm_2))