Gmshio can't successfully read the msh file created by Gmsh

When I used stl file to create 3D mesh, which contained 10 boundary layers. When the boundary layers were not saved, it works well. But since the mesh file contained the boundary layers, it seemed not work. My code is below, I don’t know why it doesn’t work:
import gmsh
import sys
import os
import math

gmsh.initialize(sys.argv)
path = os.path.dirname(os.path.abspath(file))
gmsh.merge(os.path.join(path, ‘xuluwen.stl’))
gmsh.model.mesh.classifySurfaces(math.pi, True, True)
gmsh.model.mesh.createGeometry()
extrude = True
if extrude:
gmsh.option.setNumber(‘Geometry.ExtrudeReturnLateralEntities’, 0)
sur=gmsh.model.getEntities(2)
surface = [s[1] for s in sur]
print(surface)
e = gmsh.model.geo.extrudeBoundaryLayer(gmsh.model.getEntities(2), [10], [-1],True)
print(e)
# get “top” surfaces created by extrusion
top_ent = [s for s in e if s[0] == 2] #boundary surfaces(interior)
top_surf = [s[1] for s in top_ent]
print(top_surf)
# get boundary of top surfaces, i.e. boundaries of holes
gmsh.model.geo.synchronize()
bnd_ent = gmsh.model.getBoundary(top_ent) #boundary curves
bnd_curv = [c[1] for c in bnd_ent]
print(bnd_curv)
# create plane surfaces filling the holes
loops = gmsh.model.geo.addCurveLoops(bnd_curv)
print(loops)
for l in loops:
top_surf.append(gmsh.model.geo.addPlaneSurface([l]))
print(top_surf)
sur_boundary=gmsh.model.getEntities(2)
surface_boundary = [s[1] for s in sur_boundary]
print(surface_boundary)
splenic_marker=1
smv_marker=2
portal_marker=3
wall_marker=4
domain_marker=5
gmsh.model.geo.addPhysicalGroup(2,[211,42],splenic_marker)
gmsh.model.setPhysicalName(2,splenic_marker,‘splenic’)
gmsh.model.geo.addPhysicalGroup(2,[212,56,99],smv_marker)
gmsh.model.setPhysicalName(2,smv_marker,‘smv’)
gmsh.model.geo.addPhysicalGroup(2,[213,133,177],portal_marker)
gmsh.model.setPhysicalName(2,portal_marker,‘portal’)
gmsh.model.geo.addPhysicalGroup(2,surface,wall_marker)
gmsh.model.setPhysicalName(2,wall_marker,‘wall’)
gmsh.model.geo.addPhysicalGroup(3,[1,2,3,4,5,6,7,8,9,10,11],domain_marker)
gmsh.model.setPhysicalName(3,domain_marker,‘domain’)
gmsh.model.geo.addVolume([gmsh.model.geo.addSurfaceLoop(top_surf)])
gmsh.model.geo.synchronize()
gmsh.option.setNumber(‘Mesh.Algorithm’, 1)
gmsh.option.setNumber(‘Mesh.MeshSizeFactor’, 0.1)
gmsh.model.mesh.generate(3)
gmsh.write(‘msh_generate.msh’)
gmsh.finalize()
import numpy as np
import matplotlib.pyplot as plt
import tqdm.autonotebook

from mpi4py import MPI
from petsc4py import PETSc

from dolfinx.cpp.mesh import to_type, cell_entity_type
from dolfinx.fem import (Constant, Function, FunctionSpace,
assemble_scalar, dirichletbc, form, locate_dofs_topological, set_bc)
from dolfinx.fem.petsc import (apply_lifting, assemble_matrix, assemble_vector,
create_vector, create_matrix, set_bc)
from dolfinx.graph import adjacencylist
from dolfinx.geometry import bb_tree, compute_collisions_points, compute_colliding_cells
from dolfinx.io import (VTXWriter, distribute_entity_data, gmshio)
from dolfinx.mesh import create_mesh, meshtags_from_entities
from ufl import (FacetNormal, FiniteElement, Identity, Measure, TestFunction, TrialFunction, VectorElement, as_vector, div, dot, ds, dx, inner, lhs, grad, nabla_grad, rhs, sym)
gdim = 3
mesh_comm = MPI.COMM_WORLD
model_rank = 0
mesh,ct, ft = gmshio.read_from_msh(“msh_generate.msh”, MPI.COMM_WORLD, 0, gdim=3)

