Fast 2D mesh library for hydrodynamic domains — Python API with optional C++ acceleration
Project description
CHILmesh
Fast 2D mesh processing, smoothing, and analysis for triangular, quadrilateral, and mixed-element meshes. Intended for hydrodynamic domains.
Dominik Mattioli1†, Ethan Kubatko2
†Corresponding author | 1Unaffiliated | 2Ohio State University ()
MATLAB users: This Python library is the actively-developed successor to the original MATLAB codebase. The original (no longer maintained) is at
src/@CHILmesh/CHILmesh.mand on
Table of Contents
- Status & Roadmap
- Why CHILmesh
- Installation
- Quick start
- Features — Performance · Smoothing · Backends · Engine · Examples · CLI
- Citation
- Contributing · Documentation · License
Status & Roadmap
Current status (June 2026): Stable and actively-maintained. C++ half-edge backend (up to ~15× faster on full init); bit-identical output verified; cross-backend equivalence tests across C++ and Rust; fort.14 + .2dm + fort.13 I/O; mixed-element support; full mesh-mutation API (split/swap/merge/collapse, #94); lazy header-only summary().
- Now: Pre-built binary wheels (cibuildwheel, manylinux/macOS/Windows); Rust layer-peel completion (#163).
- Next: performance optimization; parallelization; conda-forge packaging; mkdocs API site; native
.chilfile format - Future: formal integration within a unified ecosystem including
and
Why CHILmesh
The stable backbone for hydrodynamic mesh generation & tooling.
- Pythonic API —
from chilmesh import Mesh; backwards-compatibleCHILmeshalias preserved. - C++ acceleration, bit-identical output — half-edge extension is up to ~15× faster than pure Python on full init (8.6× on the 272k-element ENPAC mesh below), verified bit-for-bit by the cross-backend equivalence suite (76 tests across C++ and Rust backends).
- One interface for all topologies — triangles, quadrilaterals, and mixed meshes share the same call surface.
- Stable v1.x API — downstream projects can pin
chilmesh>=1.0,<2.
Installation
pip install chilmesh # PyPI
uv pip install chilmesh # uv
conda install -c conda-forge chilmesh # conda-forge (pending)
pip install -e . # from source
Backends & the PyPI wheel. The published PyPI wheel is currently pure-Python — it does not bundle the compiled C++/Rust extensions, so a plain
pip install chilmeshruns the (correct, but slower) Python backend andchilmesh.backend_info()reportsavailable: ['python']. The C++/Rust speedups advertised below require a source build of the extension (pip install ./src/chilmesh_cppwith a C++ toolchain;cargo build --releaseinsrc/chilmesh_corefor Rust). Pre-built binary wheels are tracked in #229.
Quick Start
from chilmesh import Mesh
mesh = Mesh.read_from_fort14("ocean.14")
mesh.smooth_mesh(method="fem", acknowledge_change=True)
quality, angles, stats = mesh.elem_quality()
mesh.plot_quality()
The legacy chilmesh.CHILmesh import is preserved for backward compatibility. Built-in fixtures live at chilmesh.examples.{annulus, donut, block_o, structured}(). See examples/ for runnable scripts.
Features
- Fast — C++ backend full-inits the 531,680-element ENPAC2003 mesh in ~1.4 s — 8.6× over pure Python (up to ~15× on smaller meshes)
- Mixed-element — triangles, quads, and mixed meshes share one API
- Smoothing — Balendran direct FEM, Zhou-Shimada angle-based, and ADMESH Spring-Based Truss
- Analysis — element quality, interior angles, layer-based decomposition (peel_layers)
- I/O — ADCIRC
.fort.14and SMS Aquaveo.2dmread/write - Spatial queries — point-in-element, k-nearest vertices, radius search at O(log n)
- Mesh alterations — advancing-front element addition (
add_advancing_front_element), coordinate moves; full mutation suite tracked in #94 - Valence integration —
from_admesh_domain()adapter
Performance
Reference workload: EasternPacific_ENPAC2003 — 272,913 vertices · 531,680 elements · 75 layers, from the Valence registry. Medians of 3 runs, single machine, chilmesh 1.2.2.
| Stage | MATLAB (Octave) ‡ | Python | C++ | Rust |
|---|---|---|---|---|
| Fast init (adj, no peel) | 2.738 s | 6.454 s | 0.769 s | tbd |
| Peel only | 12.771 s | 5.814 s | 0.669 s | tbd |
| Full init (adj + peel) | 16.677 s | 12.300 s | 1.438 s | tbd |
| Quality (signed area) | 75 ms | 51 ms | 7 ms | tbd |
Like-for-like: every backend runs the same operation on the same in-memory arrays. No fort.14 parse, signed-area quality. All resolve n_layers = 75; Python↔C++ layers are bit-identical (test_backend_equivalence.py).
- C++ leads every stage — full init 8.6× over Python, 11.6× over Octave.
- Octave builds adjacency 2.4× faster than Python —
sparse()-accumulated, in compiled built-ins. - Python peels 2.2× faster than Octave — ~26% ahead on full init overall.
- Rust — the layer peel now matches Python on
n_layers, layer-member sets (OE/IE/OV/IV), per-layerbEdgeIDs(full-mesh edge IDs, ascending), full-meshEdge2Vert/Vert2Edgeordering, and signed areas — verified by therust-equivalenceCI job across all four fixtures incl.block_o(#163); only perf timings (tbd) remain open.
‡ Octave 8.4, interpreter. Times are in-memory compute only — fort.14 parse and rendering excluded. Machine-dependent. Full method: docs/BENCHMARK.md.
Figure 1. Scale demo on EasternPacific_ENPAC2003 (272,913 vertices · 531,680 elements). plot_quality() renders per-element skew quality; plot_quality_histogram() emits the matched-colormap distribution beneath. Reproduce: python scripts/generate_enpac_showcase.py.
Full pipeline cost (parse · adjacency · peel · spatial-index · quality · render — render dominates), the cross-backend layer-parity catalog (557 → 273k vertices), and mesh-quality metrics: docs/BENCHMARK.md. The layer peel is distinct from medial axis / skeleton / distance — docs/CONCEPTS.md:
Figure 2. Related, not identical — distance is a scalar field; its ridge is the medial axis; the skeleton is a thinned discrete curve; layers are concentric element bands (what CHILmesh peels). Full write-up: docs/CONCEPTS.md. Reproduce: python scripts/illustrate_mesh_concepts.py.
Smoothing
Three algorithms — each preserves boundary nodes, leaves topology unchanged, and accepts mixed-element meshes.
| Algorithm | API call | Style | Best for |
|---|---|---|---|
| Balendran direct FEM | smooth_mesh(method='fem') |
One-shot sparse solve | General-purpose default; stable on tri/quad/mixed |
| Zhou-Shimada angle-based | smooth_mesh(method='angle-based') |
Iterative, angle-maximising | Difficult mixed meshes where FEM stalls |
| ADMESH Spring-Based Truss | smooth_mesh(method='sdf', sdf=...) |
Spring/force relaxation against SDF | Quality gains with SDF-respecting boundary nodes (triangle-only) |
Backends
pip install chilmesh gives you the pure-Python implementation — zero compiled dependencies, runs everywhere, and is the canonical reference every other backend is validated against. The C++ extension is the high-performance opt-in: same algorithms, bit-identical output, up to ~15× faster on full init.
| Language | Role | How to get it |
|---|---|---|
| Python | Reference implementation — the default | pip install chilmesh |
| C++ | High-performance backend (half-edge) — bit-identical output | pip install ./src/chilmesh_cpp (or bash scripts/build_cpp.sh) |
| Rust | Experimental (quad-edge); the layer peel (backend skeletonize()) reaches full n_layers/layer-member/bEdgeIDs/edge-ordering parity with Python (rust-equivalence CI, all 4 fixtures incl. block_o), perf timings still open — see #163 |
source build, not recommended yet |
| MATLAB | Original 2017 implementation, archived & unmaintained | src/@CHILmesh/CHILmesh.m |
import chilmesh
chilmesh.backend_info()
# After a source build of the C++ extension:
# {'available': ['cpp', 'python'],
# 'selected': 'cpp',
# 'versions': {'cpp': '0.6.0.dev0', 'python': '1.2.2'}}
PyPI installs are pure-Python. The example above reflects a source build of the C++ extension. A plain
pip install chilmeshfrom PyPI currently ships no compiled extension, sobackend_info()reports{'available': ['python'], 'selected': 'python'}(#229). Build from source (pip install ./src/chilmesh_cpp) for the C++ path until pre-built binary wheels land.
Force a specific backend with CHILMESH_BACKEND (python or cpp). When unset, the fastest available is picked. The cpp↔python bit-identity guarantee is gated in CI by the cpp-equivalence job (ubuntu), which builds the extension and runs tests/test_backend_equivalence.py. Pre-built binary wheels (manylinux / macOS / Windows) via cibuildwheel are planned — see docs/ for build-from-source instructions.
Engine
CHILmesh is a graph over the mesh — seven adjacency tables (built once) back O(1) edge lookup, O(n log n) adjacency build, O(n) peel, and O(log n) spatial queries. The C++ half-edge backend reproduces them bit-for-bit. Full table + complexities: docs/ARCHITECTURE.md.
Examples
python examples/01_quickstart.py # load, stats, plot
python examples/02_fort14_roundtrip.py # fort.14 read/write
python examples/03_smoothing.py # angle-based smoother
python examples/04_spatial_queries.py # find_element, radius search, k-nearest
CLI
chilmesh info mesh.fort.14 # stats
chilmesh convert mesh.2dm mesh.fort.14 # format conversion
chilmesh smooth mesh.fort.14 -o out.fort.14 --method fem # smooth in-place
chilmesh plot mesh.fort.14 -o mesh.png --quality # render
Also available as python -m chilmesh. Each subcommand has --help.
Documentation
docs/API.md— full API referencedocs/BENCHMARK.md— benchmark methodology and raw datadocs/CONCEPTS.md— distance vs medial axis vs skeleton vs layers (definitions, algorithms, math, synonyms)tests/TESTING.md— test guide (pytest markers, local commands)examples/— runnable scripts (quickstart, fort.14 round-trip, smoothing, spatial queries)
Citation
CHILmesh originated in MATLAB as the data structure backing a layer-peel-driven indirect tri-to-quad conversion heuristic (Mattioli, OSU MSc Thesis, 2017)
@software{mattioli_chilmesh,
author = {Mattioli, Dominik O. and Kubatko, Ethan J.},
title = {{CHILmesh}: a fast 2D mesh library for triangular,
quadrilateral, and mixed-element grids},
year = {2026},
publisher = {Zenodo},
version = {1.2.2},
doi = {10.5281/zenodo.20263854},
url = {https://github.com/domattioli/CHILmesh}
}
Thesis source (Mattioli, 2017). Read thesis (PDF)
@mastersthesis{mattioli2017quadmesh,
author = {Mattioli, Dominik O.},
title = {{QuADMESH+}: A Quadrangular ADvanced Mesh Generator
for Hydrodynamic Models},
school = {The Ohio State University},
year = {2017},
url = {http://rave.ohiolink.edu/etdc/view?acc_num=osu1500627779532088}
}
Contributing
Issues and PRs welcome at github.com/domattioli/CHILmesh. Run pytest -v before opening a PR — see tests/TESTING.md.
License
Noncommercial / research use only. Licensed under the PolyForm Noncommercial License 1.0.0 with an additional No-AI/ML-training restriction — see LICENSE and .claude/AI-USAGE.md. No commercial use and no use as AI/ML training data without a separate written license. Commercial or AI-training licenses: https://github.com/domattioli
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chilmesh-1.4.0.tar.gz.
File metadata
- Download URL: chilmesh-1.4.0.tar.gz
- Upload date:
- Size: 269.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8db83de161ed9f7a79a30fe4f97be192b4a1607daa9be153370c87dc328bd160
|
|
| MD5 |
d71058caee6e4a1f77d52b8d5de1a99a
|
|
| BLAKE2b-256 |
e18491152596ca58755f309339ea05ab1e14c4441870db9153d228d3a4901754
|
File details
Details for the file chilmesh-1.4.0-py3-none-any.whl.
File metadata
- Download URL: chilmesh-1.4.0-py3-none-any.whl
- Upload date:
- Size: 226.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea8ba24f708eea77ce2f4a79ea3b8658ad27ae0f4b1955fdae06d978157118aa
|
|
| MD5 |
bdce422290c278d80e1341758ca96eb4
|
|
| BLAKE2b-256 |
55cdf57b69a40b8723ee5e2e68680669de092c1fa88630c26b81d151262be77c
|