Ansys MAPDL coded database (.cdb / .inp)
An autonomous reader/writer for the Ansys MAPDL "coded database" format — distinct from the Fluent .msh format also named "ansys" in meshioplusplus. It parses ET/ETBLOCK, NBLOCK, EBLOCK, and CMBLOCK blocks directly, with no dependency on any other format module.
| Format name | ansysInp |
| Extensions | .cdb, .inp |
| Read / Write | ✓ / ✓ |
| Extra dependencies | — |
Reading & writing
import meshioplusplus
mesh = meshioplusplus.ansysInp.read("model.cdb")
meshioplusplus.ansysInp.write("out.cdb", mesh)Both read(filename) and write(filename, mesh) take no keyword arguments.
Note on .inp: this format registers both .cdb and .inp as extensions, colliding with Abaqus's pre-existing .inp registration. Since abaqus is imported before ansysInp in src/meshioplusplus/__init__.py, plain extension-based dispatch (meshioplusplus.read("x.inp")) still resolves to Abaqus by default — pass file_format="ansysInp" explicitly, or call meshioplusplus.ansysInp.read/write directly, to select this format for a .inp file.
File structure
Whitespace/keyword-delimited MAPDL command blocks, each starting with a header line and ending at a sentinel row:
/PREP7
ET,<slot>,<ansys element type> -- one per cell type in use
NBLOCK,6,SOLID,<n>,<n>
(3i9,6e20.13) -- format spec: int width, float width
<id><cs><...> x y z -- one row per node, fixed-width fields
N,R5.3,LOC, -1, -- NBLOCK terminator
EBLOCK,19,SOLID,<ntot>,<ntot>
(19i9)
<elem header (11 ints)><node ids...> -- continuation line if >8 nodes
-1 -- EBLOCK terminator
CMBLOCK,<name>,NODE,<n> -- named point set
(8i10)
<ids, possibly negative range markers>
CMBLOCK,<name>,ELEM,<n> -- named cell set
(8i10)
<ids>
FINISH- Field widths are read from the format-spec line following each block header (
_int_width/_real_width, parsed via regex against patterns like3i9/6e20.13), not hardcoded — but the writer always emitsi9/e20.13widths. ETBLOCK(an alternative to individualET,lines) associates a numeric element-type slot with an underlying Ansys element type id; either form populates the sameetype_libmapping used to classifyEBLOCKrows.EBLOCKrows: fields are(mat, type, real, secnum, esys, birth, death, solkey, nodes_per_elem, ..., elem_id, node_ids...); only fields 1 (etype slot), 8 (node count) and 10 (element id) are used, plus however many trailing node ids follow (spilling onto a continuation line if there are more than 8).CMBLOCK(named component = point/cell set): entityNODE→ point set, entity startingELEM→ cell set. Negative values encode a range marker:-kafter a base valuebexpands torange(b+1, k+1)— anReadErroris raised if a negative value appears before any base value.- Any line matching
_is_data_line's exclusion list (known keywords,KEYWORD,command syntax,!//comments) is treated as non-data and stops a block's row-reading loop early.
Cell types
Ansys element type ids are grouped into 4 families by node-count-independent type id, then combined with the node count actually present to resolve a meshio++ type:
| family | Ansys element type ids |
|---|---|
solid | 5, 45, 70, 87, 90, 92, 95, 162, 185, 186, 187, 226, 227, 285 |
shell | 28, 43, 63, 93, 131, 132, 181, 281 |
plane | 25, 42, 77, 82, 182, 183, 223 |
line | 1, 3, 4, 21, 180, 188, 189, 288, 289 |
| (family, nodes) | meshio++ | (family, nodes) | meshio++ |
|---|---|---|---|
| (solid, 4) | tetra | (shell/plane, 3) | triangle |
| (solid, 10) | tetra10 | (shell/plane, 6) | triangle6 |
| (solid, 8) | hexahedron | (shell/plane, 4) | quad |
| (solid, 20) | hexahedron20 | (shell/plane, 8) | quad8 |
| (solid, 6) | wedge | (line, 2) | line |
| (solid, 15) | wedge15 | (line, 3) | line3 |
| (solid, 5) | pyramid | ||
| (solid, 13) | pyramid13 |
Write uses a fixed reverse mapping (one Ansys type id per meshio++ type, regardless of which id the file was originally read with): tetra→285, tetra10→187, hexahedron→185, hexahedron20→186, wedge→185, wedge15→186, pyramid→185, pyramid13→186, triangle→181, triangle6→281, quad→181, quad8→281, line→188, line3→189. An unmapped meshio++ cell type raises WriteError.
Data mapping
mesh.point_sets[name]— fromCMBLOCK ...,NODE,..., 0-based point indices.mesh.cell_sets[name]— fromCMBLOCK ...,ELEM,..., one array per cell block (in the order blocks were first encountered), 0-based local indices.- No point_data, cell_data, or field_data — only geometry, connectivity, and named sets are represented.
Quirks & limitations
- 2D input meshes are padded to 3D with a zero z-column on write (MAPDL has no native 2D coordinate concept).
- The writer always emits exactly one
NBLOCK/EBLOCKpair (no attempt to preserve an original file's exact block layout, field widths, or element type ids) — a read→write round trip is not byte-identical, though it is semantically equivalent (same points, cells, sets). - Read and write go through the C++ core (
meshioplusplus._core.ansysinp_read/ansysinp_write), with the Python reference as an automatic fallback for buffers. CMBLOCK components (point_sets/cell_sets) travel through a dedicatedAnsysInfoside-channel struct rather than the Mesh conversion layer.
Notes
- No dedicated
tests/meshes/reference fixture;tests/test_ansysInp.pybuilds MAPDL snippets and meshes inline (including negative-rangeCMBLOCKexpansion, multi-lineEBLOCKcontinuation, and round-trips throughio.StringIO/temp files) rather than shipping a binary fixture. The internal-helper tests import the Python module directly, so the pure- Python reference stays exercised alongside the C++ path. - Ported from Simvia's meshlane fork (see
CHANGELOG.md) — this format did not exist upstream before that.