Getting cell dofs for vector valued function space in dolfinx

Consider the following MWE:

import dolfinx
from mpi4py import MPI

mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 1, 1)
Q = dolfinx.VectorFunctionSpace(mesh, ("DG", 1))

print(f"Dof numbers cell 0: {Q.dofmap.cell_dofs(0)}")

returning

Dof numbers cell 0: [1 0 2]

This obviously is not what I expect, I had expected 6 dofs per cell for the given vector valued function space. I guess I am missing something very basic here, because this seems too elementary to be a bug. But what? (the same issue manifests itself on the C++ side)

2 Likes

Each dofmap has a block size. For a traditional lagrange element, this is 1. For a vector space in 2D it is 2. this means that the cell_dofs actually correspond to a block of dofs. (You can obtain the blocks size of any space by calling Q.dofmap.index_map_bs) in your example the dofs would be [2,3,0,1,4,5].

The reason for this design is that the basis functions in each dimension of the vector space are identical.

1 Like

For more clarification, here is a code that creates an array of size number of cells times number of dofs per cell:

import dolfinx
from mpi4py import MPI
import numpy as np
mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 1, 1)
Q = dolfinx.VectorFunctionSpace(mesh, ("DG", 1))
num_dofs = mesh.topology.index_map(mesh.topology.dim).size_local
block_size = Q.dofmap.index_map_bs 
local_cell_dofs = np.zeros((num_dofs, Q.dofmap.dof_layout.num_dofs * block_size))
for i in range(num_dofs):
    cell_blocks = Q.dofmap.cell_dofs(i)
    for (j,dof) in enumerate(cell_blocks):
        for k in range(block_size):
            local_cell_dofs[i, j*block_size+k] = dof*block_size + k
print(local_cell_dofs)
5 Likes

Thanks, that’s helpful! Even though the chosen nomenclature seems somewhat confusing and not immediately/really intuitive.