Without the stl its very hard to help you. Please also note that all code should be formatted with 3x`, i.e.

```python
# Add code here
```

You also haven’t posted what kind of error message you are receiving, which makes it even harder to guide you.

```python
import gmsh
import sys
import os
import math

gmsh.initialize(sys.argv)
path = os.path.dirname(os.path.abspath(**file**))
gmsh.merge(os.path.join(path, ‘xuluwen.stl’))
gmsh.model.mesh.classifySurfaces(math.pi, True, True)
gmsh.model.mesh.createGeometry()
extrude = True
if extrude:
gmsh.option.setNumber(‘Geometry.ExtrudeReturnLateralEntities’, 0)
sur=gmsh.model.getEntities(2)
surface = [s[1] for s in sur]
print(surface)
e = gmsh.model.geo.extrudeBoundaryLayer(gmsh.model.getEntities(2), [10], [-1],True)
print(e)
# get “top” surfaces created by extrusion
top_ent = [s for s in e if s[0] == 2] #boundary surfaces(interior)
top_surf = [s[1] for s in top_ent]
print(top_surf)
# get boundary of top surfaces, i.e. boundaries of holes
gmsh.model.geo.synchronize()
bnd_ent = gmsh.model.getBoundary(top_ent) #boundary curves
bnd_curv = [c[1] for c in bnd_ent]
print(bnd_curv)
# create plane surfaces filling the holes
loops = gmsh.model.geo.addCurveLoops(bnd_curv)
print(loops)
for l in loops:
top_surf.append(gmsh.model.geo.addPlaneSurface([l]))
print(top_surf)
sur_boundary=gmsh.model.getEntities(2)
surface_boundary = [s[1] for s in sur_boundary]
print(surface_boundary)
splenic_marker=1
smv_marker=2
portal_marker=3
wall_marker=4
domain_marker=5
gmsh.model.geo.addPhysicalGroup(2,[211,42],splenic_marker)
gmsh.model.setPhysicalName(2,splenic_marker,‘splenic’)
gmsh.model.geo.addPhysicalGroup(2,[212,56,99],smv_marker)
gmsh.model.setPhysicalName(2,smv_marker,‘smv’)
gmsh.model.geo.addPhysicalGroup(2,[213,133,177],portal_marker)
gmsh.model.setPhysicalName(2,portal_marker,‘portal’)
gmsh.model.geo.addPhysicalGroup(2,surface,wall_marker)
gmsh.model.setPhysicalName(2,wall_marker,‘wall’)
gmsh.model.geo.addPhysicalGroup(3,[1,2,3,4,5,6,7,8,9,10,11],domain_marker)
gmsh.model.setPhysicalName(3,domain_marker,‘domain’)
gmsh.model.geo.addVolume([gmsh.model.geo.addSurfaceLoop(top_surf)])
gmsh.model.geo.synchronize()
gmsh.option.setNumber(‘Mesh.Algorithm’, 1)
gmsh.option.setNumber(‘Mesh.MeshSizeFactor’, 0.1)
gmsh.model.mesh.generate(3)
gmsh.write(‘msh_generate.msh’)
gmsh.finalize()
import numpy as np
import matplotlib.pyplot as plt
import tqdm.autonotebook

from mpi4py import MPI
from petsc4py import PETSc

