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 (CHIL)
Badges
Why CHILmesh
The stable backbone for hydrodynamic mesh tooling. Sibling projects ADMESH, ADMESH-Domains, and QuADMesh build on top of it.
- Pythonic API —
from chilmesh import Mesh; backwards-compatibleCHILmeshalias preserved. - C++ acceleration, bit-identical output — half-edge extension is ~15× faster than pure Python on full init, verified bit-for-bit by 36 cross-backend equivalence tests.
- One interface for all topologies — triangles, quadrilaterals, and mixed meshes share the same call surface.
- Stable v1.x API — sibling projects can pin
chilmesh>=1.0,<2.
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 MathWorks.
Installation
pip install chilmesh # PyPI
uv pip install chilmesh # uv
conda install -c conda-forge chilmesh # conda-forge (pending)
pip install -e . # from source
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 does full init + quality analysis on a 98,365-element mesh in ~0.11 s (~15× faster than pure Python)
- 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 skeletonization (medial axis)
- 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 —
insert_vertex, coord moves, advancing-front element addition; full mutation suite tracked in #94 - ADMESH-Domains integration —
from_admesh_domain()adapter
Performance
Reference workload: WNAT_Hagen (52,774 vertices · 98,365 elements · 151,248 edges · 30 layers). v1.1.0 medians, single machine. Backends are output-equivalent — the C++ extension produces bit-identical skeletonization layers to Python (n_layers = 30 on all three), verified by tests/test_backend_equivalence.py.
| Stage | MATLAB (Octave) ‡ | Python | C++ |
|---|---|---|---|
| Fast init (adj, no skeletonization) | 0.27 s | 1.31 s | 0.060 s |
| Skeletonization only | 0.67 s | 0.32 s | 0.052 s |
| Full init (adj + skeletonization) | 1.04 s | 1.65 s | 0.112 s |
| Quality analysis | 12 ms | 6.4 ms | 1.3 ms |
C++ is ~15× faster than Python on full init (1.65 s → 0.112 s) and ~9× faster than the original Octave implementation. ‡ MATLAB measured under GNU Octave 8.4 (interpreter, not MATLAB JIT) — the original-algorithm baseline, not a MATLAB-vs-Octave claim. Rust is excluded — its skeletonization is incomplete (#163). Absolute times are machine-dependent; full methodology and the regenerating harness: docs/BENCHMARK.md.
Figure 1. Scale demo on WNAT_Hagen (52,774 vertices · 98,365 elements). plot_quality() renders per-element skew quality; plot_quality_histogram() emits the matched-colormap distribution beneath. Reproduce: python scripts/generate_wnat_showcase.py.
Validation
Python, C++, and the original MATLAB/Octave implementation all produce identical n_layers (medial-axis skeletonization) across the ADMESH-Domains catalog, from 557 to 132k vertices. Identical connectivity + points are fed to both implementations; only the layering algorithm is compared.
| Mesh | Vertices | Elements | MATLAB | Python | C++ | Match |
|---|---|---|---|---|---|---|
| Baranja Hill (ADMESH v2) | 557 | 1,011 | 10 | 10 | 10 | ✅ |
| Baranja Hill | 645 | 1,193 | 12 | 12 | 12 | ✅ |
| Wetting/Drying test | 2,716 | 4,978 | 15 | 15 | 15 | ✅ |
| Lake Erie (refined) | 5,095 | 9,688 | 20 | 20 | 20 | ✅ |
| Lake Erie (5k) | 13,266 | 24,910 | 17 | 17 | 17 | ✅ |
| Delaware Bay | 14,449 | 26,698 | 17 | 17 | 17 | ✅ |
| Delaware Bay (h 100–20000) | 14,449 | 26,697 | 17 | 17 | 17 | ✅ |
| Lake Michigan | 21,981 | 41,887 | 25 | 25 | 25 | ✅ |
| WNAT (Hagen) | 52,774 | 98,365 | 30 | 30 | 30 | ✅ |
| Chesapeake Bay | 83,388 | 160,734 | 55 | 55 | 55 | ✅ |
| Great Lakes | 132,162 | 250,905 | 46 | 46 | 46 | ✅ |
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 | chilmesh.optimize_with_admesh_truss(mesh, sdf, ...) |
Spring/force relaxation against SDF | Quality gains with SDF-respecting boundary nodes |
References:
- Balendran (1999). A direct smoothing method for surface meshes. Proc. 8th IMR, pp. 189–193.
- Zhou & Shimada (2000). An angle-based approach to two-dimensional mesh smoothing. Proc. 9th IMR, pp. 373–384.
- Conroy et al. (2012). ADMESH: An advanced, automatic unstructured mesh generator for shallow water models. doi:10.1007/s10236-012-0574-0.
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, ~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 (build from source) |
| Rust | Experimental (quad-edge); skeletonization is incomplete — see #163 | source build, not recommended yet |
| MATLAB | Original 2017 implementation, archived & unmaintained | src/@CHILmesh/CHILmesh.m |
import chilmesh
chilmesh.backend_info()
# {'available': ['cpp', 'python'],
# 'selected': 'cpp',
# 'versions': {'cpp': '0.6.0.dev0', 'python': '1.1.0'}}
Force a specific backend with CHILMESH_BACKEND (python or cpp). When unset, the fastest available is picked. Pre-built binary wheels (manylinux / macOS / Windows) via cibuildwheel are planned — see docs/ for build-from-source instructions.
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.
Ecosystem
CHILmesh is the core engine for the ADCIRC mesh ecosystem. Sibling projects build on it; CHILmesh depends on none of them.
| Repo | Role |
|---|---|
| ADMESH | Unstructured triangle mesh generator; consumes CHILmesh for adjacency, smoothing, and quality analysis |
| ADMESH-Domains | Curated ADCIRC mesh registry; Mesh.from_admesh_domain() reads from it directly |
| QuADMesh | Quad mesh generator (MATLAB → Python port, in progress); CHILmesh data structure descends from the original QuADMesh+ |
| MADMESHing | Benchmark harness comparing ADMESH triangulation vs quad generators; uses CHILmesh for quality analysis |
DomI provides dev-session skills and governance infrastructure for all repos.
Status & Roadmap
- Shipped (v1.1.0): C++ half-edge backend (~15× faster on full init); bit-identical output verified; 36 cross-backend equivalence tests; fort.14 + .2dm I/O; mixed-element support.
- In flight: Pre-built binary wheels (cibuildwheel, manylinux/macOS/Windows) · Rust skeletonization completion (#163) · Full mutation suite (#94)
- Next: conda-forge packaging · mkdocs API site · advancing-front element mutation
Open issues: github.com/domattioli/CHILmesh/issues
Documentation
docs/API.md— full API referencedocs/BENCHMARK.md— benchmark methodology and raw datatests/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 skeletonization-driven indirect tri-to-quad conversion heuristic (Mattioli, OSU MSc thesis, 2017). This Python library is the actively-developed successor.
@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.1.0},
doi = {10.5281/zenodo.20263854},
url = {https://github.com/domattioli/CHILmesh}
}
MATLAB 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: domburner@duck.com
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.2.1.tar.gz.
File metadata
- Download URL: chilmesh-1.2.1.tar.gz
- Upload date:
- Size: 242.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0908b9887a8b1d85f2bd53fbbdc043d64abfe7c247cd144884d94c3b4bca1bd5
|
|
| MD5 |
2a337d1060e871ab66bd9a517a61096f
|
|
| BLAKE2b-256 |
c0a420fdd3801699ca165126c1a8a6ddf8647756b503873df3bf3ca70864f086
|
File details
Details for the file chilmesh-1.2.1-py3-none-any.whl.
File metadata
- Download URL: chilmesh-1.2.1-py3-none-any.whl
- Upload date:
- Size: 202.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c13aeb71e53fb9aca38d4d78f79a7366b1b6ac620a02fc9b0ef8084dafa35e20
|
|
| MD5 |
7c1fce8152e8eb75c130ec2982eaec15
|
|
| BLAKE2b-256 |
24d0f7d9a337d42e4c87665996108c747494a9e08d7fa308ff17efeae0a48a5d
|