Change the mesh of a function

Hello everyone, :wave:

I’m trying to create an adaptative mesh and for that I have to change my mesh during the computation. The problem is that I need to pass the values of a function created in the first mesh to the second mesh. I suppose this should be done by interpolation since the nodes of the two meshes do not coincide. However, when I try it, it tells me in the error that this is not implemented yet. I have also tried to make a projection on the new mesh but it does not work. I attach MWE with the mentioned cases.

#Import libraries
import dolfinx.generation
import dolfinx.fem
from mpi4py import MPI
import numpy as np
import ufl

#Creation of the first mesh
mesh1 = dolfinx.generation.RectangleMesh(MPI.COMM_WORLD, [np.array([0,0,0]), np.array([25e-6,150e-6,0])], [70,400])
#Define function space
P1 = ufl.FiniteElement("Lagrange", mesh1.ufl_cell(), 1)
ME1 = dolfinx.fem.FunctionSpace(mesh1,ufl.MixedElement([P1, P1]))
# Define functions
u1 = dolfinx.fem.Function(ME1)
# Split mixed functions
c1, eta1 = ufl.split(u1)

#Interpolate a function
u1.sub(0).interpolate(lambda x: 1/(1+ufl.e**(2e6*(x[1]-0.9*150e-6))))
u1.sub(1).interpolate(lambda x: 1/(1+ufl.e**(1.6e6*(x[1]-0.9*150e-6))))
u1.x.scatter_forward()

#Creation of the second mesh with different number of nodes
mesh2 = dolfinx.generation.RectangleMesh(MPI.COMM_WORLD, [np.array([0,0,0]), np.array([25e-6,150e-6,0])], [80,500])
#Define function space
P2 = ufl.FiniteElement("Lagrange", mesh2.ufl_cell(), 1)
ME2 = dolfinx.fem.FunctionSpace(mesh2,ufl.MixedElement([P2, P2]))
# Define functions
u2 = dolfinx.fem.Function(ME2)
# Split mixed functions
c2, eta2 = ufl.split(u2)

#First option --RuntimeError: Interpolation on different meshes not supported (yet).
u1.sub(0).interpolate(u2.sub(0))

#Second option -- Kernel restarted
def project(expression, V):
    dx = ufl.dx(V.mesh)
    u_, v_ = ufl.TrialFunction(V), ufl.TestFunction(V)
    a_p = ufl.inner(u_, v_) * dx
    L_p = ufl.inner(expression, v_) * dx
    projection = dolfinx.fem.LinearProblem(a_p, L_p)
    return projection.solve()

V2 = dolfinx.fem.FunctionSpace(mesh2,P2)
c2 = project(c1, V2)

I would like to know if there is a way to do this in dolfinx as I did in dolfin with:

u2.assign(interpolate(u1,ME2))

Thank you very much and best regards,
Jesús

Any update on that ? Could there be a workaround inside dolfinx or should it be done by hand using u1.vector, mesh1.geometry.x and scipy.interpolate ?

You could try using this branch: Interpolation between different meshes by massimiliano-leoni · Pull Request #1598 · FEniCS/dolfinx · GitHub

Thanks for the pointer, I’ll think about it

I actually have another workaround that uses Expression.

expr=dfx.fem.Expression(u1,ME2.element.interpolation_points())
u2 = Function(ME2)
u2.interpolate(expr)

The interpolation between meshes has now been merged into main.

Are you sure your suggested approach will work in parallel?

Yes, I am sure. Good to know it’s possible to do it directly from main though.

I cannot get your approach to work, i.e.

import dolfinx
from mpi4py import MPI

mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)
V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 1))

mesh2 = dolfinx.mesh.create_unit_square(
    MPI.COMM_WORLD, 30, 30, cell_type=dolfinx.mesh.CellType.quadrilateral)
Q = dolfinx.fem.FunctionSpace(mesh2, ("Lagrange", 1))

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

w = dolfinx.fem.Function(Q)

expr = dolfinx.fem.Expression(u, Q.element.interpolation_points())
w.interpolate(expr)


with dolfinx.io.VTXWriter(mesh2.comm, "w.bp", [w]) as vtx:
    vtx.write(0.0)

Could you clarify what differs between mine and your approach.

What error are you getting ?

In my code I use this Expression trick to obtain a specific component of a VectorElement, or its gradient, on another mesh. Maybe Expression requires a ufl object that could be forced by adding a dummy ufl.Constant or something ?

Im getting a segfault, which in itself I’ll admit is not very helpful.
multiplying u with a constant is not changing that error.
The reason for asking you for how you’ve done this is because I do not think dolfinx.fem.Expression will be able to cope with problems where the cells of u and w does not align.

I have no segfault on my end and my code is reasonably the same (this is a snippet, the whole thing is heavier).

with dfx.io.XDMFFile(comm, "nozzle_coarse.xdmf", "r") as file: mesh = file.read_mesh(name="Grid")
FE=ufl.FiniteElement("CG",mesh.ufl_cell(),2)
V = FunctionSpace(mesh,FE)
expr=dfx.fem.Expression(u1[0],V.element.interpolation_points())
u2 = Function(V)
u2.interpolate(expr)

That said, I posted too fast something that was more an idea than a solution, as the end result that I just checked is very unsatisfying :


I’d say let’s not waste more time on this I should have tested my code before posting. In passing, I also appreciate that the new syntax for FunctionSpace that alleviates the need for FiniteElement - I never understood its added value.