Format conformance
What every writable format keeps when meshio++ writes a file and reads it back. One canonical mesh — one cell of each linear type, float64/int32/vector point data, float64/int32 cell data, field data and one point, cell and side region — goes through write and read for each format, and the observed result must match the declaration in tests/python/conformance_spec.py exactly: tests/python/test_conformance.py fails when a format starts losing something or starts keeping something, so this page cannot drift from the code. It is generated by tools/gen_conformance_table.py; do not edit it by hand.
The per-format pages say why something is lost; this page says what. Region membership is checked in depth by the region round-trip matrix, and node-ordering by node ordering.
Legend
- Cell columns: ✓ the cell comes back node for node; ↻ the same nodes in another order; → types written as other cells (a quad as two triangles, a volume as its skin); ✗ silently dropped when written next to the other types; blank: the writer refuses the type on its own.
- Points:
exact;approx(within 1e-6, single precision);2d(z dropped);subset(the points of dropped cells are gone, the rest exact);none(a format with no geometry);changed. - Point data / cell data: the arrays that come back, with the dtype read (
~: values only approximately equal;?: shape or values changed).p_f64/c_f64are float64,p_i32/c_i32int32,p_veca float64 3-vector. - F: the field-data array
fdsurvives. Regions: the kinds (point, cell, side) whose region comes back under its own name.
Matrix
| Format | vtx | line | tri | quad | tet | hex | wdg | pyr | Points | Point data | Cell data | F | Regions |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
abaqus | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point, side | ||
abaqus_fil | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point, side | |
ansys | ✗ | ✗ | ↻ | ↻ | ✓ | ✓ | exact | — | — | — | cell | ||
ansys_rst | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point |
ansysInp | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point |
avsucd | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64 | — | — |
cad_json | ✓ | ✓ | exact | — | — | — | — | ||||||
cae | ✗ | ✗ | → tri | → tri | → tri | → tri | subset | — | — | — | — | ||
cgns | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | — | ✓ | cell, point |
code_aster | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point |
dex | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | exact | p_f64 float64 | — | — | — |
dolfin-xml | ✗ | ✓ | exact | p_f64 float64, p_i32 int64 | c_f64 float64, c_i32 int64 | — | — | ||||||
dxf | ✓ | exact | — | — | — | — | |||||||
elmer | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell | |
ensight | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | approx | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | — | — |
exodus | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | cell, point, side |
febio | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64?, c_i32 float64? | — | cell, point, side | |
femap | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64 | c_f64 float64, c_i32 float64 | — | cell, point |
flac3d | ✓ | ✓ | ✓ | ✓ | ↻ | ✓ | exact | — | — | — | — | ||
flux | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | — |
frd | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | — | — | — | ||
freefem | ✓ | ✓ | exact | — | — | — | — | ||||||
gid | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | — | — |
gltf | ✓ | ✓ | ✓ | → tri | → tri | → tri | → tri | → tri | approx | p_f64 float64, p_i32 float64, p_vec float64 | — | — | cell |
gmsh | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | ✓ | cell |
gmsh22 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | ✓ | cell |
h5m | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | — | — | — | |||||
hmf | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | — |
ip | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | exact | p_f64 float64, p_i32 float64 | — | — | — |
libmesh | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point, side |
lsdyna | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point, side |
lsdyna_binout | ✓ | → vtx | → vtx | → vtx | → vtx | → vtx | → vtx | → vtx | approx | p_f64 float64, p_i32 float64 | — | — | — |
lsdyna_d3plot | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | approx | — | — | — | cell |
marc | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point | |
marc_t19 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | — | cell, point | |
mdpa | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | — | — | — |
med | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | cell, point |
medit | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | — | |
medit_sol | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | none | — | — | — | — |
mfem | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell | |
mff | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | none | — | — | — | — |
mfm | ? | ? | ? | ? | ? | ? | fails: WriteError | ||||||
mphbin | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell |
mphtxt | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell |
nastran | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell |
nastran_h5 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | — | — | — |
nastran_op2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | approx | — | — | — | — |
netgen | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | ✓ | — |
neuroglancer | ✓ | exact | — | — | — | — | |||||||
obj | ✓ | ✓ | exact | — | — | — | — | ||||||
off | ✓ | ✓ | exact | — | — | — | — | ||||||
openfoam | ↻ | ↻ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | — | cell, point, side | ||||
patran | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point | |
pcd | ✓ | → vtx | → vtx | → vtx | → vtx | → vtx | → vtx | → vtx | approx | p_f64 float64, p_i32 int32, p_vec float64 | — | — | — |
permas | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | — |
ply | ✗ | ✗ | ✗ | ✗ | → tri | → quad | → quad+tri | → quad+tri | subset | — | — | — | — |
pmsh | ✗ | ✗ | ✗ | ✗ | ✓ | → tet | → tet | → tet | approx | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | ✓ | — |
pvd | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | ✓ | cell, point, side |
pvtp | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | ✓ | cell, point | ||||
pvtu | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | ✓ | cell, point, side |
radioss | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | cell, point, side | |
radioss_anim | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | approx | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | — | cell |
radioss_th | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | none | — | — | — | — |
step | → tri | → tri | → tri | → tri | exact | — | — | — | — | ||||
stl | ✗ | → tri | → tri | → tri | → tri | subset | — | — | — | — | |||
su2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | — | ||
svg | ✓ | ✓ | ✓ | exact | — | — | — | — | |||||
szplt | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | → hex | → hex | subset | — | c_f64 float64, c_i32 float64 | — | cell |
tecplot | ✓ | ✓ | ✓ | ✓ | ✓ | → hex | → hex | exact | p_f64 float64, p_i32 float64 | c_f64 float64, c_i32 float64 | — | cell | |
tetgen | ✓ | exact | — | — | — | — | |||||||
tikz | ✓ | ✓ | ✓ | exact | — | — | — | — | |||||
triangle | ✓ | exact | — | — | — | — | |||||||
ugrid | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | — | — | — | — | ||
unv | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | — | cell, point | |
usd | ✗ | ✗ | → tri | → quad | → quad+tri | → quad+tri | subset | — | — | — | — | ||
vti | fails: no cell type round-trips | ||||||||||||
vtk | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | — |
vtk42 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | — |
vtk51 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | — |
vtkhdf | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | ✓ | — |
vtm | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | cell |
vtp | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | ✓ | cell, point | ||||
vtr | fails: no cell type round-trips | ||||||||||||
vts | fails: no cell type round-trips | ||||||||||||
vtu | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | ✓ | cell, point, side |
vtx | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | — |
wkt | ✓ | exact | — | — | — | — | |||||||
xdmf | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exact | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | — | cell, point, side |
xplt | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | approx | p_f64 float64, p_i32 float64, p_vec float64 | c_f64 float64, c_i32 float64 | ✓ | cell, point, side |
xyz | ✓ | → vtx | → vtx | → vtx | → vtx | → vtx | → vtx | → vtx | exact | p_f64 float64, p_i32 float64 | — | — | — |
z88 | ✓ | ✓ | ✓ | exact | — | — | — | cell, point | |||||
zarr | ✗ | ✗ | ✗ | ✗ | ✓ | → tet | → tet | → tet | approx | p_f64 float64, p_i32 int32, p_vec float64 | c_f64 float64, c_i32 int32 | ✓ | — |
Notes
abaqus_fil: A results file holds the model and the results Abaqus names: only point data named like a nodal result (U,RF...) and cell data named like an element result (S,E...) are written, so the canonical arrays andfdhave no place; avertexhas no Abaqus element. Side regions are contact surfaces.ansys: A Fluent mesh stores volume cells and the faces that bound them; lower-dimensional cells that are not boundary faces of a volume cell are dropped with a warning.ansys_rst: A results file holds the solution MAPDL names: point data calledU,ROT,TEMP... (andRFreactions) and cell dataS,EPEL,EPPL,EPCR,EPTHcome back; arbitrary arrays such as the probe's are not kept. Side regions are dropped with a warning.cad_json: Kratos IGA geometry: without a B-rep side channel, quads are written as bilinear NURBS faces and lines as edges.cae: The physics-ML.npzstores the surface of the volume cells.cgns: Cell data cannot be written for the probe: it mixes cell dimensions, which a zone-wideCellCentersolution cannot span. Side regions are not written, and a region's cells must lie in fixed-size sections.dex: DEX stores one nodal field over a node set: cells are not kept.dxf: A drawing exchange file: a line mesh is written as oneLINEper segment, afit_curvessketch asLINE,ARCandCIRCLEentities, and only the drawing comes back (dxf:entity,dxf:type). Vertex cells are skipped and surface or volume cells are refused by name.frd: Nodal, with no sets: cell data, regions and other field data are dropped with a warning, and values print at six digits (E12.5). No vertex or pyramid element exists. Onlyfrd:groupandfrd:materialcome back as cell data.gltf: A surface export: volume and 2-D cells come back as their triangulated skin, positions arefloat32, andweld=Truemerges the vertices split per smooth fan.ip: An integration-point cloud: points and nodal values, no cells.libmesh: A.xda/.xdrholds geometry, subdomains, p-levels, boundaries and the refinement tree, and no data arrays;libmesh:levelis derived from the tree.lsdyna_binout: A binout holdsnodout's nodes, not elements: the points come back as avertexcloud, single precision, and onlynodout's own vectors (displacement...) are(n, 3); per-point scalars come back as float64 (an integer one is stored asint32, and the reader widens every per-point array to float64), and the canonicalfdis not abinout:name.lsdyna_d3plot: Single-precision words, so coordinates and data come back rounded to float32. Only what the state layout names is kept: the nodal variables (displacement,velocity,temperature...), the element variables (stress,strain,history_variables, the shell and beam resultants ...),lsdyna:aliveand theglobal_*field data; the probe's arrays are not. Blocks come back by family (solids, beams, shells, SPH particles; a vertex is an SPH particle), and a cell belongs to one part, so only the first cell region holding it survives.marc: A deck holds no data arrays; Marc's face and edge numbering is not mapped to facets, so side regions are dropped (roadmap §1.2.11); avertexhas no type; Herrmann, bubble and generalized plane strain types come back as the default type of their shape.marc_t19: Reals aree13.6, six digits, and integers come back as float64; the model is the input deck's, so avertexhas no type, side regions are dropped, and Herrmann, bubble and generalized plane strain types come back as the default type of their shape. A post file is checked against meshio++'s own reader only, until a Mentat run (roadmap §1.2.11).medit_sol: Fields without geometry: the float data comes back renamedmedit:sol:<i>, element fields only throughmedit.read(path, sol=...).mff: A field without geometry: one array of values, no points or cells.mfm: MFM holds one element type per file, so the mixed canonical mesh is refused; each type alone round-trips.mphtxt: A Selection selects elements, so point and side regions (which address points and facets, not elements) have no form in the file; several Mesh objects merge into one mesh on read and are written as one.nastran_h5: Results are the schema's own tables: point data is nodal tables (float64), cell data only<G>:<M>centre values, so the canonical cell arrays, field data and regions (derived from property ids on read) have no place.nastran_op2: Single precision; results are the OP2 tables' own point and cell data (DISPLACEMENT,STRESS:<M>...), so the canonical arrays have no place; the property and material values are field data (nastran:<CARD>_<id>:<MEMBER>), and the regions come from the property ids; cells come back ordered by element card.netgen: Field data is interpreted as Netgen name tables ([id, dimension]), not arbitrary numeric arrays; periodic tables use reserved netgen:* keys.openfoam: Fields are written to time directory 0 as volume and point fields (float64); OpenFOAM has no field_data.pcd: A point cloud: every node is kept as a vertex, cells are not.ply: PLY stores faces: volume cells are written as their skin.pmsh: The physics-ML mesh stores tetrahedra: other volume cells are simplexified, and non-volume blocks dropped.radioss: A starter deck holds no data arrays; avertexhas no element card.radioss_anim: Everything is stored as 32-bit floats, so coordinates and data are approximate and integers come back as float64; the animation holds one state, so the data are the state's and field data other than the time are not kept.radioss_th: A time-history file holdsradioss_th:*field data only: points, cells, regions and other data are not kept (a warning names the field data dropped); the canonicalfdis not aradioss_th:name.step: A B-rep solid for CAD tools (coplanar facets merged into one face), read back through OpenCASCADE as its triangulation: volume cells come back as their skin, and data is not kept. Checked only in a build with OpenCASCADE (the meshioplusplus-occt wheel carries it).stl: STL stores triangles: volume cells are written as their skin, and other blocks are dropped when volume cells are present.su2: SU2 holds volume cells and boundary markers: a volume region has no slot (separate meshes areNZONEzones,su2:zone), and data arrays are not stored.svg: A 2-D drawing, read back as planar (z = 0) from the scale and offset meshio++ records in a comment. Observed withfloat_fmt=".17g": the default.3fkeeps three decimals of a drawing 100 units wide, so corners come back to about 1.5e-5 of its width. A 3-D mesh is drawn projected, and what comes back is that picture. Data arrays are not drawn; a colour comes back as an RGBsvg:fill.szplt: SZL has no wedge or pyramid zone type: both are written as degenerate bricks and come back as hexahedra, and a zone has no vertex element. TecIO shares a variable between zones only with their connectivity, so with several blocks each zone holds the points its cells use (a point several blocks use is repeated: the mixed mesh reads back with more points, and its point data with them); one block alone round-trips exactly.tecplot: Tecplot has no wedge or pyramid zone type: both are written as degenerate bricks and come back as hexahedra.tikz: A 2-D drawing, read back as planar (z = 0) with its coordinates verbatim, to the digitsfloat_fmtkept. A 3-D mesh is drawn projected, and what comes back is that picture. Data arrays are not drawn; a colour comes back as an RGBtikz:fill.triangle: Triangle reads and writes 2-D triangulations only, so this row is observed on the planar part of the canonical mesh.unv: Entities a dataset does not list are NaN, and NaN rows are not written back.usd: A UsdGeom mesh stores faces: volume cells are written as their skin.vti: ImageData holds one regular hexahedral lattice; the canonical mesh is not one (VTI).vtr: RectilinearGrid holds one axis-aligned lattice; the canonical mesh is not one.vts: StructuredGrid holds one curvilinear lattice; the canonical mesh is not one.vtx: A mesh of several cell types is one block per type, each with the points it uses and the ghost arrays that let the reader weld the shared points back, so the mixed canonical mesh round-trips exactly (DOLFINx and ParaView read a single type only); the file holds the mesh and its arrays, with no regions or field data other than the time.xplt: Everything is stored as 32-bit floats and comes back as float64 (the probe's coordinates are exact in float32, general ones are not); a plot file has no vertex element. A side region is a facet set.xyz: A point cloud: every node is kept as a vertex, cells are not.z88: A deck has no slot for an arbitrary array, andz88o2/z88o3/z88o4are what Z88R writes from the deck, so none is written; Aurora's sets hold elements and nodes only, sosideregions are dropped.zarr: Aspmsh: tetrahedra only, other volume cells simplexified.
Formats missing a direction
Every registered format is meant to read and write, in both engines (roadmap decisions). A format that does only one is a tracked gap, listed here with the roadmap item that closes it; ansys_rst_cyclic, iges and step are the exemptions. test_conformance.py fails when a format reads without writing, or writes without reading, and is not listed here, or is listed and has gained the missing direction, in either the Python or the native registry.
| Format | Missing | Why, and the item that closes it |
|---|---|---|
ansys_rst_cyclic | writer | Exempt, not a gap: not a file of its own but the full rotor that a static cyclic-symmetry .rst expands to, read from ansys_rst's file. Its write side is ansys_rst's cyclic option (roadmap non-goals: every format reads and writes). |
iges | writer | Exempt, not a gap: a CAD exchange format read through OpenCASCADE (roadmap non-goals: every format reads and writes); STEP is the CAD format meshio++ writes. |