mfem: FaceRestriction numbering inconsistencies
I’ve been trying to debug this boundary dof issue for days now, and I need some help making sense of what I’m seeing.
I’m using mfem::FiniteElementSpace::GetFaceRestriction
to get an operator that would take me from an “L-vector” to a boundary “E-vector”. Our shape functions are ordered lexicographically, so I call it with the following arguments:
test_space_->GetFaceRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC, mfem::FaceType::Boundary, mfem::L2FaceValues::SingleValued)
I need the dof ids as well if I’m going to add the boundary-element jacobian (e.g. stiffness) matrix contributions back into their appropriate locations in the global jacobian matrix. I don’t see an obvious way to get that information out of the restriction operator itself, so I looked to mfem::FiniteElementSpace::GetBdrElementDofs()
. It appears that the output of GetBdrElementDofs
is in NATIVE ordering, so I apply the permutation from calling GetDofMap()
to get the dofs in LEXICOGRAPHIC ordering. When I compare this with the dofs used by FaceRestriction
I see the following:
the FaceRestriction
’s node numbering within a face appears to be inconsistent with both the NATIVE and LEXICOGRAPHIC options. In addition, the numbering of the faces in the FaceRestriction
is also inconsistent with GetBdrElementDofs
(face number indicated in parentheses):
Also, the windings of the FaceRestriction node numbering are also inconsistent: for faces 1, 4, and 5, the normal directions (n := cross(dx_dxi, dx_deta)) are inward-facing while faces 2, 3, and 6 have outward-facing normals. As a sanity check, I compared GetElementDofs
against GetElementRestriction
’s numbering as well:
So, there seems to be agreement between GetElementDofs
and GetElementRestriction
, but not GetFaceRestriction
and GetBdrElementDofs
.
Is this behavior a bug, or is it intentional (and if so, is there any documentation or explanation available)?
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 16 (16 by maintainers)
Let me try to summarize the functionality in MFEM that has to do with faces and boundaries. There are basically two separate interfaces for this:
In the context of (1) there are two sets of elements of dimension
(dim-1)
, wheredim = Mesh::Dimension()
: (A) the set of all face elements which is auto-generated from the volume elements, and (B) the set of all “boundary” elements which is typically read from the mesh file. Note that the boundary elements (B) contain the boundary attributes. Also, note that the boundary elements can describe actual interior faces (interfaces). Every element in (B) can be identified uniquely as a face in set (A), however, the boundary element may have an orientation (vertex ordering) different from that of its corresponding face in (A). The number of elements in (A) and (B) are given byMesh::GetNumFaces()
andMesh::GetNBE()
, respectively.In the context of (2), the set (A) is decomposed in two parts: (Ai) the set of all real interior faces (faces that have 2 adjacent volume elements), enumerated contiguously following the ordering from (A); and (Ab) the set of all real boundary faces (faces that have 1 adjacent volume element), also enumerated contiguously following the ordering from (A). The number of elements in (Ai) and (Ab) are given by
Mesh::GetNFbyType(FaceType::Interior)
andMesh::GetNFbyType(FaceType::Boundary)
, respectively. An important point is that in the context (2), both the elements in (Ai) and those in (Ab) have orientations (vertex ordering) different from the one in (A). The main reason for using different orientations for (Ai) and (Ab) is to simplify the implementation of the tensor product evaluations.Now, given the above description, we have the following:
FiniteElementSpace::GetFaceRestriction
,Mesh::GetFaceGeometricFactors
, andFiniteElementSpace::GetFaceQuadratureInterpolator
are part of (2) and they work on the sets (Ai) or (Ab) depending on their parameter of typeFaceType
.Mesh::GetBdrElementVertices
,Mesh::GetBdrElementTransformation
, andFiniteElementSpace::GetBdrElementDofs
are part of (1) and they work with the set (B).Hopefully this helps explain why you see the inconsistencies you observed.
I think there are different paths forward: either using (1), or using (2) with some functionality that we can add in MFEM, e.g. a method similar to
FiniteElementSpace::GetBdrElementDofs
that works with the set (Ab) instead of (B).I have no idea about these details, I just want to know how you made these animations. 😃