Gmsh#
.msh read + write (v2) eager
Summary of the specification#
A Gmsh .msh file is a sequence of $Section / $EndSection blocks. $MeshFormat states the version, whether the file is ASCII or binary, and the size of a float. $Nodes lists node tags with coordinates, and $Elements lists elements with an integer type code and their node tags. $PhysicalNames maps physical group ids to names. Version 4.1 restructures nodes and elements into per-entity blocks with a leading count line, which is why the two revisions must be parsed differently.
Specification at a glance#
sections |
$MeshFormat, $PhysicalNames, $Nodes, $Elements, $Periodic |
v2 nodes |
tag x y z, one per line |
v4.1 nodes |
entity blocks: numBlocks, then per-block tags and coordinates |
element codes |
integer type ids (1 = 2-node line, 2 = triangle, 4 = tetrahedron, …) |
groups |
$PhysicalNames: dimension, tag, “name” |
Reading#
import polyxios as px
mesh = px.read("model.msh")
mesh.vertices # (n, 3)
mesh.element_types # one type code per element
Writing#
px.write(mesh, "out.msh")
px.write(mesh, "out.msh", float_fmt=".8g")
Format-specific options#
Option |
Default |
Effect |
|---|---|---|
|
|
On write: the format specifier for coordinates and data values. The default writes every float64 so it reads back unchanged. |
Quirks worth knowing#
ASCII v2 and v4.1 are both read; writing emits v2.2, the revision every consumer still understands. A binary file, or any other version, is refused with
CodecError.Each element’s physical tag is read into
element_attrs["phys_tag"], and the names$PhysicalNamesgives them become element tags, so named boundaries and volumes survive the read. The writer takesphys_tagback when it holds one value per element, and derives the physical tags fromelement_tagsotherwise.Node tags need not be contiguous; they are remapped to dense indices.
$NodeDataand$ElementDatasections becomevertex_attrsandelement_attrs, at any component count the file declares, and are written back. A field is scattered by the tag each row names, so one covering part of the mesh lands where it belongs and the rest staysNaN. A row naming an entity the mesh does not hold - an element of a type this codec skipped, say - costs that row rather than the whole field.A data section declares 1, 3 or 9 components and Gmsh refuses any other count, so a field of another width is padded out to the next of the three with zero columns and the padding is reported. The reader stays lenient and takes whatever width a file declares.
Gmsh numbers the mid-edge and face nodes of the higher-order elements by its own edge and face tables, which are not VTK’s; they are permuted on the way in and back on the way out. Gmsh’s 18-node prism becomes a
biquadratic_quadratic_wedge.Gmsh type 14, the 14-node pyramid, has no VTK equivalent and is skipped with a warning rather than reshaped into something else.
.mshis ANSYS Fluent’s extension as well, and the two are told apart by content: a file opening with$MeshFormatreads here, one opening with a parenthesised section reads as ANSYS Fluent. A bare write to.mshis Gmsh; passfmt="fluent"for the other.
See also
Supported formats - the full format table.