from dolfinx.cpp.mesh import to_type, cell_entity_type
from dolfinx.fem import (Constant, Function, FunctionSpace,
assemble_scalar, dirichletbc, form, locate_dofs_topological, set_bc)
from dolfinx.fem.petsc import (apply_lifting, assemble_matrix, assemble_vector,
create_vector, create_matrix, set_bc)
from dolfinx.graph import adjacencylist
from dolfinx.geometry import bb_tree, compute_collisions_points, compute_colliding_cells
from [dolfinx.io](http://dolfinx.io) import (VTXWriter, distribute_entity_data, gmshio)
from dolfinx.mesh import create_mesh, meshtags_from_entities
from ufl import (FacetNormal, FiniteElement, Identity, Measure, TestFunction, TrialFunction, VectorElement, as_vector, div, dot, ds, dx, inner, lhs, grad, nabla_grad, rhs, sym)
gdim = 3
mesh_comm = MPI.COMM_WORLD
model_rank = 0
mesh,ct, ft = gmshio.read_from_msh(“msh_generate.msh”, MPI.COMM_WORLD, 0, gdim=3)

As you haven’t provided the error message, how are you expecting anyone to give you guidance?

Please note that your code contains errors, such as

which would make it unrunnable.

Secondly, one should never call synchronize after setting physical entities, i.e.

is not right. Please ensure that you add volume and synchronize prior to defining any physical group.

I’m very sorry, I’m not very proficient in coding. Below is the error message:


Info    : Writing 'msh_generate.msh'...
Info    : Done writing 'msh_generate.msh'
Info    : Reading 'msh_generate.msh'...
Info    : 130 entities
Info    : 55817 nodes
Info    : 136219 elements
Info    : 10 parametrizations                                              
Info    : [  0%] Processing parametrizations                                    Info    : [ 10%] Processing parametrizations                                    Info    : [ 20%] Processing parametrizations                                    Info    : [ 30%] Processing parametrizations                                    Info    : [ 40%] Processing parametrizations                                    Info    : [ 50%] Processing parametrizations                                    Info    : [ 60%] Processing parametrizations                                    Info    : [ 70%] Processing parametrizations                                    Info    : [ 80%] Processing parametrizations                                    Info    : [ 90%] Processing parametrizations                                    Info    : Done reading 'msh_generate.msh'
[0]PETSC ERROR: ------------------------------------------------------------------------
[0]PETSC ERROR: Caught signal number 11 SEGV: Segmentation Violation, probably memory access out of range
[0]PETSC ERROR: Try option -start_in_debugger or -on_error_attach_debugger
[0]PETSC ERROR: or see https://petsc.org/release/faq/#valgrind and https://petsc.org/release/faq/
[0]PETSC ERROR: configure using --with-debugging=yes, recompile, link, and run 
[0]PETSC ERROR: to get more information on the crash.
[0]PETSC ERROR: Run with -malloc_debug to check if memory corruption is causing the crash.
Abort(59) on node 0 (rank 0 in comm 0): application called MPI_Abort(MPI_COMM_WORLD, 59) - process 0

This is likely due to the fact that you are synchronizing after adding groups, please avoid that

Thank you so much. But when I delete the synchronizing code you remained, new errors raised:



Info    : Writing 'msh_generate.msh'...
Info    : Done writing 'msh_generate.msh'
Info    : Reading 'msh_generate.msh'...
Info    : 126 entities
Info    : 53185 nodes
Info    : 119988 elements
Info    : 10 parametrizations                                              
Info    : [  0%] Processing parametrizations                                    Info    : [ 10%] Processing parametrizations                                    Info    : [ 20%] Processing parametrizations                                    Info    : [ 30%] Processing parametrizations                                    Info    : [ 40%] Processing parametrizations                                    Info    : [ 50%] Processing parametrizations                                    Info    : [ 60%] Processing parametrizations                                    Info    : [ 70%] Processing parametrizations                                    Info    : [ 80%] Processing parametrizations                                    Info    : [ 90%] Processing parametrizations                                    Info    : Done reading 'msh_generate.msh'
Traceback (most recent call last):
  File "/public/home/cxr1/fenics/msh_generate.py", line 142, in <module>
    mesh,ct, ft = gmshio.read_from_msh("msh_generate.msh", MPI.COMM_WORLD, 0, gdim=3)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/public/home/cxr1/.conda/envs/fenicsx/lib/python3.12/site-packages/dolfinx/io/gmshio.py", line 332, in read_from_msh
    msh = model_to_mesh(gmsh.model, comm, rank, gdim=gdim, partitioner=partitioner)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/public/home/cxr1/.conda/envs/fenicsx/lib/python3.12/site-packages/dolfinx/io/gmshio.py", line 232, in model_to_mesh
    cell_id = cell_information[perm_sort[-1]]["id"]
                               ~~~~~~~~~^^^^
IndexError: index -1 is out of bounds for axis 0 with size 0

This is because you haven’t added a physical group for the volume. You should:

  1. Define all lines, surfaces and volumes
  2. Synchronize
  3. Define physical groups for volume and surfaces
  4. Generate mesh

I define a physical group for the volume used this code, the indices include the whole volume domain, and I added a physical group for every surface on the surface.


gmsh.model.geo.addPhysicalGroup(3,[1,2,3,4,5,6,7,8,9,10,11],domain_marker)
gmsh.model.setPhysicalName(3,domain_marker,‘domain’)

Please provide your up to date script (for any proper guidance, we would need the stl).

Please also ensure that the physical groups looks correct in the msh file by opening it with gmsh and navigate to “Tools->Visibility” and then change “Elementary entities” dropdown to Physical groups, and ensure that each group looks sensible, and that there are no duplicate surfaces or volumes.

The update script is as follows: and how can I provide the stl to you?

import gmsh
import sys
import os
import math
gmsh.initialize(sys.argv)
path = os.path.dirname(os.path.abspath(__file__))
gmsh.merge(os.path.join(path, 'xuluwen.stl'))
gmsh.model.mesh.classifySurfaces(math.pi, True, True)
gmsh.model.mesh.createGeometry()
extrude = True
if extrude:
    gmsh.option.setNumber('Geometry.ExtrudeReturnLateralEntities', 0)
    sur=gmsh.model.getEntities(2)
    surface = [s[1] for s in sur]
    print(surface)
    e = gmsh.model.geo.extrudeBoundaryLayer(gmsh.model.getEntities(2), [10], [-1],True)
    print(e)
    top_ent = [s for s in e if s[0] == 2] 
    top_surf = [s[1] for s in top_ent]
    print(top_surf)
    gmsh.model.geo.synchronize()
    bnd_ent = gmsh.model.getBoundary(top_ent)
    bnd_curv = [c[1] for c in bnd_ent]
    print(bnd_curv)
    loops = gmsh.model.geo.addCurveLoops(bnd_curv)
    print(loops)
    for l in loops:
        top_surf.append(gmsh.model.geo.addPlaneSurface([l]))
    print(top_surf)
    sur_boundary=gmsh.model.getEntities(2)
    surface_boundary = [s[1] for s in sur_boundary]
    print(surface_boundary)
    splenic_marker=1
    smv_marker=2
    portal_marker=3
    wall_marker=4
    domain_marker=5
    gmsh.model.geo.synchronize()
    gmsh.model.geo.addPhysicalGroup(2,[211,42],splenic_marker)
    gmsh.model.setPhysicalName(2,splenic_marker,'splenic')
    gmsh.model.geo.addPhysicalGroup(2,[212,56,99],smv_marker)
    gmsh.model.setPhysicalName(2,smv_marker,'smv')
    gmsh.model.geo.addPhysicalGroup(2,[213,133,177],portal_marker)
    gmsh.model.setPhysicalName(2,portal_marker,'portal')
    gmsh.model.geo.addPhysicalGroup(2,surface,wall_marker)
    gmsh.model.setPhysicalName(2,wall_marker,'wall')
    gmsh.model.geo.addPhysicalGroup(3,[1,2,3,4,5,6,7,8,9,10,11],domain_marker)
    gmsh.model.setPhysicalName(3,domain_marker,'domain') 
    gmsh.model.geo.addVolume([gmsh.model.geo.addSurfaceLoop(top_surf)])
    gmsh.model.geo.synchronize()

gmsh.option.setNumber('Mesh.Algorithm', 1)
gmsh.option.setNumber('Mesh.MeshSizeFactor', 0.1)
gmsh.model.mesh.generate(3)
gmsh.write('msh_generate.msh')
gmsh.finalize()
import numpy as np
import matplotlib.pyplot as plt
import tqdm.autonotebook

from mpi4py import MPI
from petsc4py import PETSc

from dolfinx.cpp.mesh import to_type, cell_entity_type
from dolfinx.fem import (Constant, Function, FunctionSpace,
                         assemble_scalar, dirichletbc, form, locate_dofs_topological, set_bc)
from dolfinx.fem.petsc import (apply_lifting, assemble_matrix, assemble_vector,
                               create_vector, create_matrix, set_bc)
from dolfinx.graph import adjacencylist
from dolfinx.geometry import bb_tree, compute_collisions_points, compute_colliding_cells
from dolfinx.io import (VTXWriter, distribute_entity_data, gmshio)
from dolfinx.mesh import create_mesh, meshtags_from_entities

from ufl import (FacetNormal, FiniteElement, Identity, Measure, TestFunction, TrialFunction, VectorElement, as_vector, div, dot, ds, dx, inner, lhs, grad, nabla_grad, rhs, sym)
gdim = 3
mesh_comm = MPI.COMM_WORLD
model_rank = 0
mesh,ct, ft = gmshio.read_from_msh("msh_generate.msh", MPI.COMM_WORLD, 0, gdim=3)

the screenshot of Gmsh is as follows:

Now the error is like this, but the .msh can be opened through Gmsh:

Info    : Done reading 'msh_generate.msh'
Traceback (most recent call last):
  File "/public/home/cxr1/fenics/msh_generate.py", line 143, in <module>
    mesh,ct, ft = gmshio.read_from_msh("msh_generate.msh", MPI.COMM_WORLD, 0, gdim=3)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/public/home/cxr1/.conda/envs/fenicsx/lib/python3.12/site-packages/dolfinx/io/gmshio.py", line 332, in read_from_msh
    msh = model_to_mesh(gmsh.model, comm, rank, gdim=gdim, partitioner=partitioner)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/public/home/cxr1/.conda/envs/fenicsx/lib/python3.12/site-packages/dolfinx/io/gmshio.py", line 268, in model_to_mesh
    local_entities, local_values = _cpp.io.distribute_entity_data(
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MemoryError: std::bad_alloc
(fenicsx) [cxr1@master fenics]$ gmsh msh_generate.msh

If the stl can fit as plain-text in a post here, that would be preferable, if that is not possible, please share a link to a shared space, such as a public github repo or similar where you put the stl file.

My best guess is that

is not right.
What is the output of print(gmsh.model.getEntities(dim=3))

Note that you are still synchronizing at the end of your script:

I’m so sorry that I’m not very familiar with the code

gmsh.model.geo.synchronize()

When I delete the code, the surface filled valid, so I add it again.
I will set a public github repo now, please wait me a few minitues

I have uploaded the stl and script at here. Could you open it?

I would strongly suggest to not use the built in model (geo) and rather use occ as you can do boolean operations with it. It is quite hard for me to get into the specifics of your problem, as your mesh consists of mixed elements (wedges and tetrahedra) which is currently not supported in DOLFINx. The mesh needs to consist of a single cell type, say only tetrahedra or only hexahedral elements.