Skip to content

Medit / GMF (.mesh, .meshb) ​

The Medit mesh format, also known as the INRIA libMeshb GMF (Gamma Mesh Format): keyword sections in ASCII (.mesh) or a binary, position-indexed record stream (.meshb). Dispatch is purely by whether the filename ends in "b".

Format namemedit
Extensions.mesh, .meshb (.mesh is shared with MFEM: a file whose first line names an MFEM mesh is read as mfem)
Read / Write✓ / ✓
Extra dependencies—

Reading & writing ​

python
import meshioplusplus

mesh = meshioplusplus.read("mesh.mesh")
meshioplusplus.medit.write("out.mesh", mesh, float_fmt=".16e")
  • float_fmt (default ".16e") — coordinate format for the ASCII writer (the binary path's float width is dictated by the file's MeshVersionFormatted version, not by this kwarg).

The native ASCII tokenizer reads bounded views over a FileSource, retaining comment skipping, numeric-prefix behavior and version-driven dtypes. Returned arrays are owned; the writer and binary fallback are unchanged. See the text-I/O measurements.

File structure ​

ASCII (.mesh) ​

Whitespace/#-comment tokenized, keyword-driven:

MeshVersionFormatted <v>      # 0/1 -> float32 coords, 2 -> float64
Dimension <d>
Vertices
<n>
x1 x2 [x3] ref                # n rows
Triangles
<n>
v0 v1 v2 ref                  # n rows, 1-based
...
End

Recognized element keywords: Edges, Triangles, Quadrilaterals, Tetrahedra, Prisms, Pyramids, Hexahedra (and the alternate spelling Hexaedra). Every keyword listed above is followed by a count then that many rows of <node ids> <ref>. Several other keywords are recognized but discarded on read: Normals, NormalAtVertices, SubDomainFromMesh, VertexOnGeometricVertex/Edge, EdgeOnGeometricEdge, Identifier, Geometry, TangentAtVertices, Tangents, Ridges.

Binary (.meshb, libMeshb GMF) ​

A leading int32 magic code — 1 for native byte order, or its byte-swap (16777216) to signal the opposite endianness, which flips every subsequent typed read. Then an int32 version (1-4), which fixes the integer/float/ position field widths: v1 → 4-byte int, 4-byte float; v2 → 4-byte int, 8-byte float; v3 → 4-byte int, 8-byte float, 8-byte positions; v4 → 8-byte int, 8-byte float, 8-byte positions. The rest of the file is a sequence of (keyword_code, [position], [count], payload) records, each keyed by a numeric GMF field code (from a large internal table of ~200 known libMeshb field codes — only a handful are meaningful to meshio++: GmfVertices (4), GmfEdges (5), GmfTriangles (6), GmfQuadrilaterals (7), GmfTetrahedra (8), GmfPrisms (9), GmfPyramids (49), plus GmfMeshVersionFormatted (1), GmfDimension (3) and GmfEnd (54)). Records with any other code are skipped with a warning.

Cell types ​

keywordmeshio++ typenodes
Edgesline2
Trianglestriangle3
Quadrilateralsquad4
Tetrahedratetra4
Prismswedge6
Pyramidspyramid5
Hexahedra / Hexaedrahexahedron8

Data mapping ​

  • point_data["medit:ref"] — the per-vertex trailing reference integer.
  • cell_data["medit:ref"] — the per-element trailing reference integer, one array per cell block.

Quirks & limitations ​

  • A file without a Dimension keyword (FEconv writes none) is read with the dimension its first Vertices row implies: the number of values on that row minus the trailing reference. Before v16.6.0 both engines refused such a file.
  • Only one integer point-data array and one integer cell-data array can be written (Medit's single-ref-column limitation): if more than one candidate exists, the first is used and the rest silently dropped (a warning is emitted for the dropped ones).
  • Coordinate dtype is version-driven, not user-selectable in binary mode: ASCII MeshVersionFormatted 0 or 1 → float32, 2 → float64; binary version 1 → float32, versions 2-4 → float64. The binary writer always writes float64 coordinates, little-endian, and version 3 (32-bit integers); it upgrades to version 4 when an index or reference needs 64 bits.
  • Binary record headers embed absolute byte offsets (pos fields) that the writer must track precisely while emitting records — a strict requirement for libMeshb compatibility, not merely a convenience field.
  • Normals/Tangents/etc. sections are read but discarded. Corners, RequiredVertices (point regions medit:Corners, medit:RequiredVertices), Ridges and RequiredEdges (cell regions medit:Ridges, medit:RequiredEdges over the file's Edges) and RequiredTriangles (cell region medit:RequiredTriangles over its Triangles) are kept as regions and written back as those keywords, in the ASCII variant of both engines. The binary .meshb path carries them as the libMeshb sections GmfCorners, GmfRidges, GmfRequiredVertices, GmfRequiredEdges and GmfRequiredTriangles. A cell region is written relative to the first block of its type, so entries elsewhere are dropped with a warning.
  • Both variants, ASCII .mesh and binary .meshb (including its little/big-endian variants), are read and written by the C++ core and by the Python twin, which write the same bytes. The binary reader skips the sections it has no home for (solutions, normals ...) through their next-section position, with a warning, and refuses a file whose position is outside it.
  • Cells are written one section per cell block, in block order.

Notes ​

  • tests/python/meshes/medit/cube86.mesh (ascii) — 39 points, 72 triangles, 86 tets, boundary tag counts {1:14, 2:14, 3:14, 4:8, 5:14, 6:8}.
  • sphere_mixed.1.meshb (binary) — 3270 points, 864 triangles, 3024 wedges, 9072 tets, tag counts {1:432, 2:216, 3:216}.
  • hch_strct.4.meshb / hch_strct.4.be.meshb (binary, little/big-endian pair, exercising the endian-swap path) — 306 points, 12 triangles, 178 quads, 96 wedges, 144 hexahedra, tag counts {1:15, 2:15, 3:160}.
  • All four originate from UGRID files converted with UGC (simcenter.msstate.edu).

Released under the MIT License.