Today I tried integrating BDM elements of order 1 https://defelement.org/elements/brezzi-douglas-marini.html along interior edges of a 2D domain and encountered a seemingly wrong value.
In the finite element space there are two degrees of freedom on each facet, so I expect the integral of a BDM-function with its outwards normal to be the average between the two DOF values. However my code only returns the value of one singular DOF, which (in my opinion) should not be the case.
MWE:
import numpy as np
from dolfinx.mesh import create_unit_square
from dolfinx.fem import functionspace, Function, assemble_scalar
from mpi4py import MPI
import ufl
mesh = create_unit_square(MPI.COMM_WORLD, 1, 1)
V = functionspace(mesh, ("BDM", 1))
bdm_function = Function(V)
rand_init = np.random.rand(len(bdm_function.x.array))
bdm_function.x.array[:] = rand_init
n = ufl.FacetNormal(mesh)
dS = ufl.Measure("dS", domain=mesh)
form_final = ufl.inner(bdm_function('+'), n('+')) * dS
result = assemble_scalar(fem.form(form_final))
print("Rand init: ", rand_init)
print("Computed integral:", result)
print("DOF value at index 2: ", rand_init[2])
On my end the result is always equal to this one parameter at DOF 2. Changing quadrature rules or orders didn’t impact the result. The BDM space has the expected dimension, 10 and I expected that the integral uses the 2 DOFs on the interior edge instead of only one.
I tried the (presumably) same example in legacy fenics, where it returned the expected value:
from dolfin import *
import numpy as np
mesh = UnitSquareMesh(1, 1)
V = FunctionSpace(mesh, "BDM", 1)
bdm_function = Function(V)
random_vector = np.random.rand(len(bdm_function.vector()[:]))
bdm_function.vector()[:] = random_vector
n = FacetNormal(mesh)
dS = Measure("dS", domain=mesh)
form = inner(bdm_function('-'), n('-')) * dS
result = assemble(form)
print("Computed integral: ", result)
print("Predicted result: ", (random_vector[2] + random_vector[3])/2)
I got the indices by using np.arange
before, changing directions of the normal as expected only flips the sign of the result.
These two code snippets were done in disjoint conda envivorments, for the first I installed version 0.9.0 of FEniCSx from conda-forge and it uses fenics-ufl version 2024.2.0 with python 3.12.9. For the second I also installed FEniCS from conda-forge, so everything has version 2019.1.0 , again in python, version 3.10.16