Interpolate Expression on submesh with parent mesh function

Hi all,

I’m trying to interpolate a fem.Expression onto a submesh but using a function from the parent mesh.

MWE:

import dolfinx
from mpi4py import MPI

mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)


submesh, _, _, _ = dolfinx.mesh.create_submesh(
    mesh,
    dim=2,
    entities=dolfinx.mesh.locate_entities(mesh, dim=2, marker=lambda x: x[0] > 0.5),
)

V = dolfinx.fem.functionspace(mesh, ("CG", 1))
V_sub = dolfinx.fem.functionspace(submesh, ("CG", 1))


u = dolfinx.fem.Function(V)
u.interpolate(lambda x: x[0] + x[1])

u_sub = dolfinx.fem.Function(V_sub)

u_sub_expr = dolfinx.fem.Expression(
    2 * u,
    V_sub.element.interpolation_points(),
)
u_sub.interpolate(u_sub_expr)

I get the following error message:

Traceback (most recent call last):
  File "/home/remidm/FESTIM-workshop/book/content/mwe.py", line 26, in <module>
    u_sub.interpolate(u_sub_expr)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/home/remidm/anaconda3/envs/festim-workshop/lib/python3.13/site-packages/dolfinx/fem/function.py", line 459, in interpolate
    _interpolate(u0)
    ~~~~~~~~~~~~^^^^
  File "/home/remidm/anaconda3/envs/festim-workshop/lib/python3.13/functools.py", line 934, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/remidm/anaconda3/envs/festim-workshop/lib/python3.13/site-packages/dolfinx/fem/function.py", line 455, in _
    self._cpp_object.interpolate(e0._cpp_object, cells0, cells1)  # type: ignore
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: Cells lists have different lengths.

It’s probably something silly :slight_smile:

Hello,

The only way I found is to do:

uu = dolfinx.fem.Function(V)
uu.x.array[:] = 2.0 * u.x.array
u_sub.interpolate(uu)

Is it helpful?

Hi @LucasPa thanks for reaching out. I specifically need to use fem.Expression unfortunately

One more idea (not sure it’s what you need but at least fem.Expression is used): first interpolate u as uu on the submesh and then use uu to construct the fem.Expression:

mesh_cell_map = submesh.topology.index_map(submesh.topology.dim)
num_cells_on_proc = mesh_cell_map.size_local + mesh_cell_map.num_ghosts
cells = np.arange(num_cells_on_proc, dtype=np.int32)
interpolation_data = dolfinx.fem.create_interpolation_data(V_sub, V, cells)

uu = dolfinx.fem.Function(V_sub)
uu.interpolate_nonmatching(u, cells=cells, interpolation_data=interpolation_data)

u_sub = dolfinx.fem.Function(V_sub)

u_sub_expr = dolfinx.fem.Expression(
    2 * uu,
    V_sub.element.interpolation_points(),
)
u_sub.interpolate(u_sub_expr)
2 Likes

thanks! I’d like to avoid making another function if possible (because I have a transient problem and I’d have to update it at each timestep, i’d like to avoid that if possible).

Don’t know if we could use interpolate_nonmatching on Expression

Alternatively, you could interpolate into an appropriate quadrature space, as illustrated below:

from mpi4py import MPI
import basix.ufl
import dolfinx

mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)


submesh, cell_map, _, _ = dolfinx.mesh.create_submesh(
    mesh,
    dim=2,
    entities=dolfinx.mesh.locate_entities(mesh, dim=2, marker=lambda x: x[0] > 0.5),
)


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


q_el = basix.ufl.quadrature_element(submesh.basix_cell(), u.ufl_shape, scheme="default", degree=3)
Q = dolfinx.fem.functionspace(submesh, q_el)
q = dolfinx.fem.Function(Q)

expr = dolfinx.fem.Expression(u, Q.element.interpolation_points())
q.x.array[:] = expr.eval(mesh, cell_map).flatten()

import scifem
with scifem.xdmf.XDMFFile("point_cloud.xdmf", [u]) as xdmf:
    xdmf.write(0.0)

Getting Expressions to work with sub-meshes in general requires some work both in DOLFINx and FFCx.

2 Likes

Hi @dokken i see this works but you can’t use interpolate(expr) on q, correct?

Correct, that requires a rewrite of some internals in expression in both ffcx and dolfinx.