Transitioning from mesh.xml to mesh.xdmf, from dolfin-convert to meshio

Something is wrong with your msh file, as you have

but if you open the mesh in gmsh, there are no Physical Groups in the mesh (Tools->Visibility->Physical Groups). Thus meshio cannot read the mesh.
If you believe your mesh is correct, I would suggest making an issue at: Sign in to GitHub · GitHub

Thank you, you are right it does not read the msh file correctly. I exported the mesh from gmsh and I am using the same method as before but now it is not working now.

I would suggest providing your .geo file or the Python script you used to generate the mesh

1 Like

I can confirm that I am able to generate my 3d mesh using gmsh app but cannot convert it to xdmf on FEniCS somehow. Here is my code:

x_max = 2
y_max = 3
z_max = 4

# Mesh size
h = 0.1

mesh_script  = "Point(1) = {{{0}, {1}, {2}, {3}}};\n".format(0, 0, 0, 1)
mesh_script += "Point(2) = {{{0}, {1}, {2}, {3}}};\n".format(x_max, 0, 0, 1)
mesh_script += "Point(3) = {{{0}, {1}, {2}, {3}}};\n".format(x_max, y_max, 0, 1)
mesh_script += "Point(4) = {{{0}, {1}, {2}, {3}}};\n".format(0, y_max, 0, 1)

mesh_script += "Point(5) = {{{0}, {1}, {2}, {3}}};\n".format(0, 0, z_max, 1)
mesh_script += "Point(6) = {{{0}, {1}, {2}, {3}}};\n".format(x_max, 0, z_max, 1)
mesh_script += "Point(7) = {{{0}, {1}, {2}, {3}}};\n".format(x_max, y_max, z_max, 1)
mesh_script += "Point(8) = {{{0}, {1}, {2}, {3}}};\n".format(0, y_max, z_max, 1)

mesh_script += "Line(1) = {1, 2};\n"
mesh_script += "Line(2) = {2, 3};\n"
mesh_script += "Line(3) = {3, 4};\n"
mesh_script += "Line(4) = {4, 1};\n"

mesh_script += "Line(5) = {1, 5};\n"
mesh_script += "Line(6) = {2, 6};\n"
mesh_script += "Line(7) = {3, 7};\n"
mesh_script += "Line(8) = {4, 8};\n"

mesh_script += "Line(9) = {5, 6};\n"
mesh_script += "Line(10) = {6, 7};\n"
mesh_script += "Line(11) = {7, 8};\n"
mesh_script += "Line(12) = {8, 5};\n"

mesh_script += "Curve Loop(1) = {8, -11, -7, 3};\n"
mesh_script += "Plane Surface(1) = {1};\n"

mesh_script += "Curve Loop(2) = {7, -10, -6, 2};\n"
mesh_script += "Plane Surface(2) = {2};\n"

mesh_script += "Curve Loop(3) = {2, 3, 4, 1};\n"
mesh_script += "Plane Surface(3) = {3};\n"

mesh_script += "Curve Loop(4) = {4, 5, -12, -8};\n"
mesh_script += "Plane Surface(4) = {4};\n"

mesh_script += "Curve Loop(5) = {12, 9, 10, 11};\n"
mesh_script += "Plane Surface(5) = {5};\n"

mesh_script += "Curve Loop(6) = {6, -9, -5, 1};\n"
mesh_script += "Plane Surface(6) = {6};\n"

mesh_script += "Surface Loop(1) = {4, 3, 2, 1, 5, 6};\n"
mesh_script += "Volume(1) = {1};\n"

mesh_script += "MeshSize {1, 2, 3, 4, 5, 6, 7, 8}"
mesh_script += " = {0};\n".format(h)

mesh_script += "Physical Surface(201) = {1, 2, 3, 4, 5, 6};\n"
mesh_script += "Physical Volume(301) = {1};\n"

