UFL representation of ALE deformation gradient and determinant

I am using the dolfin.ALE class. I need a cellwise ufl representation of the ALE deformation Jacobian j = det(\frac{\partial x}{\partial x_0}). For example, the following code scales the coordinates of a unit square (two cells with volumes = 0.5) by three and returns the correct determinant of the Jacobian j=9. Is there a way that anyone can suggest that doesn’t use project ? Thanks!

from dolfin import *
mesh = UnitSquareMesh(1, 1)
V = FunctionSpace(mesh, 'DG', 0)

# old cell volume
cvol_old = CellVolume(mesh)
old = project(cvol_old, V)
print(old.vector().get_local())

[0.5 0.5]

# Create boundary mesh
boundary = BoundaryMesh(mesh, "exterior")

# Move vertices in boundary
for x in boundary.coordinates():
x[0] *= 3
x[1] *= 3

# Move mesh
ALE.move(mesh, boundary)

# new cell volume
cvol_new = CellVolume(mesh)
new = project(cvol_new, V)
print(new.vector().get_local())

[4.5 4.5]

# determinant
j_vol = new/old
print(project(j_vol,V).vector().get_local())

[9. 9.]

The following doesn’t use project() (although it still uses interpolate() once, to save the original coordinates):

from dolfin import *
import dolfin.cpp.function
mesh = UnitSquareMesh(1, 1)
V = FunctionSpace(mesh, 'DG', 0)

# Create boundary mesh:
boundary = BoundaryMesh(mesh, "exterior")

# Get initial configuration as CG1 vector-valued Function:
d = mesh.geometry().dim()
x0 = interpolate(Expression(["x["+str(i)+"]" for i in range(0,d)], degree=1),
                 VectorFunctionSpace(mesh,"CG",1))

# Move vertices in boundary:
for x in boundary.coordinates():
    x[0] *= 3
    x[1] *= 3

# Move mesh:
ALE.move(mesh, boundary)

# (Unfortunately, the `MeshDisplacement` object returned by `ALE.move()` is not
# usable in UFL; otherwise, you could avoid the initial interpolation, which
# is perhaps not in the spirit of avoiding `project()`.)

# Get deformation gradient associated with mesh displacement, i.e., the
# inverse of the derivative of initial coordinates `x0` w.r.t.
# current coordinates.
F_ALE = inv(grad(x0))

# Determinant that can be used in UFL:
j_vol = det(F_ALE)

# Test: Value is 9.0, as expected:
print(assemble(j_vol*dx)/assemble(Constant(1.0)*dx(domain=mesh)))
1 Like

Thanks for the tips!