New error with locate_dofs_geometrical

Hi, I recently reinstalled dolfinx after the nanobind update but locate_dofs_geometrical no longer seems to work. This is an MWE:

import numpy as np
import mpi4py
import dolfinx

msh = dolfinx.mesh.create_unit_square(mpi4py.MPI.COMM_WORLD, 50, 50)

V = dolfinx.fem.functionspace(msh, ('Lagrange', 1))
dof = dolfinx.fem.locate_dofs_geometrical(V, lambda x: np.isclose(0,0))

and this is my output:

Traceback (most recent call last):
  File "/tmp_user/sator/hmmak/fenicsx-scripts/3D/test-geom.py", line 8, in <module>
    dof = dolfinx.fem.locate_dofs_geometrical(V, lambda x: np.isclose(0,0))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp_user/sator/hmmak/anaconda3/envs/real/lib/python3.12/site-packages/dolfinx/fem/bcs.py", line 51, in locate_dofs_geometrical
    return _cpp.fem.locate_dofs_geometrical(V._cpp_object, marker)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: std::bad_cast

Please let me know if I’m doing something wrong. Thank you in advance.

I am able to run this MWE without any error on dolfinx 0.7.1, what version are you using?

I believe it is a new error from the current dev version of dolfinx (i.e. 0.8.0dev) as I wished to update to nanobind. I can’t be certain of which git commit I used but I believe it was somewhere around this commit of dolfinx. Doflinx was installed in a conda environment via building the c++ core and pip installing (rather than conda-forge).

From the error message it may suggests a wrong shape for the marker.
I must admit I don’t really understand the lambda x: np.isclose(0,0) as this only returns True.

Could you try something like:

dof = dolfinx.fem.locate_dofs_geometrical(V, lambda x: np.isclose(x[0],0))

or

dof = dolfinx.fem.locate_dofs_geometrical(V, lambda x: np.full_like(x, True))

Those both seem to run but not producing what I would like. Which is to return the dof that corresponds to the point (0,0). This seems to be the output of lambda x: np.isclose(0,0) in previous versions as far as I understand. Although, now that I think about what np.isclose is doing, that’s probably incorrect. I’ve probably been using it incorrectly but somehow gotten the correct result.

I guess one way to do what I want to achieve is where if you want to find the DoF for coordinate (a,b), one could use

dolfinx.fem.locate_dofs_geometrical(V, lambda x: np.isclose((x[0]-a)**2+(x[1]-b)**2,0))

which seems not very elegant.

In that case this is what you want:

import numpy as np
import mpi4py
import dolfinx

msh = dolfinx.mesh.create_unit_square(mpi4py.MPI.COMM_WORLD, 4, 4)

V = dolfinx.fem.functionspace(msh, ('Lagrange', 1))

def marker(x):
    return np.logical_and(np.isclose(x[0], 0), np.isclose(x[1], 0))

dof = dolfinx.fem.locate_dofs_geometrical(V, marker)

Ah that makes a lot more sense. Thank you!

This can also be written as

def marker(x):
    return np.isclose(x[0], 0) & np.isclose(x[1], 0)
1 Like