print("Running Gmsh...")
geo_file=open("mesh.geo",'w')
geo_file.write(mesh_script)
geo_file.close()
gmsh_err=call(["gmsh", "-3", "mesh.geo", "-o", "mesh.msh"])
if gmsh_err:
    print("...mesh cannot be generated!")
else:
    print("...mesh generated successfully!")

def mesh_generation(mesh_script):

    print("Running Gmsh...")
    geo_file=open("mesh.geo",'w')
    geo_file.write(mesh_script)
    geo_file.close()
    gmsh_err=call(["gmsh", "-3", "mesh.geo", "-o", "mesh.msh"])
    if gmsh_err:
        print("...something bad happened \
        when the mesh was being generated...")
    else:
        print("...mesh generated successfully!")

    msh = meshio.read("mesh.msh")

    line_cells = []
    for cell in msh.cells:
        if cell.type == "triangle":
            triangle_cells = cell.data
        elif  cell.type == "line":
            if len(line_cells) == 0:
                line_cells = cell.data
            else:
                line_cells = np.vstack([line_cells, cell.data])

    line_data = []
    for key in msh.cell_data_dict["gmsh:physical"].keys():
        if key == "line":
            if len(line_data) == 0:
                line_data = \
                msh.cell_data_dict["gmsh:physical"][key]
            else:
                line_data = \
                np.vstack([line_data, \
                msh.cell_data_dict["gmsh:physical"][key]])
        elif key == "triangle":
            triangle_data = \
            msh.cell_data_dict["gmsh:physical"][key]

    triangle_mesh = \
    meshio.Mesh(points=msh.points, \
    cells={"triangle": triangle_cells})
    line_mesh = \
    meshio.Mesh(points=msh.points,\
    cells=[("line", line_cells)],\
    cell_data={"name_to_read":[line_data]})
    meshio.write("mesh.xdmf", triangle_mesh)

    meshio.xdmf.write("mf.xdmf", line_mesh)

    mesh = Mesh()
    with XDMFFile("mesh.xdmf") as infile:
        infile.read(mesh)
    mvc = MeshValueCollection("size_t", mesh, 2)
    with XDMFFile("mf.xdmf") as infile:
        infile.read(mvc, "name_to_read")
    mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)
    
    mesh_data = [mesh, mvc, mf]

    return mesh_data

from subprocess import call

mesh_data   = mesh_generation(mesh_script)

mesh = mesh_data[0]
mvc  = mesh_data[1]
mf   = mesh_data[2]

I am getting an “IndexError: tuple index out of range”.
I am trying to follow up .msh to xdmf for 3D from here. Can anyone help? Thanks!

Maybe this is a bit a silly question, but would it work as well to convert a xdmf file back into both a .msh file and a .xml file? Should only the file types be adjusted, or would such a conversion not be that simple?

import meshio
msh = meshio.read("mesh.xdmf")
for cell in xdmf.cells:
    if cell.type == "triangle":
        triangle_cells = cell.data
    elif  cell.type == "tetra":
        tetra_cells = cell.data

for key in 
xdmf.cell_data_dict["gmsh:physical"].keys():
    if key == "triangle":
        triangle_data = 
xdmf.cell_data_dict["gmsh:physical"][key]
    elif key == "tetra":
        tetra_data = msh.cell_data_dict["gmsh:physical"][key]
tetra_mesh = meshio.Mesh(points=xdmf.points, cells={"tetra": tetra_cells})
triangle_mesh =meshio.Mesh(points=xdmf.points,
                           cells=[("triangle", triangle_cells)],
                           cell_data={"name_to_read":[triangle_data]})
meshio.write("mesh.xml", tetra_mesh)

meshio.write("mf.xml", triangle_mesh)

Yes, meshio can convert back to xml or msh. However, Im not sure what support there is for markers in the “to msh” conversion.

For xml i guess you would have to merge the two meshes together, as the input mesh was originally in a single file.

