Skip to content

Repository files navigation

CHILmesh pipeline — peel layers → quality → truss → FEM smooth → peel layers

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 (The CHIL)

PyPI Python 3.10+ Tests Open issues DOI License

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.m and on MATLAB File Exchange


Table of Contents

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 .chil file format
  • Future: formal integration within a unified ecosystem including ADMESH PyPI version and QuADMESH PyPI version

Why CHILmesh

The stable backbone for hydrodynamic mesh generation & tooling.

  • Pythonic APIfrom chilmesh import Mesh; backwards-compatible CHILmesh alias 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 chilmesh runs the (correct, but slower) Python backend and chilmesh.backend_info() reports available: ['python']. The C++/Rust speedups advertised below require a source build of the extension (pip install ./src/chilmesh_cpp with a C++ toolchain; cargo build --release in src/chilmesh_core for 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/OADCIRC .fort.14 and SMS Aquaveo .2dm read/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 integrationfrom_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 Pythonsparse()-accumulated, in compiled built-ins.
  • Python peels 2.2× faster than Octave — ~26% ahead on full init overall.
  • Rust — the layer peel matches Python on n_layers, layer-member sets (OE/IE/OV/IV), per-layer bEdgeIDs (full-mesh edge IDs, ascending), full-mesh Edge2Vert/Vert2Edge ordering, and signed areas — verified by the rust-equivalence CI job across all four fixtures incl. block_o (#163). Perf is now measured (the ENPAC cells above stay tbd — that mesh lives outside the repo): on the bundled fixtures Rust full-inits ~3–5× faster than Python but ~2–5× slower than C++. Its get_vertex_edges query path was O(n) per call (rebuilt the edge list each call); that defect is now fixed — the vertex→edge index is cached, so queries are O(1) (Block_O 954 μs → 0.32 μs, 76/76 equivalence tests still pass). Full data, methodology, the "should Rust replace Python anywhere?" analysis, and the default-backend/opt-in discussion: docs/RUST_EVALUATION.md. Bottom line: C++ remains the acceleration path; Rust earns no perf niche over it.

‡ Octave 8.4, interpreter. Times are in-memory compute only — fort.14 parse and rendering excluded. Machine-dependent. Full method: docs/BENCHMARK.md.

EasternPacific_ENPAC2003 quality plot and distribution
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:

distance field vs medial axis vs skeleton vs layers
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 ❄️ Frozen (experimental quad-edge); output-equivalent to Python (rust-equivalence CI, all 4 fixtures incl. block_o) but not developed further. Measured ~2–5× slower than C++ on full init (queries were O(n)/call, now cached to O(1)) — docs/RUST_EVALUATION.md concludes it earns no perf niche over C++ source build, not recommended
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 chilmesh from PyPI currently ships no compiled extension, so backend_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.

How the backend is chosen. When CHILMESH_BACKEND is unset, CHILmesh auto-selects the fastest available backend, in order C++ → Rust → Python — so a build that has only the Rust extension will use Rust over Python automatically. Force one with CHILMESH_BACKEND=python|cpp|rust, and check what's active with chilmesh.backend_info().

Opt-in reality — both compiled backends are source builds. Neither C++ nor Rust ships in the PyPI wheel, and Rust is not a lighter-weight opt-in than C++: C++ needs a C++ toolchain + CMake (pip install ./src/chilmesh_cpp), Rust needs a Rust toolchain (maturin build …). Until pre-built binary wheels land (#229), a plain pip install chilmesh runs pure-Python everywhere. If you build one, build C++ — it is the recommended accelerator (~5× faster than Rust on full init, bit-identical output); the Rust backend is frozen (kept and output-equivalent, but not developed further — docs/RUST_EVALUATION.md explains why it earns no niche over C++ and should not replace Python). The path to making C++ the zero-opt-in default is prebuilt binary wheels (docs/dev/PREBUILT_WHEELS_PLAN.md, #229), not switching languages. The cpp↔python bit-identity guarantee is gated in CI by the cpp-equivalence job and Rust output-parity by the rust-equivalence job, both of which build the extension and run 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 reference
  • docs/BENCHMARK.md — benchmark methodology and raw data
  • docs/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) QuADMESH Thesis

@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

About

Mesh data structure for representing triangular, quadrangular, and mixed-element meshes. Intended for hydrodynamic domains.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages