Renumbered .msh imported data giving wrong subdomains

There are a few things to consider here.
Python has a zero index as a starting point, GMSH starts with index 1. That means that you need to add 1 to any result that you get from DOLFINx (as the input index relates to the index in a python data structure.

Secondly, we do not associate the original_cell_index with the index it had in GMSH, as in the msh format, there might be cells that are not part of the actual mesh.
Following is a code that highlights that the vertices have the correct global numbering, but it then also shows you that for DOLFINx to read a msh file, we extract cells by their physical group, and order them in an array (which the input global index is relative to):


from mpi4py import MPI
import dolfinx
import numpy as np
mesh, subdomains, boundaries = dolfinx.io.gmshio.read_from_msh("mh104.msh", MPI.COMM_WORLD,0, gdim=3)
o_cell_idx= mesh.topology.original_cell_index

c_to_node = dolfinx.mesh.entities_to_geometry(mesh, mesh.topology.dim, np.arange(len(o_cell_idx), dtype=np.int32))
# Sort entities to make them comparable
c_to_node = np.sort(c_to_node, axis=1)
coord=mesh.geometry.x

o_node_idx = mesh.geometry.input_global_indices
# Inspecting gmsh:
# 1116 2 2 2 276 2140 2145 2141
# 2140 0 5.740535104259405e-05 0.1428603951628746
# 2145 0 8.756520587749979e-05 0.1428477232139085
# 2141 0 0.0001658069490290491 0.1428511737801536

# Get vertices of given cell (subtract 1 from gmsh to get correct python index)
v0 = np.flatnonzero(o_node_idx == 2139)
v1 = np.flatnonzero(o_node_idx == 2144)
v2 = np.flatnonzero(o_node_idx == 2140)
input_vertices = np.sort(np.hstack([v0,v1,v2]))
# Find cell with matching indices
cell_index_python = np.flatnonzero(np.all(input_vertices == c_to_node, axis=1))
print(o_cell_idx[cell_index_python], coord[input_vertices])
print(coord[v0], coord[v1], coord[v2])


# Inspect pure gmsh 
import gmsh
gmsh.initialize()
gmsh.model.add("Mesh from file")
gmsh.merge("mh104.msh")
breakpoint()
# Extract all cells as done by DOLFINx when reading in the mesh (but do not subtract the 1 from the gmsh topology)
# for easy comparison
phys_grps = gmsh.model.getPhysicalGroups()
topologies = []
for dim, tag in phys_grps:
    if dim == 2:
        entities = gmsh.model.getEntitiesForPhysicalGroup(dim, tag)
        for entity in entities:
            (entity_types, entity_tags, entity_topologies) = gmsh.model.mesh.getElements(dim, tag=entity)
            assert len(entity_types) == 1

            properties = gmsh.model.mesh.getElementProperties(entity_types[0])
            name, dim, _, num_nodes, _, _ = properties
            topology = entity_topologies[0].reshape(-1, num_nodes)
            topologies.append(topology)

print(np.vstack(topologies)[o_cell_idx[cell_index_python]])

You can create your own gmsh reader that respect the ordering in the msh file,

import gmsh
gmsh.initialize()
gmsh.model.add("Mesh from file")
gmsh.merge("mh104.msh")

# Extract cells in original order
topologies_2 = []
entities = gmsh.model.getEntities()
entities_sorted = np.sort([e[1] for e in entities])
for obj in entities_sorted:
    (entity_types, entity_tags, entity_topologies) = gmsh.model.mesh.getElements(2, tag=obj)
    assert len(entity_types) == 1
    properties = gmsh.model.mesh.getElementProperties(entity_types[0])
    name, dim, _, num_nodes, _, _ = properties
    topology = entity_topologies[0].reshape(-1, num_nodes)
    topologies_2.append(topology)

topologies_2 = np.vstack(topologies_2)
print(topologies_2[1115])

and then replicate everything in

(if you want facet tags you need to call get entities(1) as well.

1 Like