Hello, dear @dokken I have several questions.
Firstly, using Gmsh I created .geo file and .msh file as well. For starting my simulation I need to convert .msh file to .xml.gz file. When I try to use dolfin-convert I get error that:

File “/usr/lib/python2.7/dist-packages/dolfin_utils/meshconvert/meshconvert.py”, line 279, in gmsh2xml
num_elements = int(line)
ValueError: invalid literal for int() with base 10: ‘124 10780 1 10780\n’

Due to reading your discussion I find information that dolfin-convert isn’t maintained anymore, so I install Meshio for making converting.
Secondly, while instalation I get message that:

use --no-warn-script-location.

And Meshio installed on /home/magnumfe/.local/bin , so I change my ~/.bashrc file and add line export PATH=“/home/magnumfe/.local/bin:$PATH”
Unfortunately, command meshio convert doesn’t work I get message:

meshio: command not found

And when I try to use script,

Summary

import meshio
import numpy

msh = meshio.read(“newcil.msh”)

def create_mesh(mesh, cell_type, prune_z=False):
cells = mesh.get_cells_type(cell_type)
cell_data = mesh.get_cell_data(“gmsh:physical”, cell_type)
out_mesh = meshio.Mesh(points=mesh.points, cells={cell_type: cells}, cell_data={“name_to_read”:[cell_data]})
if prune_z:
out_mesh.prune_z_0()
return out_mesh

msh=meshio.read(“newcil.msh”)

triangle_mesh = create_mesh(msh, “triangle”, False)
tetra_mesh = create_mesh(msh, “tetra”, False)
meshio.write(“newciltetr.xml”, tetra_mesh)
meshio.write(“newciltri.xml”, triangle_mesh)
#print(msh.cell_data_dict)
from dolfin import *
parameters[“allow_extrapolation”] = True
parameters[“form_compiler”][“optimize”] = True

mesh=Mesh()
mvc = MeshValueCollection(“size_t”, mesh, mesh.topology().dim())
with XMLFile(“newciltetr.xml”) as infile:
infile.read(mesh)
infile.read(mvc, “name_to_read”)
cf = cpp.mesh.MeshFunctionSizet(mesh, mvc)

mvc = MeshValueCollection(“size_t”, mesh, mesh.topology().dim()-1)
with XMLFile(“newciltri.xml”) as infile:
infile.read(mvc, “name_to_read”)
mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)

ds = Measure(“ds”, domain=mesh, subdomain_data=mf)

dx=Measure(“dx”, domain=mesh, subdomain_data=cf)

I get this message:

AttributeError: ‘module’ object has no attribute ‘read’

So, I will be happy to get any advice about this situation and how I can make converting from .msh to .xml.

This is my .geo file:

Summary

// Gmsh project created on Sun Oct 8 06:12:34 2023

cl = 2.5;

Point(0) = { 0, 0, 0, cl};
Point(1) = { -30, 0, 0, cl};
Point(2) = { 30, 0, 0, cl};
Point(3) = { 0, -30, 0, cl};
Point(4) = { 0, 30, 0, cl};

Circle(1) = {1, 0, 3};
Circle(2) = {3, 0, 2};
Circle(3) = {2, 0, 4};
Circle(4) = {4, 0, 1};

Line Loop(1) = {1, 2, 3, 4};

Plane Surface(1) = {1};

s0 = Extrude{0, 0, 10.0} {Surface{1}; Layers{3};};
s1 = Extrude{0, 0, -7} {Surface{s0[0]}; Layers{2};};

Point(26) = { 0, 0, 10, cl};
Point(21) = { -10, 0, 10, cl};
Point(22) = { 10, 0, 10, cl};
Point(23) = { 0, -10, 10, cl};
Point(24) = { 0, 10, 10, cl};

