How to obtain coordinates of nodes? How to work with dofmap?

Hi there,

I am trying to rebuild either this or this in Fenics2019.1.0.
For the first option

x_ks = V.dofmap().tabulate_all_coordinates(mesh).reshape((-1, 1))[:, 0]

does not seem to work any more in Fenics 2019.1.0.
For the second option similarly, I do not know how to get the coordinates of the nodes such that they are in the right order corresponding to my linear lagrange space. How does the function “index → coordinate” look like ?
Or is there a tutorial concerning my question? Or would there have been a possibility to find this out by myself without asking here ? :smile:
Thanks a lot for your help!
Jan

You can use V.tabulate_dof_coordinates() where the coordinates is ordered in the same order as your degrees of freedom.

thank you very much for your answer, that does the job and the program already works :slight_smile:

Hello, whatif we define a mixed element function space with high order element (p>1)
what is the return of tabulate_dof_coordinates()?
here is my minimal code example:

P = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 2)
V = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 2)
U = ufl.VectorElement("Lagrange", msh.ufl_cell(), 2)
element = ufl.MixedElement([P,V,U])
PVU = FunctionSpace(msh, element)
p, v, u = ufl.TrialFunctions(function_space=PVU)
q, v_t, u_t = ufl.TestFunctions(function_space=PVU)

P_dof_coord = PVU.sub(0).collapse()[0].tabulate_dof_coordinates()
V_dof_coord = PVU.sub(1).collapse()[0].tabulate_dof_coordinates()
U_dof_coord = PVU.sub(2).collapse()[0].tabulate_dof_coordinates()

I expect the total length of these three coords (P+V+U) is equal to total dofs, but is it not. and the length of U_dof_coord should three times longer than the other twos.
I cannot understand what the return of these coord.

How can I get the dofs_index (corresponds to the position in the global matrix) with the associated coordinates?

Thanks for reply

Hello, I am getting error for Serendipity element while extracting dof coordinates.

MWE:

import dolfinx
import ufl
from mpi4py import MPI

mesh=dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10,10, dolfinx.mesh.CellType.quadrilateral)
Ve = ufl.VectorElement("S", mesh.ufl_cell(), 2)
V = dolfinx.fem.FunctionSpace(mesh, Ve)
V.tabulate_dof_coordinates()

Error:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[6], line 8
      6 Ve = ufl.VectorElement("S", mesh.ufl_cell(), 2)
      7 V = dolfinx.fem.FunctionSpace(mesh, Ve)
----> 8 V.tabulate_dof_coordinates()

File /usr/lib/petsc/lib/python3/dist-packages/dolfinx/fem/function.py:721, in FunctionSpaceBase.tabulate_dof_coordinates(self)
    710 def tabulate_dof_coordinates(self) -> npt.NDArray[np.float64]:
    711     """Tabulate the coordinates of the degrees-of-freedom in the function space.
    712 
    713     Returns:
   (...)
    719 
    720      """
--> 721     return self._cpp_object.tabulate_dof_coordinates()

RuntimeError: Cannot evaluate dof coordinates - this element does not have pointwise evaluation.

Dofs for second order serendipity are associated with facets, see: DefElement and thus does not have a single coordinate to represent it

Thanks @dokken for your response.

In the link, the location from 5th dof to 8th dof is evaluated by integration over edge, which is theoretically understandable.

Can you suggest any way to obtain the coordinates of dof within S2 definition. Because if I want to do manually by gaussian integration, I first need to define S1 to extract edge coordinates.
therefore, it seems not to work.

To me it is unclear what you want to achieve here.

What do you want to do manually? Could you write an example of what youvwant to do?

1 Like

@dokken , Thanks for your response. Apologies for the unclear statement. I am using V.tabulate_dof_coordinates() to define rotational nullspace.

Ve = VectorElement("S", mesh.ufl_cell(), 2)
V = FunctionSpace(mesh, Ve)
# Create list of vectors for null space
index_map = V.dofmap.index_map
nullspace_basis = [dolfinx.la.create_petsc_vector(index_map, V.dofmap.index_map_bs) for i in range(4)]

with ExitStack() as stack:
    vec_local = [stack.enter_context(x.localForm()) for x in nullspace_basis]
    basis = [np.asarray(x) for x in vec_local]
    
# Dof indices for each subspace (x, y and z dofs)
dofs = [V.sub(i).dofmap.list for i in range(3)]

# Build rotational null space basis
x = V.tabulate_dof_coordinates()
dofs_block = V.dofmap.list
x0, x1, x2 = x[dofs_block, 0], x[dofs_block, 1], x[dofs_block, 2]
basis[3][dofs[1]] = -x2
basis[3][dofs[2]] = x1

For rotational nullspace, I require dof coordinates x1 and x2 for Serendipidity second order elements.

How about interpolating the rotational vector into the space? That is straightforward and takes care of the integral moments aspect.

1 Like

I am sorry, but, I don’t understand how rotation vector can be interpolated into space for above MWE.

The rotation vector is -y, x, i.e.

from mpi4py import MPI
import ufl
import dolfinx

mesh = dolfinx.mesh.create_unit_square(
    MPI.COMM_WORLD, 10, 10, cell_type=dolfinx.mesh.CellType.quadrilateral)
Ve = ufl.VectorElement("S", mesh.ufl_cell(), 2)

V = dolfinx.fem.functionspace(mesh, Ve)
u = dolfinx.fem.Function(V)
u.interpolate(lambda x: (-x[1], x[0]))


V_out = dolfinx.fem.FunctionSpace(
    mesh, ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2))

u_out = dolfinx.fem.Function(V_out)
u_out.interpolate(u)

with dolfinx.io.VTXWriter(mesh.comm, "mwe_rot.bp", [u_out], engine="BP4") as bp:
    bp.write(0.0)

yielding

1 Like