How to do updated Lagrangian when the displacement lives in a different space to the mesh geometry?

When implementing updated Lagrangian, the mesh geometry should be changed at each resolution step. To do so, based on the existing support for interpolating between functions living in different spaces (on the same mesh), this update is still possible when the displacement lives in a different space to the mesh geometry. This step is crucial since each element integral in the real mesh is pulled back to the reference element. It allows ending up with theusual suspects from differential geometry like the Jacobian and its determinant which are calculated from the mesh geometry.

A minimal example is:

import dolfinx
from mpi4py import MPI
import numpy as np

mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 4, 4)
V_coord = dolfinx.fem.FunctionSpace(mesh, mesh.ufl_domain().ufl_coordinate_element())

V = dolfinx.fem.VectorFunctionSpace(mesh, ("CG", 2))

u = dolfinx.fem.Function(V)
u.interpolate(lambda x: np.stack((x[1]**2, x[0]**2)))

u_coord = dolfinx.fem.Function(V_coord)
u_coord.interpolate(u)

mesh.geometry.x[:,:mesh.geometry.dim] = u_coord.x.array.reshape((-1, mesh.geometry.dim))

how about the following mwe:

import dolfinx
from mpi4py import MPI
import numpy as np

mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 4, 4)
V_coord = dolfinx.fem.FunctionSpace(
    mesh, mesh.ufl_domain().ufl_coordinate_element())

V = dolfinx.fem.VectorFunctionSpace(mesh, ("CG", 2))

u = dolfinx.fem.Function(V)
u.interpolate(lambda x: np.stack((0.1*x[1]**2, 0.1*x[0]**2)))

u_coord = dolfinx.fem.Function(V_coord)
u_coord.interpolate(u)

mesh.geometry.x[:, :mesh.geometry.dim] += u_coord.x.array.reshape(
    (-1, mesh.geometry.dim))

with dolfinx.io.XDMFFile(mesh.comm, "mesh.xdmf", "w") as xdmf:
    xdmf.write_mesh(mesh)

image

1 Like