Circle(21) = {21, 26, 23};
Circle(22) = {23, 26, 22};
Circle(23) = {22, 26, 24};
Circle(24) = {24, 26, 21};

Line Loop(21) = {21, 22, 23, 24};

Plane Surface(2) = {21};

s2 = Extrude{0, 0, 4.0} {Surface{2}; Layers{1};};

my_new_surf = Translate {0, 0, 14}{Duplicata {Surface{1};}};
Printf(“New surface ‘%g’”, my_new_surf[0]);

s3 = Extrude{0, 0, 6.0} {Surface{71}; Layers{3};};
s4 = Extrude{0, 0, -4} {Surface{s0[0]}; Layers{2};};

Physical Volume(1) = {s0[1]};
Physical Volume(2) = {s1[1]};
Physical Volume(3) = {s2[1]};
Physical Volume(4) = {s3[1]};
Physical Volume(5) = {s4[1]};

Physical Surface(1) = {s0[0]};
Physical Surface(2) = {s1[0]};

Could you start with trying the following command on your commandline:

python3 -c "import meshio; print(meshio); print(meshio.read)"

and also add what instructions you used to install meshio?

I try this command, but get this error:

Traceback (most recent call last):
File “”, line 1, in
File “/home/natalia/mesh/meshio.py”, line 6, in
msh = meshio.read(“newcil.msh”)
AttributeError: partially initialized module ‘meshio’ has no attribute ‘read’ (most likely due to a circular import)

For installation I use instructions from meshio · PyPI
Command:

pip install meshio

