Parallel implementation using mesh.geometry.dofmap

Hi everyone,

I’m encountering an issue while implementing parallel processing in my code. It seems that when I try to compute an internal area enclosed by a surface mesh, there’s a problem when the function calls the indexes.

Below is my MWE:

import os

from mpi4py import MPI # type: ignore
from dolfinx.io import XDMFFile, gmshio # type: ignore

import basix.ufl # type: ignore
import dolfinx # type: ignore
import gmsh  # type: ignore
import numpy as np


def gmsh_circle(model: gmsh.model, name: str) -> gmsh.model:
    """Create a Gmsh model of a circle.
    """

    model.add(name)
    model.setCurrent(name)
    
    gmsh.option.setNumber("Mesh.CharacteristicLengthFactor", h)

    circle = model.occ.addDisk(0, 0, 0, R, R, tag=1)

    # Synchronize OpenCascade representation with gmsh model
    model.occ.synchronize()

    # Add physical marker for cells. It is important to call this
    # function after OpenCascade synchronization
    model.add_physical_group(dim=1, tags=[circle])

    # Generate the mesh
    model.mesh.generate(dim=1)
    model.mesh.setOrder(2)

    return model

def create_mesh(comm: MPI.Comm, model: gmsh.model, name: str, filename: str, mode: str):
    """Create a DOLFINx from a Gmsh model and output to file.
    """
    msh, ct, ft = gmshio.model_to_mesh(model, comm, rank=0, gdim=2)
    msh.name = name
    ct.name = f"{msh.name}_cells"
    ft.name = f"{msh.name}_facets"
    
    with XDMFFile(msh.comm, filename, mode) as file:
        msh.topology.create_connectivity(0, 1)
        file.write_mesh(msh)

def order_dofs(dof):
    """Sort the dofs in order.
    """

    len,_= dof.shape
    # print(type(dof))
    dof_ordered = np.empty_like(dof)
    dof_ordered[0,:] = dof[0,:]
    
    for i in range(len):
        pos = 0
        for j in range(len):
            if dof[j,0] == dof_ordered[i,1]:
                pos = j
                break
        if pos != 0:
            dof_ordered[i+1,:] = dof[pos,:]     
            
    return dof_ordered

def area(dofs,coordinates):
    """Compute the area with the dofs and coordinates.
    """

    num_ele, _ = dofs.shape

    area = 0
    count = 0

    for i in range(num_ele):
        x1 = dofs[i,0]
        x2 = dofs[i,2]
        x3 = dofs[i,1]        
        area += coordinates[x1,0]*coordinates[x2,1] - coordinates[x1,1]*coordinates[x2,0]
        area += coordinates[x2,0]*coordinates[x3,1] - coordinates[x2,1]*coordinates[x3,0]

    area  = 1/2 * abs(area)

    return area

gmsh.initialize()
gmsh.option.setNumber("General.Terminal", 0)

h = 1e-2
R = 1

# Create model
model = gmsh.model()
model = gmsh_circle(model, "circle")
model.setCurrent("circle")

create_mesh(MPI.COMM_SELF, model, "circle", f"out_gmsh/mesh_rankCircle_{MPI.COMM_WORLD.rank}.xdmf", "w")

with XDMFFile(MPI.COMM_WORLD, "out_gmsh/mesh_rankCircle_0.xdmf", "r") as xdmf:
    mesh = xdmf.read_mesh(name="circle")

mesh.topology.create_connectivity(mesh.topology.dim-1, mesh.topology.dim)

gmsh.finalize

dof_ordered = order_dofs(mesh.geometry.dofmap)  # Order dofs only once
area_init = area(dof_ordered, mesh.geometry.x)   # Calculate area_init only once


The code works well when run sequentially, but when running in parallel, there is a conflict with the index handling across processes and I also tried implementing the following:

if MPI.COMM_WORLD.rank == 0
    dof_ordered = order_dofs(mesh.geometry.dofmap)  # Order dofs only once
    area_init = area(dof_ordered, mesh.geometry.x)   # Calculate area_init only once

However, this approach didn’t resolve the issue

I would greatly appreciate any help or suggestions on how to resolve this issue.

Best regards,

Best,