cubit-mesh-export
Export high-order curved meshes from Coreform Cubit directly to Netgen/NGSolve
.vol. Use check-vol to verify the exported mesh and its named regions and
boundaries before analysis. The standalone tools run without Radia.
Nastran BDF export supports first- and second-order elements. Gmsh MSH 4.2 output
supports visualization and post-processing. The ELF/MAGIC writer exports
.meg directly from Cubit. The Export menu writes ASCII VTK XML .vtu and
JMAG .jcf; the export vtk command writes Legacy .vtk.
Neutral CAD capture
export model_capture "model.json" units mm records CAD topology and explicit
block/sideset identity for separate construction adapters, without meshing.
Read the model-capture contract for supported source
records, mandatory units, approximation limits and external physical mappings.
Explicit named periodic export
export netgen can write one named kt periodic identification directly into
the .vol. All nine fields are required together: periodic_name (kt),
periodic_master and periodic_slave (exact boundary labels), periodic_unit
(m), periodic_patches (masterBC:slaveBC,...), periodic_tx, periodic_ty,
periodic_tz, and periodic_match (positive finite geometric search distance).
Zero translation components must still be supplied. Coordinates must already
be in the declared unit; this option never rescales a model.
Patch numbers are BC properties, not FaceDescriptor indices or CAD surface IDs.
The sidecar records the mapping. Shared patch-seam points are deduplicated and
must satisfy every incident patch correspondence. All points must match
uniquely and bijectively; no centroid inference, default distance, nearest-only
choice or partial success is permitted. Existing identification groups reject
the request. A named periodic export requires a fresh output path.
A successful named export requires both the .vol and its complete .vol.json
mapping record; a sidecar open, serialization, write, flush or close failure fails
the export. The native VOL is staged and verified, then the record is completed,
then the final VOL is published without replacing an existing target. A failed
record cannot leave a published final VOL. A later publication failure may leave
an orphan record; a record alone is never proof of a complete export.
A failed export is unqualified even if a file exists. It may leave the requested
<name>.vol, <name>.vol.partial.vol and/or <name>.vol.json. The original error
and exact paths are reported. Inspect that error first; before a new attempt,
the owner must verify and remove only that owner's failed outputs, or choose a
new fresh output path. The exporter does not delete paths whose ownership may
have changed. Existing files are never treated as a successful retry or repaired
silently.
Before inserting identifications, the exporter requires complete triangular face correspondence in both directions and synchronizes slave curved displacement coefficients from their master entities. Polynomial q1, q2 and q3 tetrahedra with linear connectivity are supported. Reversed canonical edge orientation negates the q3 odd mode; even edge modes and the symmetric q3 triangular face bubble copy unchanged. Translation acts on the existing corners, not on displacement coefficients. Vertices, connectivity and BCs are unchanged. Shared patch edges have one consistent owner. An edge or face that is both source and destination of coefficient transfers is rejected, including corners where two periodic directions would form a chained or cyclic mapping. Such multi-direction seam ownership is not supported; rejection occurs before writes. Unsupported representations or unequal paired coefficient orders reject before mutation; no repair flag or independent refit is applied after synchronization. The sidecar records global zero-based edge/face indices, zero-based modes, signs and coefficient transfers. Exact paired coefficient equality is checked before publication, without a new geometric tolerance. Mesh quality and field acceptance remain separate gates.
The exporter persists point triples with group 1, type PERIODIC, name kt,
and checks exact geometry serialization before/after metadata insertion into
the intentionally synchronized geometry.
Consumers verify the saved group without adding or repairing identifications.
Without an explicit periodic request, ordinary mesh export does not infer a
periodic contract. Curved geometry and field accuracy are separate checks.
Gmsh MSH 4.2 export is post-processing support for visualization only; solver meshes and label/topology authority remain checked .vol files and their contracts. No .msh-to-.vol or solver-mesh import route is provided.
Mesh-only Gmsh quality APIs accept direct ASCII MSH 4.2 files only, not GEO programs or indirect Merge/Include inputs. Before any native initialization, NodeData/ElementData/ElementNodeData field tags above 2147483647 are rejected explicitly without remapping. Mesh-only size_t tags and pure-Python inventory reading have no such upper bound; field tag 2^28 remains supported. Independent validation can also compare explicit BDF/VTK reference meshes; MSH content is preflighted even under those suffixes, and GEO is rejected. The independent Gmsh Jacobian/volume calculations are unchanged.
Order-3 pyramid export to Gmsh is refused with an explicit element/order error: the native Gmsh 5 consumer cannot construct that type. No lower-order or fake element is substituted; pyramid orders 1 and 2 are unchanged.
cubit-plugin-install automatically registers the official Coreform
WorkflowToolbar for each selected profile. No manual toolbar package import is
required. Existing user toolbars and unrelated preferences are preserved;
the toolbar becomes available at the next Cubit start. MCP remains batch-only.
Solver-neutral mesh export from Coreform Cubit to NGSolve/Netgen.
cubit-mesh-export is an independent Cubit tooling distribution. It ships
its own MCP server, mesh export, the Kelvin open-boundary
transformation, symmetry helpers, and the Dirichlet label conventions
consumed by Radia's Simulink applications, Python/MCP workflows, and
result-bearing documentation notebooks.
Features
The standalone GUI, installer, and cubit-toolbar-smoke-test release check are
owned by this distribution and require no Radia installation. The former
radia.install_panels and Radia GUI paths are removed, with no compatibility
shims. Existing deployments must regenerate their startup registration using
cubit-plugin-install from the selected Python environment. See the MCP cubit_toolbar_guide for the operating contract.
The GUI and MCP are distributed independently. The repository includes
tools/release_cubit_dual.py for verifying a release on a licensed Cubit installation.
The supported binary runtime is 64-bit Windows, CPython 3.12, Coreform Cubit
2026.8, and Netgen/NGSolve 6.2.2608. These solver versions are exact pins in
package metadata because cubit_mesh_curver.pyd links against the Netgen C++
ABI. The separately loaded cubit_mesh_export.ccm plugin embeds Compact
Netgen and does not link against the Python solver wheels.
For LLM operation, the canonical manual is the included cubit_mesh_export.mcp server:
start with cubit_status and cubit_docs; use APREPRO through its headless
execution tools and cubit_check_vol before handing a mesh to a solver.
Combined Radia installations must also pass Radia's declared exporter
compatibility check; standalone operation does not import Radia.
- Cubit plugin (
.ccm+.pyd, Coreform Cubit 2026.8+):export {netgen|gmsh|vtk|femeem|meg|nastran_bdf}APREPRO commands- Cubit-owned Export menu plus the Cubit Mesh Export WorkflowToolbar
- Arbitrary-order curving (order 1-5) via ACIS geometry projection
- Kelvin open-boundary transformation built into
export netgen(auto-add an exterior sphere with copy-mesh + periodic identification) - Per-axis symmetry-plane BC labels (
bn/ht) for 1/2 and 1/4 reduced domains - Dirichlet / Neumann label conventions at three levels (BND / BBND / BBBND -- see table below)
- Companion JSON beside every
.volwith CAD reference values for Volume / Area / Length consistency checking - Free-mesh sideset preservation: direct tri/quad faces from Sculpt and imported Exodus sidesets are exported even when they have no parent CAD surface, with duplicate geometry-owned faces removed
- Standalone checker that does NOT require Cubit (
check-volCLI)
Install
cubit-mesh-export is standalone: it needs Coreform Cubit 2026.8, but it does
not need radia or radia-mcp. MCP and its private runtime support are included by default in this wheel.
pip install cubit-mesh-export
cubit-plugin-install
mcp-server-cubit
Optional features have independent installation extras:
pip install "cubit-mesh-export[sculpt]" adds Exodus/volume-fraction support;
pip install "cubit-mesh-export[mesh-quality]" adds the Gmsh quality referee.
These install Python dependencies, not Coreform Cubit or a Sculpt license.
The included MCP manual owns the operating workflow.
Cubit MCP uses CUBIT_MCP_* settings, not RADIA_MCP_*. Historical Radia
logs and caches are neither automatically migrated nor deleted. Runtime support
is intentionally maintained independently; see its ownership and license.
For an MCP client, use the installed mcp-server-cubit command, or the selected
Python interpreter with -m cubit_mesh_export.mcp.server. See the
Cubit MCP manual for capabilities and
headless operation. Old radia_mcp.cubit module commands must be updated;
no compatibility forwarding package is shipped. Radia topology optimization
may depend on Cubit, but Cubit users do not install Radia to use MCP.
cubit-plugin-install deploys the plugin binaries, the Netgen DLLs, and the
Cubit-side Python helpers (cubit_helpers/add_kelvin.py,
cubit_helpers/auto_kelvin_entry.py) into your Coreform Cubit 2026.8 profile.
Use cubit-plugin-install --all-users for a shared lab machine.
The generated Cubit startup script finds the installed package at every Cubit
start through the recorded Python, so a versioned checkout it was installed
from can be removed after the next release is installed.
For a standalone round-trip check, supply your own Cubit journal:
cubit-smoke-test --jou path/to/sample.jou
The journal must produce the expected material and boundary labels; adjust
--expect and --expect-materials for its label contract. The check exports a
.vol and runs the solver-ready validation gate, including NGSolve reload.
The no-argument cubit-smoke-test uses the package-owned
solver_ready_sample.jou; no Radia installation or source tree is required.
The Export menu runs through Claro in Cubit's embedded Python and uses Cubit's bundled PySide6.
The menu lists, in order: Netgen (.vol), Gmsh (.msh), Nastran (.bdf),
VTK (.vtu), JMAG (.jcf), Femtet (COM) and ELF/MAGIC (.meg). VTK (.vtu) writes
block cells and sideset faces with full-precision coordinates; every volume
element must belong to a block. Femtet (COM) needs a separately installed
handler registered in the entry-point group cubit_mesh_export.model_transfer;
without one the menu reports that it is unavailable and does nothing.
JMAG (.jcf) asks for an analysis settings JSON file, then for the output path,
and writes a static analysis input from the active mesh. The settings name Cubit
blocks and sidesets: block_materials maps every block to an entry of
material_library (inline, or a JSON file next to the settings), coils give
current, turns and a flow-in sideset or direction, external_field is optional,
and boundaries maps sideset names to a boundary type (symmetry only). The
former symmetry_sidesets key is rejected. See the
JMAG JCF settings JSON guide (Japanese) for examples.
The full schema is in the cubit_mesh_export.jmag module documentation.
Only static analysis is written. To copy the wheel's starter settings into
your working directory without importing Cubit or the package, run this in
the Python environment where the wheel is installed:
from importlib.metadata import distribution
from pathlib import Path
template = distribution("cubit-mesh-export").locate_file(
"cubit_mesh_export/examples/jmag/settings.json"
)
with Path("settings.json").open("xb") as output:
output.write(template.read_bytes())
Set the block names, sideset names, and analysis parameters for your model before selecting the file in the Cubit Export menu.
For batch export on Windows with Cubit 2026.8, run the script below with
64-bit CPython 3.12 after installing the wheel and its dependencies in that
environment (python -m pip install cubit-mesh-export). The package imports
Netgen at startup, so the wheel's pinned netgen-mesher dependency must also
be importable for JCF export.
import json
import os
from pathlib import Path
import sys
cubit_bin = r"C:\Program Files\Coreform Cubit 2026.8\bin"
cubit_dlls = os.add_dll_directory(cubit_bin) # Keep the handle alive.
sys.path.insert(0, cubit_bin)
import cubit
from cubit_mesh_export.jmag import export_jcf
cubit.init(["cubit", "-nographics", "-batch", "-nojournal", "-noinitfile"])
if not cubit.cmd('open "model.cub5"'):
raise RuntimeError("Cubit could not open model.cub5")
settings_path = Path("settings.json")
settings = json.loads(settings_path.read_text(encoding="utf-8"))
library = settings.get("material_library")
if isinstance(library, str):
library_path = settings_path.parent / library
settings["material_library"] = json.loads(library_path.read_text(encoding="utf-8"))
export_jcf("model.jcf", settings)
Use the path to your Cubit installation and an already meshed .cub5 model.
The menu resolves a material_library file name relative to settings.json;
with the Python API the caller loads that file into a dictionary as shown.
Femtet (COM) scope: this package ships only the entry-point contract and the menu action, verified with test handlers. A transfer through a real handler, including saving and reopening the model, depends on that handler and is not verified by this package.
If Cubit exits with code 2 while the export itself succeeded, check for a machine-wide
CUBIT_PLUGIN_DIRenvironment variable. A stale setting can cause Cubit to receive a-commandplugindirargument and report both the flag and its value as files it could not open. This is a diagnosed environment issue, not a reason to accept every exit code 2. Inspect the log and correct the stale setting, then rerun. An exported.volmust still passcheck-vol; a valid output alone does not prove the entire Cubit command completed successfully.
Upgrade
pip install --upgrade cubit-mesh-export
cubit-plugin-install
Always re-run cubit-plugin-install after upgrading.
cubit-plugin-install --verify-only checks both the deployed binary
hashes and the Cubit toolbar startup registration. If the official WorkflowToolbar was imported previously, the
installer refreshes its scripts and toolbar definition automatically and the
verification step rejects any stale deployed copy.
Native developer rebuild
Rebuild and propagate both mandatory native payloads from the current worktree with:
pwsh -File src/cubit_plugin/cubit_build.ps1 -Rebuild
The command fails unless both artifacts are produced and their copied
SHA-256 hashes match, then records the source-tree digest, source commit, and
both payload hashes in native_payloads.json. Wheel creation independently
recomputes that content evidence; checkout timestamps are irrelevant. It emits
a native cp312-cp312-win_amd64 wheel for CPython 3.12 on 64-bit Windows.
Because .pyd files are intentionally gitignored, upload the newly named,
content-addressed curver to the binaries GitHub release before pushing a
manifest change. Release CI downloads it and checks both native payloads.
Building a wheel from an sdist still verifies the manifest and both payloads;
only source-tree comparison is omitted when the C++ tree is not included.
For a complete deployed-export check, close the interactive Cubit process and run:
cubit-smoke-test --order 2
This launches Cubit in batch mode, exports the bundled solver-ready model, and applies
the production check-vol gate. Success requires strict boundary/material
labels, matching companion-JSON metadata, successful NGSolve reload,
tetrahedral topology, complete boundary-domain ownership, positive required
volumes and areas, and valid sampled Jacobians for the curved map. A failed run
retains its temporary work directory together with vol-check.json (or
vol-check-error.json) for diagnosis.
Cubit commands
export netgen "model.vol" order 3 overwrite # NGSolve FEM (.vol)
export gmsh "model.msh" order 2 overwrite # GMSH v4.2 raw data + .geo launch
export nastran_bdf "model.bdf" order 2 overwrite # Nastran BDF
export vtk "model.vtk" order 2 overwrite # VTK Legacy
export nastran_bdf is the only supported Nastran command. Nastran output is
a mesh-interchange deck: blocks become PSOLID or
PSHELL properties, sidesets become collision-free PSHELL properties, and
nodesets become SET1 cards. The exporter does not invent MAT cards; assign
physical material data in the receiving solver.
For Radia post-processing, .geo is the standard launch artifact. The Gmsh
export writes:
model.msh: raw GMSH v4.2 mesh/data containermodel.geo: normal review entry point; it mergesmodel.mshmodel.geo.opt: exact Gmsh sidecar auto-loaded whenmodel.geoopensmodel.msh.opt: raw mesh/data inspection sidecar whenmodel.mshopens
Associate/open .geo for normal review; treat .msh as optional raw
mesh/data inspection.
The export netgen command additionally accepts Kelvin / symmetry
options (see below). The other formats do not consume Kelvin.
Free Sculpt meshes
Sculpt places its hexes and boundary faces in free mesh groups. Use
gen_sidesets 2 and put the hexes in a material block before export:
sculpt volume all processors 1 size 0.01 gen_sidesets 2
block 1 add hex all
block 1 name "iron"
export netgen "model.vol" order 1 overwrite
The Netgen exporter reads both geometry-owned surfaces and direct/free
sideset tri/quads, deduplicates equal connectivity, and emits a synthetic
boundary descriptor for the latter. It recovers DomainIn/DomainOut from
the adjacent block elements and splits one sideset into multiple descriptors
when it spans more than one material pair. This is essential for disconnected
free bodies and mixed-material interfaces: assigning every free face to domain
1 silently removes the other materials from boundary-based operators.
check-vol audits that every volume domain appears in a valid boundary or
interface descriptor. Also verify that the .vol surface-element count equals
an independent topological-skin count before a surface-charge formulation uses
the mesh. Sculpt material blocks can exist without an owning CAD volume. The
companion JSON records these under mesh_only_materials, rather than inventing
a zero CAD volume in materials; check-vol then treats the label as valid but
reports that no CAD-volume reference is available.
For a free-mesh material interface created after Sculpt, materialize the skin of one block as a sideset:
skin block 1 make sideset 3
sideset 3 name "left_right_interface"
The exporter removes connectivity already owned by the exterior sideset,
emits the remaining interface once with both nonzero domains, and computes the
sidecar area from the faces actually exported under that label. check-vol
reports exterior and internal-interface counts separately and rejects duplicate
surface connectivity.
Workflow
┌────────────┐ export netgen ┌──────────┐
│ Cubit │ ─────────────────────────▶ │ .vol │
│ geometry │ (+add_kelvin, +sym) │ │
└────────────┘ └──────────┘
│
▼
user opens a Radia Simulink application block;
docs notebooks retain reproducible field evidence
cubit-mesh-export produces the .vol and the label conventions; the
domain block/headless tool reads the .vol and applies the physics. There is no
"pick your analysis" launcher in this plugin -- end-user tools split by
analysis target (IH designer / electromagnet designer / ...), not by
solver type.
Kelvin open-boundary transformation
Idempotent helper: skipped if a kelvin block already exists; needs an
air block in the current Cubit model.
export netgen "model.vol" order 3 overwrite \
add_kelvin # auto-create the exterior Kelvin sphere
[kelvin_air "air"] # name of the air block (default "air")
[kelvin_block "kelvin"] # name to give the Kelvin block (default "kelvin")
[kelvin_mesh 0.03] # tet size [m] on the Kelvin shell
# (omit to inherit from air outer surface)
[kelvin_sym_x {off|bn|ht}] # per-axis symmetry-plane BC
[kelvin_sym_y {off|bn|ht}] # off = no reduction (default)
[kelvin_sym_z {off|bn|ht}] # bn = B.n=0 (flux parallel)
# ht = HxN=0 (flux perpendicular)
In the Export Mesh GUI, the same options appear as widgets on the
Netgen Vol export dialog (only there -- Kelvin is .vol-specific).
The Kelvin step runs before the mesh extract / .vol write, so the
new kelvin block, the kelvin_int / kelvin_ext sidesets, and the
optional sym_<bc>_<axis> sidesets all end up in the .vol.
Symmetry semantics
kelvin_sym_<axis> |
Sideset name produced | B/H constraint | Radia image | A formulation | Omega formulation |
|---|---|---|---|---|---|
off |
(none) | (full domain) | n/a | n/a | n/a |
bn |
sym_bn=0_<axis> |
B·n = 0 | + |
Dirichlet (A×n=0) | natural |
ht |
sym_ht=0_<axis> |
H×n = 0 | - |
natural | Dirichlet (Ω=const) |
The convention is physics-named, formulation-agnostic: the same
sym_bn=0_x sideset means "B.n = 0 on x = 0 plane" regardless of
whether the domain panel solves A or Omega. Each domain tool decides
which BC type to apply per its formulation.
1/8 reduction (all three axes set to bn or ht) is supported when at
least one axis is ht. Three bn axes are physically impossible (B
parallel to three mutually perpendicular planes forces B = 0
everywhere) and rejected.
Label conventions
cubit-mesh-export reserves a small set of label names and prefixes
across all three NGSolve dimension levels (BND / BBND / BBBND). The
domain tools rely on these to wire up Dirichlet / Kelvin / symmetry
without having to inspect geometry.
BND -- surface labels (NGSolve mesh.GetBoundaries())
Source: Cubit sidesets on surfaces.
| Cubit sideset name | NGSolve BND name | Meaning |
|---|---|---|
kelvin_int |
kelvin_int |
Inner Kelvin face (auto-paired with outer via copy-mesh) |
kelvin_ext |
kelvin_ext |
Outer Kelvin face |
sym_bn=0_<axis> |
sym_bn=0_<axis> |
B.n = 0 (flux parallel) symmetry plane |
sym_ht=0_<axis> |
sym_ht=0_<axis> |
H×n = 0 (flux perpendicular) symmetry plane |
dir_<name> |
dir_<name> |
Dirichlet surface (variable = 0; physics is solver-side) |
neu_<name> |
neu_<name> |
Explicit Neumann (= no-op; documentation only) |
| anything else | (passes through) | Free-form name; meaning is up to the domain tool |
kelvin_int / kelvin_ext are auto-detected from the air ↔ kelvin
block topology when the user does not name them explicitly, so .jou
files using a plain "concentric Kelvin" pattern need no manual sideset
work.
BBND -- edge / curve labels (NGSolve mesh.GetBBoundaries())
Source: Cubit sidesets-on-curves, named with sideset <id> name "<label>".
Geometry curve names alone do not define a BBND label. For example:
sideset 100 add curve 1
sideset 100 name "test_edge"
Each curve's complete exported segmentation receives its sideset name in the
Netgen EdgeDescriptor/CD2 table. Multiple curves may share one label. Spaces
are normalized to underscores, as for surface labels. Different labels on the
same curve, the reserved name default, or a curve that cannot be completely
represented in the exported volume mesh cause export to fail before writing.
The exporter writes CD2 segments only for curves that own actual 1-D mesh edges and whose parent surfaces both have exported Netgen descriptors. Imported STL or Sculpt geometry can retain CAD curves while producing no BBND mesh segment; those stale curves are intentionally omitted from the companion edge-length references. For a point-only anchor, put the curve or vertices in a Cubit nodeset; the exporter expands the nodeset to BBBND points (next table).
The BBND label-name convention is:
| Cubit curve sideset name | NGSolve BBND name | Meaning |
|---|---|---|
dir_<name> |
dir_<name> |
Dirichlet edge (e.g. ground line in 2D) |
neu_<name> |
neu_<name> |
Explicit Neumann edge |
| anything else | (passes through) | Free-form; meaning is solver-side |
BBBND -- vertex / point labels (NGSolve mesh.GetBBBoundaries())
Source: Cubit nodesets. Free-floating vertices (not merged into any
meshed volume, e.g. the bare vertex add_kelvin_cubit creates at the
Kelvin sphere centre) are anchored to the nearest mesh node so the
BBBND point is always usable as a Dirichlet anchor.
| Cubit nodeset name | NGSolve BBBND name | Meaning |
|---|---|---|
GND |
GND |
Special: Omega-reduced anchor at Kelvin sphere centre |
dir_<name> |
dir_<name> |
Dirichlet point (e.g. PEEC port gnd, source / sink reference) |
| anything else | (passes through) | Free-form name; meaning is solver-side |
GND is automatically created by the Auto-Kelvin helper at the
Kelvin sphere centre (the image of physical infinity) for use by
Omega-reduced FEM formulations.
Python API
import netgen # must import before cubit (DLL load order)
import cubit
cubit.init(['cubit', '-nojournal', '-batch'])
cubit.cmd('open "model.cub5"')
cubit.cmd('mesh volume all')
cubit.cmd('block 1 add hex all') # elements must be in a block to export
cubit.cmd('export netgen "model.vol" order 3 overwrite') # high-order CURVED .vol (order 1-5)
# Load it in NGSolve. A high-order .vol already carries its curved mid-side nodes:
# load AS-IS and do NOT call mesh.Curve() -- mesh.Curve() re-curves from CAD geometry
# (absent in a loaded .vol) and would RESET every element to straight-sided.
from ngsolve import Mesh
mesh = Mesh("model.vol")
The Cubit-side Python helpers (Kelvin transformation, etc.) live in
cubit_mesh_export.cubit_helpers:
from cubit_mesh_export.cubit_helpers.add_kelvin import (
add_kelvin_cubit, # 3D Cubit path
add_kelvin_occ, # 3D OCC path
add_kelvin_2d_axisym, # 2D axisymmetric (r, z) path
sym_sideset_name, # canonical sym_<bc>_<axis> string
parse_sym_label, # inverse
)
In Cubit-embedded Python (where cubit_mesh_export itself is not
importable), the same helpers are available directly after
cubit-plugin-install deploys them to <Cubit>/bin/plugins/cubit_helpers/:
# Inside a .jou or panel script, after add_kelvin is on sys.path:
python "import sys; sys.path.insert(0, r'<Cubit>/bin/plugins/cubit_helpers')"
python "from add_kelvin import add_kelvin_cubit"
python "add_kelvin_cubit(R=0.06, symmetry=['z'])"
The export netgen ... add_kelvin flow handles sys.path
itself, so users invoking Kelvin via the new APREPRO args do not need
to set anything by hand.
Mesh consistency check (does NOT require Cubit)
check-vol model.vol # labels + curved-map quality
check-vol model.vol --strict-labels # enforce canonical label names
check-vol model.vol --contract ih_labels.json --strict-labels
check-vol model.vol --json model.vol.json # require this CAD reference
check-vol model.vol --tet-only --min-scaled-jacobian 0.05
check-vol model.vol --conductors copper,magnet \
--sibc-boundaries conductor_air,conductor_exterior
check-vol model.vol --format json --report-json run/vol_check.json
The sibling model.vol.json written by export netgen is auto-discovered when
present. It is optional for a standalone .vol: mesh loading, label checks,
and the curved NGSolve mapping gate still run without Cubit or CAD data. Passing
--json makes that specific sidecar mandatory. Curved-map sampling is enabled
by default; --no-quality is available only for a quick label/CAD inspection.
materials contains only labels with a real CAD-volume reference;
mesh_only_materials contains free-mesh block labels that cannot supply one.
The checker rejects a label appearing in both sets, so a true CAD zero is not
confused with the absence of CAD ownership.
from cubit_mesh_export.check import (
check_consistency,
check_label_contract,
check_mesh_quality,
)
results = check_consistency(
"model.vol",
contract="ih_labels.json",
strict_labels=True,
)
quality = check_mesh_quality(
"model.vol",
conductors=("copper", "magnet"),
sibc_boundaries=("conductor_air", "conductor_exterior"),
tet_only=True,
)
An application label contract is a versioned JSON object. required catches
missing solver labels; optional allowed lists reject labels that do not belong
to the selected application/mode.
{
"schema": "radia.vol-label-contract.v1",
"application": "radia-ih/fem-kelvin",
"strict_labels": true,
"required": {
"materials": ["coil", "air", "kelvin"],
"boundaries": ["source", "sink", "sibc", "kelvin_int", "kelvin_ext"],
"bbboundaries": ["GND"]
},
"allowed": {
"materials": ["coil", "air", "kelvin"],
"boundaries": [
"source", "sink", "sibc", "coil_surface", "air_seam",
"kelvin_int", "kelvin_ext"
]
}
}
Strict mode requires descriptive lower snake-case material/boundary names,
while preserving Radia's sym_bn=0_x / sym_ht=0_x convention and the reserved
GND point label. It rejects generated fallbacks such as volume_1 and
Surface_7, case-insensitive collisions, incomplete source/sink or
kelvin_int/kelvin_ext pairs, invalid Kelvin anchors, and contradictory
symmetry labels.
The quality gate samples the actual curved NGSolve element mapping; it does not
infer quality from straight corner nodes. A consistently positive or negative
element orientation is valid, while a sign change inside one element fails;
scaled quality uses abs(det(J)). It checks mapping magnitude, geometry order,
tetrahedron-only contracts, required labels, and material-aware face roles.
Only conductor-air or conductor-exterior faces may
be classified as SIBC. Conductor-insulator faces retain a trace role, while
conductor-conductor faces retain the interface/loop-bridge role needed by the
reduced HCurl cycle space.
check-vol returns 0 for pass, 1 for a validation finding, and 2 for an input or
configuration error. JSON reports use schema
cubit-mesh-export.vol-check.v1. Run the checker after .vol export and before
solver or Simulink initialization. Material constants are not inferred from
mesh labels; the application's checked DesignSpec/configuration owns those
values and validates them separately.
Source and licenses
The project license is Apache-2.0 for owner-authored exporter code. See third-party notices for the native components and their licenses.
Gmsh output boundary
The exported MSH 4.2 file is post-processing and visualization only.
It must never be loaded as a solver mesh or converted to .vol.
Solver input remains a checked .vol produced by Cubit or Netgen; that .vol
and its versioned contract remain the authority for labels and topology.
Gmsh inspection results do not certify a solver input or replace check-vol.
Gmsh 5 development runtime
Install Gmsh alone from its official development index in an isolated Python 3.12 environment, then install the exporter and its other dependencies from PyPI:
python -m pip install --pre -i https://gmsh.info/python-packages-dev gmsh --report gmsh-install.json
python -m pip install "cubit-mesh-export[mesh-quality]"
$env:CUBIT_GMSH_INSTALL_REPORT = (Resolve-Path gmsh-install.json).Path
$gmsh = (Get-Content -Raw gmsh-install.json | ConvertFrom-Json).install | Where-Object { $_.metadata.name -eq 'gmsh' }
python -m pip download --no-index --no-deps --dest gmsh-wheel $gmsh.download_info.url
$env:CUBIT_GMSH_WHEEL = (Get-ChildItem gmsh-wheel/*.whl).FullName
The extra declares gmsh>=5.0.0.dev0; there is no dated or upper metadata pin.
The quality runtime requires native major 5 and proves MSH 4.2 write/read support
in its isolated child before invoking Gmsh. Non-4.2 mesh input is rejected.
Retain the original wheel selected by the installer report; the runtime verifies
its full hash and compares the actual wrapper/native payloads against its ZIP
bytes. Neither installed RECORD nor a reconstructed wheel is the integrity oracle. Qualification
uses a hash-verified archived official wheel, not an unrecorded index resolution.
The exporter supports geometric orders 1-3 for hex/tet/triangle/quad, and 1-2
for wedge/pyramid. Unsupported requests fail before creating a partial .msh;
they never substitute a lower-order mesh. Pyramid 3 export remains unqualified:
the current official reference runtime advertises type 125 but cannot construct
it. This restriction is a pending adoption disposition, not a physics criterion
change.
Metadata
Release files for cubit-mesh-export 2.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cubit_mesh_export-2.3.1-cp312-cp312-win_amd64.whl | CPython 3.12 | CPython 3.12 | Windows x86-64 | Details for cubit_mesh_export-2.3.1-cp312-cp312-win_amd64.whl |
Release files / cubit_mesh_export-2.3.1-cp312-cp312-win_amd64.whl
| Download URL | cubit_mesh_export-2.3.1-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 2.5 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
2c3935cfda47c9cab72810d08ada2051ef258becc500523a28acd02e40539ad9
|
|
BLAKE2b-256 checksum How to use checksums |
f321ef10a7a3b4be61bfc93b870b03ddeb4f7ae575409858f20f742bd042aedb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.
Transparency logSecurity for cubit-mesh-export 2.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
1 file in this release has been uploaded with provenance metadata.
Attestation for cubit_mesh_export-2.3.1-cp312-cp312-win_amd64.whl
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.