And also ```
pip install meshio[all]

Linux writes that: *Requirement already satisfied.*

Do you have a file called meshio.py in your current directory? If so, please rename it as it comes first on python’s import priority.

Yes, I have this file. I rename it and try this command python3 -c “import meshio; print(meshio); print(meshio.read)” again, but get this

Traceback (most recent call last):
File “”, line 1, in
ImportError: bad magic number in ‘meshio’: b’\x03\xf3\r\n’

But I don’t have file string.

Remove any .pyc files and the __pycache__ from your directory.

Thank for advice. I did everything as you said. And after command ~/mesh$ python3 -c “import meshio; print(meshio); print(meshio.read)” get this

<module ‘meshio’ from ‘/home/natalia/.local/lib/python3.8/site-packages/meshio/init.py’>
<function read at 0x7f9bdbaeea60>

And command meshio convert still doesn’t work. Types that

meshio: command not found

I would not use the meshio convert script from terminal.
All the posts in this forum uses meshio as a python module, as it has alot more features than the command line tool.

Got it. So, for converting my mesh file .msh to .xml I will create the python file, correct? Actually i only need one operation (converting), but due to your discussions with other users I’ve realized that meshio is powerful instrument. For using meshio can I found tutorial or information exist only in this branch of dialogue?

See for instance: Mesh generation and conversion with GMSH and PYGMSH | Jørgen S. Dokken

1 Like

Dear, @dokken I have a question (again). Due to converting from .msh to .xml file with this code:

import meshio
mesh_from_file = meshio.read("my_mesh.msh")

#if I had 3D mesh how I have to put z coordinate back?
import numpy
def create_mesh(mesh, cell_type, prune_z=False):
    cells = mesh.get_cells_type(cell_type)
    cell_data = mesh.get_cell_data("gmsh:physical", cell_type)
    #points = mesh.points[:,:2] if prune_z else mesh.points
    out_mesh = meshio.Mesh(points=points, cells={cell_type: cells}, cell_data={"name_to_read":[cell_data]})
    if prune_z:
        out_mesh.prune_z_0()
    return out_mesh

#can I save in .xml format not in .xdmf?
#line_mesh = create_mesh(mesh_from_file, "line", prune_z=True)
#meshio.write("facet_my_mesh.xml", line_mesh)
tetra_mesh = create_mesh(mesh_from_file,"tetra", False)
triangle_mesh = create_mesh(mesh_from_file, "triangle", False)
meshio.write("my_mesh.xml", triangle_mesh)

meshio.write("my_mesh.xml", tetra_mesh) 

I get this error:

Traceback (most recent call last):
  File "convertmsh.py", line 2, in <module>
    mesh_from_file = meshio.read("my_mesh.msh")
  File "/home/magnumfe/.local/lib/python2.7/site-packages/meshio/helpers.py", line 176, in read
    return format_to_reader[file_format].read(filename)
  File "/home/magnumfe/.local/lib/python2.7/site-packages/meshio/msh_io/main.py", line 15, in read
    mesh = read_buffer(f)
  File "/home/magnumfe/.local/lib/python2.7/site-packages/meshio/msh_io/main.py", line 46, in read_buffer
    return reader.read_buffer(f, is_ascii, data_size)
  File "/home/magnumfe/.local/lib/python2.7/site-packages/meshio/msh_io/msh4_1.py", line 61, in read_buffer
    points, point_tags = _read_nodes(f, is_ascii, data_size)
  File "/home/magnumfe/.local/lib/python2.7/site-packages/meshio/msh_io/msh4_1.py", line 137, in _read_nodes
    assert parametric == 0, "parametric nodes not implemented"
AssertionError: parametric nodes not implemented

My .geo file is

// Gmsh project created on Sat Oct  7 09:53:39 2023

cl = 2.5;

Point(1) = {  0,  0, 0, cl};
Point(2) = { 10,  0, 0, cl};
Point(3) = {-30,  0, 0, cl};
Point(4) = { 30,  0, 0, cl};
Point(5) = {  0, 30, 0, cl};
Point(6) = {  0,-30, 0, cl};
Point(7) = {-10,  0, 0, cl};
Point(8) = {  0,-10, 0, cl};
Point(9) = {  0, 10, 0, cl};
Point(10) = { 5,  0, 0, cl};

Ellipse(1) = {5,1,2,3};
Ellipse(2) = {4,1,2,5};
Ellipse(3) = {6,1,2,3};
Ellipse(4) = {4,1,2,6};
Ellipse(5) = {9,1,10,7};
Ellipse(6) = {2,1,10,9};
Ellipse(7) = {8,1,10,7};
Ellipse(8) = {2,1,10,8};

Line Loop(9) = {1,-3,-4,2};
Plane Surface(1) = {9};
Line Loop(10) = {5,-7,-8,6};
Plane Surface(2) = {10};

s0[] = Extrude{0, 0, 8.0} {Surface{1};     Layers{3};};
s1[] = Extrude{0, 0,  3} {Surface{s0[0]}; Layers{1};};
s2[] = Extrude{0, 0,  -3.0} {Surface{2}; Layers{4};};

my_new_surf[] = Translate {0, 0, -3}{Duplicata {Surface{1};}};
Printf("New surface '%g'", my_new_surf[0]);

s3[] = Extrude{0, 0, -1.5} {Surface{77};     Layers{6};};
s4[] = Extrude{0, 0,  -4} {Surface{s3[0]}; Layers{5};};

Physical Volume(1) = {s0[1]};
Physical Volume(2) = {s1[1]};
Physical Volume(3) = {s2[1]};
Physical Volume(4) = {s3[1]};
Physical Volume(5) = {s4[1]};

I read this brunch of dialogue and saw that some people get the same error because they don’t mention physical volume/surface. As you can see my code has Physical Volume. Unfortunately, when I check .msh file I didn’t see any mention about it. Could you give me some suggestions?

MSH file

This is a pure meshio issue, as it is regarding translating a Gmsh msh file with meshio. I would strongly recommend you post a question at Issues · nschloe/meshio · GitHub
as the mesh can be read with dolfinx.io.gmshio with no issue (which uses gmsh to get the raw data structures). You could use a similar approach by following https://github.com/FEniCS/dolfinx/blob/main/python/dolfinx/io/gmshio.py#L180-L260
to get the mesh geometry and topology, and use meshio to save it.

I note that you are usinga very outdated version of python (2.7), and your issue might be resolved in a newer version of meshio

Hi Everybody,

as i am struggling to do so, Is there some kind enough to indicate which versions of gmsh/meshio permits to write these two files ?

I use
gmsh 4.11.1
meshio 4.4.0

and the following code

gmsh.initialize()
gmsh.model.add("MODEL")
# get the geometry and define the bounding box
v = gmsh.model.occ.importShapes("SLICE.step")
xmin, ymin, zmin, xmax, ymax, zmax = gmsh.model.occ.getBoundingBox(v[0][0], v[0][1])
Delta_x = xmax - xmin
Delta_y = ymax - ymin
Delta_z = zmax - zmin
Delta = np.min([Delta_x,Delta_y,Delta_z])
h = Delta /50
# add tags for surfaces
gmsh.model.occ.synchronize()


surfaces = gmsh.model.getEntities(dim=2)
for surface in surfaces:
    gmsh.model.addPhysicalGroup(2, [surface[1]], tag=surface[1])
    
gmsh.model.occ.synchronize()

# Define meshing options
gmsh.option.setNumber("Mesh.MeshSizeMin", h)
gmsh.option.setNumber("Mesh.MeshSizeMax", h)
gmsh.option.setNumber("Mesh.Algorithm", 6)   
gmsh.model.mesh.generate(3)
gmsh.model.occ.synchronize()
gmsh.write("SLICE.msh")


mesh = meshio.read("SLICE.msh")

line_cells = []
for cell in mesh.cells:
    if cell.type == "triangle":
        triangle_cells = cell.data
    elif  cell.type == "line":
        if len(line_cells) == 0:
            line_cells = cell.data
        else:
            line_cells = np.vstack([line_cells, cell.data])

line_data = []
for key in mesh.cell_data_dict["gmsh:physical"].keys():
    if key == "line":
        if len(line_data) == 0:
            line_data = mesh.cell_data_dict["gmsh:physical"][key]
        else:
            line_data = np.vstack([line_data, mesh.cell_data_dict["gmsh:physical"][key]])
    elif key == "triangle":
        triangle_data = mesh.cell_data_dict["gmsh:physical"][key]

triangle_mesh = meshio.Mesh(points=mesh.points, cells={"triangle": triangle_cells})
line_mesh =meshio.Mesh(points=mesh.points,
                           cells=[("line", line_cells)],
                           cell_data={"name_to_read":[line_data]})
meshio.write("mesh.xdmf", triangle_mesh)

meshio.xdmf.write("mf.xdmf", line_mesh)

provide the following error message :

Traceback (most recent call last):
  File "/mnt/c/Users/quent/Documents/Codes/Python/Mesh_GMSH2MeshIO/XDMF_OUTPUT_BOUNDARIES_TAGS/Conversion_GMSH2MeshIO.py", line 287, in <module>
    meshio.xdmf.write("mf.xdmf", line_mesh)
  File "/home/quentin_digimind/anaconda3/lib/python3.11/site-packages/meshio/xdmf/main.py", line 535, in write
    XdmfWriter(*args, **kwargs)
  File "/home/quentin_digimind/anaconda3/lib/python3.11/site-packages/meshio/xdmf/main.py", line 358, in __init__
    self.write_cells(mesh.cells, grid)
  File "/home/quentin_digimind/anaconda3/lib/python3.11/site-packages/meshio/xdmf/main.py", line 424, in write_cells
    NodesPerElement=str(cells[0].data.shape[1]),
                        ~~~~~~~~~~~~~~~~~~~^^^
IndexError: tuple index out of range

any help would be appreciated.

thanks,

Quentin

See up to date scripts at Mesh generation and conversion with GMSH and PYGMSH | Jørgen S. Dokken