In my application I’m using a custom quadrature routine on each cell in the mesh using ufl.Measure (cutFEM type application). I uniquely identify each quadrilateral using it’s bounding box. What I’ve found is that I get different results depending on the number of processors I use. The following is a minimal working example using dolfinx 0.9.0 installed via Conda. When I run using 1 processor the result is 5.134887570312367 and when I run using 2 processors the result is 6.72445068591649:
#Import packages
from mpi4py import MPI
from dolfinx import mesh as dmesh, fem
import dolfinx.fem.petsc
import ufl
import numpy as np
def verts_to_bbox(verts):
assert verts.shape == (3, 4)
xL, xR = verts[0].min(), verts[0].max()
yL, yR = verts[1].min(), verts[1].max()
bbox = np.round([xL, yL, xR, yR], decimals=9)
return bbox
#Problem parameters
nx = 2 #Number of cells in x-direction
ny = 2 #Number of cells in y-direction
#Define unique quadrature rule for each quadrilateral
x_vals = np.linspace(-1, 1, nx+1)
y_vals = np.linspace(-1, 1, ny+1)
quad = {}
for i in range(nx):
for j in range(ny):
bbox = np.round([x_vals[i], y_vals[j], x_vals[i+1], y_vals[j+1]], decimals=9)
qp = [[0.1, 0.1], [0.9, 0.1], [0.9, 0.9], [0.1, 0.9]]
qw = [np.abs(bbox[0]), np.abs(bbox[1]), np.abs(bbox[2]), np.abs(bbox[3])]
quad[tuple(bbox)] = [qp, qw]
#Define mesh
mesh = dmesh.create_rectangle(MPI.COMM_WORLD, [(-1, -1), (+1, +1)], (nx, ny), dmesh.CellType.quadrilateral)
tdim = mesh.topology.dim
comm = mesh.comm
#Create necessary mesh entities
imap = mesh.topology.index_map(tdim)
ncell = imap.size_local + imap.num_ghosts
cells_local = np.arange(ncell, dtype=np.int32)
cell_tags = dmesh.meshtags(mesh, tdim, entities=cells_local, values=cells_local)
assert ncell > 0, "Too many processors"
c2v = dmesh.entities_to_geometry(mesh, tdim, cells_local, False)
verts = mesh.geometry.x
#Create measure for each cell
for c in cells_local:
#Get bounding box
cell_verts = verts[c2v[c]].T
bbox = verts_to_bbox(cell_verts)
#Retrieve quadrature rule
[qp, qw] = quad[tuple(bbox)]
#Define measure
metadata={'quadrature_rule': 'custom', 'quadrature_points': qp, 'quadrature_weights':qw}
dx_cell = ufl.Measure('dx', domain=mesh, subdomain_id=c, subdomain_data=cell_tags, metadata=metadata)
if c == 0:
dx = dx_cell
else:
dx += dx_cell
#Define variational problem projecting 1 into V
V = fem.functionspace(mesh, ('CG', 1))
u, v = ufl.TrialFunction(V), ufl.TestFunction(V)
a = u*v*dx
L = v*dx
#Solve
problem = fem.petsc.LinearProblem(a, L, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
uh = problem.solve()
uh.x.scatter_forward()
#Assemble functional of solution
Ju_local = fem.assemble_scalar(fem.form(uh*uh*ufl.dx))
Ju_global = mesh.comm.allreduce(Ju_local, op=MPI.SUM)
print(comm.rank, Ju_global)
If I replace metadata with an empty dictionary, then I get a value of 4.0 on both 1 and 2 cores. What am I doing wrong?