Z88 (z88i1.txt, results z88o2.txt / z88o3.txt / z88o4.txt)
Z88 is an open-source finite element program for teaching and small companies (Z88OS, and the freeware Z88Aurora). Its files have fixed names: the structure file z88i1.txt, then boundary conditions (z88i2.txt), surface loads (z88i5.txt), materials (z88mat.txt and the files it names), element parameters (z88elp.txt), integration orders (z88int.txt) and, after a run, displacements (z88o2.txt), stresses (z88o3.txt) and nodal forces (z88o4.txt).
| Format name | z88 |
| File names | z88i1.txt, z88structure.txt (Aurora), and z88o2.txt/z88o3.txt (which read the structure file next to them); any case |
| Read / Write | ✓ / ✓ (structure file, the input files above and Z88Aurora's sets) |
| Extra dependencies | — |
Reading & writing
import meshioplusplus
mesh = meshioplusplus.read("run/z88i1.txt") # mesh + results next to it
mesh = meshioplusplus.z88.read("run/z88i1.txt", results=False)
meshioplusplus.write("out/z88i1.txt", mesh) # or z88.write(..., stubs=True)The file name decides the format: z88i1.txt is Z88's, although .txt otherwise belongs to xyz. The native resolver and the Python dispatch both check the name first. A structure file under any other name needs file_format="z88".
The structure file
- The header's first three integers are the dimension, the node count and the element count. Z88OS v15 writes
ndim nnodes nelem ndof kflag; Z88 up to V13 and Z88Aurora V1 add the material count and more flags, and put one material line per range after the elements, which the reader skips. - One line per node,
id ndof x y [z], and two per element:id type, then its nodes (their count is fixed by the type). Text after the numbers on a line is ignored. KFLAG = 1means cylindrical input (r, φ in degrees, z), converted to Cartesian with a warning.
| Z88 type | Element | meshio++ type |
|---|---|---|
| 1 | 8-node hexahedron | hexahedron |
| 10 | 20-node hexahedron | hexahedron20 |
| 16 / 17 | 10- / 4-node tetrahedron | tetra10 / tetra |
| 7, 8, 20, 23 | 8-node plane, torus, plate, shell | quad8 |
| 3, 14, 15, 18, 24 | 6-node plane, torus, plate, shell | triangle6 |
| 6 | 3-node torus | triangle |
| 2, 4, 5, 9, 13, 25 | beams, trusses, shaft | line |
| 19 | 16-node Lagrange plate | VTK_LAGRANGE_QUADRILATERAL (order 3, 16 nodes; v16.12.0) |
| 11, 12 / 21 / 22 | 12-node plane and torus / 16- and 12-node volume shells | corners only: quad / hexahedron / wedge, with a warning and a provenance note |
The Z88 type is kept as the z88:type cell data, so a round trip keeps it.
Node order
- Hexahedra (types 1 and 10) list the face the Z88 manual draws on top first, so read as-is their volume is negative: every hexahedron of the Z88OS examples is. They use the
"z88"tables of the node-ordering registry. Z88R ran the hex20 fixture deck and the deck meshio++ writes back from it, and gave identical displacements. - tet10 lists its last three mid-edge nodes on edges 2-4, 3-4, 1-4 (checked on the mid-edge positions of the Z88OS example
b11). - The 16-node plate (type 19) numbers its 4 × 4 lattice with r slow and s fast: node 4i + j + 1 sits at the i-th r and the j-th s, where its shape functions in Z88R (
hpla88.c) are 1, so corners 1, 13, 16, 4 run counter-clockwise. It is read whole as VTK's order-3 Lagrange quad (corners, the two nodes of each edge along r, s, r, s, then the interior) and written back from one (a 16-nodeVTK_LAGRANGE_QUADRILATERALbecomes type 19 in a 2-D file). - The volume shells 21 and 22 list their upper layer, then the lower one; the reader keeps the corners, the wedge's lower triangle first so its volume is positive.
- Everything else is in meshio++'s order (checked on the Z88OS plane, torus and plate examples).
The rest of the deck
When the directory holds them, the reader attaches the input files as data (whatever results says), and the writer writes them back from that data:
| File | Read as |
|---|---|
z88i2.txt | point_data["z88:bc:u"] (prescribed displacements, flag 2) and ["z88:bc:f"] (nodal forces, flag 1, summed when a degree of freedom has several), one column per degree of freedom (2, 3 or 6, the widest node's), NaN where there is no entry. An empty file adds nothing |
z88mat.txt and its material files | cell_data["z88:material"] (the file's number, 51 for 51.txt, else its row), ["z88:E"] and ["z88:nu"] (the first line of the material file) |
z88elp.txt | cell_data["z88:elp"], 12 columns: QPARA, RIYY, EYY, RIZZ, EZZ, RIT, WT, IFBETI, XCP, YCP, ZCP, RKAP. Fields a row leaves out are NaN (Z88R leaves them untouched, which is not the same as 0) |
z88int.txt | cell_data["z88:int"]: INTORD, INTOS; −1 for elements no row names |
z88i5.txt | field_data["z88:surface_load"], one row per load: pressure, tangential shear in r, in s (NaN where the element type takes none); field_data["z88:surface_load:cells"], one row per load: the cell, then up to 8 points naming the loaded edge or face (−1 past them). What a line holds follows the element type, as Z88R reads it: plane and torus quad8/tri6 (7, 8, 14, 15) a pressure, a shear and 3 edge nodes; 12-node quads (11, 12) a pressure, a shear and 4; the hexahedra (1 / 10) and the hexahedral volume shell (21) a pressure, two shears and 4 / 8 / 8 face nodes; the tetrahedra (17 / 16) and the wedge shell (22) a pressure and 3 / 6 / 6; plates (18, 19, 20) and flat shells (23, 24) a pressure alone. Loads on other elements are skipped with a warning |
z88sets.txt (Z88Aurora) | element sets as cell regions and node sets as point regions, named as in Aurora (tag = set id). Surface sets name Aurora's own surface mesh, not the structure file's elements, and are skipped with a warning |
Element ranges refer to element ids, node entries to node ids; elements no row names get NaN (or 0, −1).
Results
With results (the default), the reader also attaches:
z88o2.txt:point_data["U"]with 2, 3 or 6 columns (the widest node's degrees of freedom; NaN where a node has fewer). The language-dependent header is skipped: data rows are recognised by their shape.z88o4.txt: the nodal sums (the last table) aspoint_data["F"], with the same columns as the constraints.z88o3.txt: each element's block has a line of column labels, then one row per corner or Gauss point; each label is averaged over the rows. Solid (1, 10, 16, 17) and plane-stress (3, 7, 11, 14) elements give the stress tensorcell_data["SIG"](XX YY ZZ XY YZ ZX in 3-D, XX YY XY in 2-D). Every other label becomes a scalar cell array of its name, NaN on elements that do not print it:SIGXX TAUXX SIGYY1 SIGZZ1 SIGYY2 SIGZZ2for 3-D beams (2, 25),SIGXX SIGZZ1 SIGZZ2for beams in the plane (13),SIGXX TAUXX SIGXY1 SIGXZ1 SIGXY2 SIGXZ2for the shaft (5), the axialSIGXXof trusses (4, 9),MXX MYY MXY QYZ QZX SIGXX SIGYY TAUXY TAUXZ TAUYZfor plates (18–20),SIGXX SIGYY TAUXYfor shells (23, 24),SIGRR SIGZZ TAURZ SIGTEfor tori (6, 8, 12, 15), andSIGRR SIGTT TAURTwhen plane elements are computed in polar coordinates. The equivalent stress iscell_data["SIGV"]for every family. Coordinate columns (XX, YY, ZZ, RR, PHI) are not kept.
Z88 is linear static, so there are no steps.
Writing
- The Z88OS v15 layout: the five-integer header (the provenance tag follows it on the same line, where Z88 writes its own comment), nodes with their degrees of freedom (the most any of their elements needs), then the elements.
- The element type comes from
z88:typewhen it matches the cell, else from the cell type:hexahedron1,hexahedron2010,tetra17,tetra1016,triangle614 (24 in 3-D),quad87 (23 in 3-D),line9 (4 in 3-D), a 16-nodeVTK_LAGRANGE_QUADRILATERAL19 (in a 2-D file only). A 2-D file is written when every z is 0 and no cell is 3-D. - A 3-D file is also written when a kept
z88:typeexists only in 3-D files (solids, 3-D beams, trusses and the shaft, shells), so flat frames and shells stay 3-D. - The
z88:arrays above are written back next to the structure file:z88i2.txt,z88mat.txtwith one<n>.txtper distinct E and ν (numbered byz88:materialwhen that is free, else 1, 2, …),z88elp.txt(the leading fields up to the first NaN) andz88int.txt, each grouping consecutive elements with equal values into one range. z88i5.txtfrom the twoz88:surface_loadarrays, the cells and points renumbered as written. A load whose cell is not written, or whose element type takes a different line (say an 8-node face load on a volume shell written back as a hexahedron), is dropped with a warning.z88sets.txt(Z88Aurora's sets) from the regions:cellregions as element sets (purposeMATERIAL) andpointregions as node sets (purposeCONSTRAINT), the purposes Aurora gives them, in region order. A set's id is its region's tag, or the next free id when the tag is not positive or another set took it. Z88OS ignores the file; Aurora reads it with the structure file.stubs=Truealso writes an emptyz88i5.txtwhen there are no surface loads, and an emptyz88i2.txtwhen the mesh has no constraints, so the deck is complete.- Dropped, with a warning and a provenance note: cells with no Z88 type (
hexahedron27, pyramids, polygons…),sideregions and other data arrays, results included. A mesh with nothing to write is aWriteError. - These are the format's limits, by design (v16.17.0): a Z88 deck has no slot for an arbitrary array;
z88o2.txt/z88o3.txt/z88o4.txtare what Z88R writes from the deck, so a converted mesh has none to write back; and Z88Aurora's sets hold elements and nodes only, so asideregion has no set to go to (a face load goes throughz88:surface_loadintoz88i5.txtinstead).
Validation
The decks under tests/python/meshes/z88/ are written by tools/gen_z88_fixtures.py; their z88o2.txt/z88o3.txt/z88o4.txt are Z88OS V15's own output (a hex20 cantilever, a frame of 3-D beams and a truss, a plate, flat tri6 shells, an axisymmetric torus and, from v16.12.0, 16-node plates with a pressure, a slab of volume shells 21 and 22 with face loads, and flat 8-node shells). The 16-node plate's corner deflection is within 6 % of the 8-node plate deck's for the same plate and load, and Z88R solves the deck meshio++ writes back from it, loads included, to the same displacements. The cantilever's tip deflection, 1.849 mm, is within 3 % of the Euler-Bernoulli value for this coarse mesh; on free degrees of freedom the nodal forces equal the applied loads.
Outside the repository (v16.11.0) Z88R solved the 14 example decks of Z88OS, covering trusses, shafts, beams in the plane, tori, plane stress, plates and shells as well as solids. Both engines read the same arrays from every deck and write the same bytes, and Z88R run on each deck meshio++ writes back gave exactly the same displacements and stresses (two tetrahedral decks exceed the prebuilt Z88R's memory). Z88R stops with its "Jacobi-determinant zero or negative" error when it computes the Gauss-point stresses of 8-node shells (type 23, integration order INTOS > 0), whatever the geometry: flat, raised or tilted. Its displacements and corner stresses (INTOS = 0) are fine, and the shell23/ fixture uses those. A public Z88Aurora V2 project (structure file, sets and Z88R V15.0B displacements; not redistributable) was read with its element and node sets.