Second-order Serendipity Elements [dirichletbc]

Hi,

I’m conducting a benchmark to compare my code with commercial FEM software, which typically only offer Serendipity elements for plane stress cases, rather than Lagrange Elements.

I followed the suggestion from @dokken on dealing with Serendipity Elements as discussed in this FEniCS Project forum thread. However, I encountered an issue when trying to create a Dirichlet boundary condition in just one direction, resulting in the following error:
RuntimeError: Constant can be used only with point-evaluation elements

I’m trying to fix a displacement of 0 in the x-direction at the bottom of the domain. Here’s a code snippet illustrating my problem:

import dolfinx
from mpi4py import MPI
import numpy as np
from petsc4py.PETSc import ScalarType

def boundary_bottom(x: List[float]) -> bool:
    return np.isclose(x[1], min(x[1]))

domain = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 1, 1, dolfinx.mesh.CellType.quadrilateral)
v_func_space = dolfinx.fem.VectorFunctionSpace(domain, ("S", 2))
        
sub_0, _ = v_func_space.sub(0).collapse()
edges = dolfinx.mesh.locate_entities_boundary(domain, domain.topology.dim - 1, boundary_bottom)
boundary_dofs = dolfinx.fem.locate_dofs_topological((v_func_space.sub(0), sub_0), domain.topology.dim - 1, edges)

bc = dolfinx.fem.dirichletbc(ScalarType(0), boundary_dofs[0], v_func_space.sub(0))

What doesn’t make sense is that this approach works for second-order Lagrange elements, as well as for first-order Serendipity and Lagrange Elements.

Thanks in advance for any help!

Simplest workaround I can think of is to replace your final line with

# bc = dolfinx.fem.dirichletbc(ScalarType(0), boundary_dofs[0], v_func_space.sub(0))
zero_scalar = dolfinx.fem.Function(sub_0)
bc = dolfinx.fem.dirichletbc(zero_scalar, boundary_dofs, v_func_space.sub(0))
1 Like

Thanks, @francesco-ballarin!
Could you also tell me how the code would change if the displacement values are a constant instead of zero?

Additionally, out of curiosity, do you know why my solution doesn’t work with Serendipity Elements but works with Lagrange Elements?

Could you also tell me how the code would change if the displacement values are a constant instead of zero?

Just interpolate the value into a dolfinx.fem.Function

Additionally, out of curiosity, do you know why my solution doesn’t work with Serendipity Elements but works with Lagrange Elements?

I can’t claim to know much about Serendipity Elements, because I’ve never used them. Still, the error

RuntimeError: Constant can be used only with point-evaluation elements

aligns with what I can see from DefElement, i.e. that DOFs 4 to 7 in S elements are given by the average on edges.

If you look at the similar page for Q elements at DefElement
you will see that DOFs 4 to 7 are again associated to edges, but are pointwise evaluation at the midpoint, rather than an integral.

1 Like

I followed your suggestion to interpolate the value into a dolfinx.fem.Function and it worked perfectly!

Your explanation was excellent and now the error makes complete sense.

Thanks, Francesco, for your help!