When I was trying out some examples, I found that there seems to be some difference in the numbering of DoFs between basix and dolfinx.
If I tabulate the DoFs of a quadrilateral cell using dolfinx routine like this:
domain = mesh.create_rectangle(comm, [[0.0, 0.0], [1.0, 1.0]], [1, 1], mesh.CellType.quadrilateral, dtype=default_scalar_type, ghost_mode=mesh.GhostMode.shared_facet)
V = fem.functionspace(domain, ("Lagrange", 1))
print(V.dofmap.list)
print(V.tabulate_dof_coordinates())
The results will be:
[[0 1 2 3]]
[[ 2.77555756e-17 5.55111512e-17 0.00000000e+00]
[-2.77555756e-17 1.00000000e+00 0.00000000e+00]
[ 1.00000000e+00 -2.77555756e-17 0.00000000e+00]
[ 1.00000000e+00 1.00000000e+00 0.00000000e+00]]
As shown above, the second DoF is assigned to the vertex on the y-axis.
However, if I tabulate the DoFs (associated basis functions) of a reference cell in basix like this:
lagrange = basix.create_element(
basix.ElementFamily.P, CellType.quadrilateral, 1, basix.LagrangeVariant.equispaced
)
points = np.array([[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]])
tab = lagrange.tabulate(0, points)[0, :, :, 0]
print(tab)
The results will be:
[[ 1.00000000e+00 0.00000000e+00 -2.77555756e-17 5.55111512e-17]
[ 1.38777878e-16 1.00000000e+00 2.77555756e-17 -5.55111512e-17]
[ 1.38777878e-16 2.77555756e-17 1.00000000e+00 -5.55111512e-17]
[-8.32667268e-17 0.00000000e+00 0.00000000e+00 1.00000000e+00]]
As shown above, the second basis funtion (or the second DoF) is the one located at the vertex on the x-axis. And this is exactly the numbering rule defined in DefElement.
I’m wondering how does this difference happen? Is it related to the “orientation” of the cell entities?
I care about this detail because I’m working with a custom assembler. I need to replace the element stiffness matrix with a pre-calculated numpy array, so I have to figure out what is the local numbering rule of dofs in a cell.