Form compiler has to compute `CellVolume`
jorgensd opened this issue · comments
Is there any specific reason for the following code:
ufl/ufl/algorithms/apply_geometry_lowering.py
Lines 184 to 198 in 4fd9a80
To me, it seems like this should work for both affine and non-affine cells. I tested this locally with DOLFINx (by commenting out the if clause, with the following code:
import gmsh
import numpy as np
import ufl
from dolfinx import fem, io
from mpi4py import MPI
# Generate a mesh with non-affine cells
gdim = 2
mesh_comm = MPI.COMM_WORLD
model_rank = 0
if mesh_comm.rank == model_rank:
gmsh.initialize()
rectangle = gmsh.model.occ.addRectangle(0, 0, 0, 1, 1, tag=1)
obstacle = gmsh.model.occ.addDisk(0.5, 0.5, 0, 0.3, 0.3)
fluid = gmsh.model.occ.cut([(gdim, rectangle)], [(gdim, obstacle)])
gmsh.model.occ.synchronize()
volumes = gmsh.model.getEntities(dim=gdim)
gmsh.model.addPhysicalGroup(volumes[0][0], [volumes[0][1]], 1)
gmsh.option.setNumber("Mesh.Algorithm", 8)
gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2)
gmsh.option.setNumber("Mesh.RecombineAll", 1)
gmsh.option.setNumber("Mesh.SubdivisionAlgorithm", 1)
gmsh.model.mesh.generate(gdim)
domain, _, _ = io.gmshio.model_to_mesh(
gmsh.model, mesh_comm, model_rank, gdim=gdim)
gmsh.finalize()
Ve = fem.FunctionSpace(domain, ("DG", 0))
elmVol_ufl = ufl.CellVolume(domain)
elmVol_expr = fem.Expression(elmVol_ufl, Ve.element.interpolation_points())
elmVol = fem.Function(Ve, name="Element Volume (expression)")
elmVol.interpolate(elmVol_expr)
q_degree = 3
vol2 = fem.Function(Ve)
fem.petsc.assemble_vector(vol2.vector, fem.form(
1*ufl.TestFunction(Ve)*ufl.dx(metadata={"quadrature_degree": q_degree})))
vol2.x.scatter_forward()
print(vol2.x.array - elmVol.x.array)
assert np.allclose(vol2.x.array, elmVol.x.array)
vol2.name = "ElementVolume (assembly)"
with io.XDMFFile(domain.comm, "cell_vol.xdmf", "w") as xdmf:
xdmf.write_mesh(domain)
xdmf.write_function(elmVol)
xdmf.write_function(vol2)
That lowering is a one point quadrature for computing the cell volume. If your cell is a way from affine, this is a bad approximation I think.
That lowering is a one point quadrature for computing the cell volume. If your cell is a way from affine, this is a bad approximation I think.
How can you see that the lowering is to a single point quadrature? (I know the expression interpolation in DOLFINx is equivalent to a one point quadrature, but that is not the main point here).
I cannot spot that assumption in the referenced ufl code, as I would expect JacobianDeterminant to be what we use in general for integral scaling of non-affine and affine geometries, but maybe I've missed something.
That lowering is a one point quadrature for computing the cell volume. If your cell is a way from affine, this is a bad approximation I think.
Oh, right. It is because this doesn't give the form compiler any instructions on summing the jacobians for each quadrature point before multiplying by anything else.