Skip to main content

Fast 2D mesh library for hydrodynamic domains — Python API with optional C++ acceleration

Project description

CHILmesh pipeline — raw → smoothed → skeletonized

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)

CHIL Lab @ OSU PyPI Tests DOI MATLAB File Exchange 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 MathWorks.


Table of Contents


Why CHILmesh

The stable backbone for hydrodynamic mesh tooling. Sibling projects ADMESH, ADMESH-Domains, and QuADMesh build on top of it.

  • Pythonic APIfrom chilmesh import Mesh; backwards-compatible CHILmesh alias preserved.
  • C++ acceleration, bit-identical output — half-edge extension is ~24× 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.

Quick Start

pip install chilmesh
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.


Gallery

WNAT_Hagen quality plot and distribution
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.

Mixed-element mesh: wireframe, layers, quality
Figure 2. Mixed-element pipeline — wireframe, skeletonization, and per-element quality on one tri+quad mesh. Reproduce: python scripts/generate_mixed_truss_demo.py.

Skeletonization + quality plotting across three smoothing states
Figure 3. plot_layer() and plot_quality() tracking skeletonization and quality across raw → truss → FEM smoothing. Reproduce: python scripts/generate_3row_admesh.py.

Animated 4-stage CHILmesh annulus pipeline
Figure 4. Figure 3 as a Manim animation. Higher-fidelity 1080p at output/readme_pipeline_annulus.mp4.


Features

  • Fast — full init + quality analysis on a 98,365-element mesh in ~1.7 s (4.6× faster than v0.2.0)
  • 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/OADCIRC .fort.14 and SMS Aquaveo .2dm read/write
  • Spatial queries — point-in-element, k-nearest vertices, radius search at O(log n)
  • Mesh alterationsinsert_vertex, coord moves, advancing-front element addition; full mutation suite tracked in #94
  • ADMESH-Domains integrationfrom_admesh_domain() adapter

Installation

pip install chilmesh                        # PyPI
uv pip install chilmesh                     # uv
conda install -c conda-forge chilmesh       # conda-forge (pending)
pip install -e .                            # from source

Performance

Reference workload: WNAT_Hagen (52,774 vertices · 98,365 elements). Median of 3 trials. v1.0.0 backends are output-equivalent — the C++ extension produces bit-identical skeletonization layers to Python, verified by tests/test_backend_equivalence.py.

Metric v0.1.0 MATLAB ‡ v0.2.0 Python Port v0.3.0 Python Optimized v0.4.0 Rust † v1.0.0 C++
Fast init (adj, no skeletonization) 0.27 s ~3.9 s 1.31 s 0.029 s 0.036 s
Skeletonization only 0.67 s ~3.8 s 0.32 s 0.20 s 0.033 s
Full init (adj + skeletonization) 1.04 s 7.7 s 1.65 s 0.23 s 0.069 s
Quality analysis 12 ms 6.6 s 6.4 ms <1 ms <1 ms
Vertex-edge lookup (per call) ~2200 μs ~700 μs 0.34 μs 0.02 μs 0.04 μs

C++ is ~24× faster than Python on full init. Python's skeletonization is now within ~10× of C++ (and faster than the original MATLAB/Octave); the remaining Python gap is the pure-Python adjacency build (~4× slower than vectorized MATLAB, the largest single cost). The Python implementation remains the canonical reference; C++ is opt-in via direct chilmesh_cpp import, Rust via chilmesh_core.

‡ MATLAB v0.1.0 = the original QuADMesh+ @CHILmesh class (Mattioli, OSU MSc thesis, 2017) measured under GNU Octave 8.4 (no MathWorks MATLAB license in CI) on WNAT_Hagen, connectivity + points fed to the 2-arg constructor; medians of 3. Absolute times are Octave's interpreter, not MATLAB JIT — treat as the original-algorithm baseline, not a MATLAB-vs-Octave claim.
† Rust (v0.4.0) is experimental: its skeletonization is incomplete (#163), so the skeletonization/full-init figures reflect a partial peel, not a verified result. Fast init includes fort.14 file I/O; Python and C++ receive raw arrays.

Full methodology and raw data: docs/BENCHMARK.md.


Validation

Cross-language skeletonization parity. The Python port's n_layers (medial-axis skeletonization) is validated against the original QuADMesh+ MATLAB @CHILmesh algorithm — run under GNU Octave 8.4 — across the ADMESH-Domains catalog, from 557 to 132k vertices. Identical connectivity + points are fed to both implementations; the MATLAB reader is bypassed so 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

n_layers agrees across MATLAB (original), Python (reference), and C++ on all 11 meshes (557 → 132k vertices). The seven previously-uncaptured reference counts (Lake Erie refined, Delaware Bay refined, Chesapeake Bay, Great Lakes, Lake Michigan, both Baranja Hill variants) were captured here and pinned in tests/test_skeletonization_matlab_parity_external.py (#128). C++↔Python equivalence is also unit-tested by tests/test_backend_equivalence.py. Reproduce any of this with python scripts/benchmark.py --matlab. (Rust is omitted — its skeletonization is incomplete, #163.)


Implementations

CHILmesh exists in four languages, but you only need to think about two. 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 implementation: same algorithms, bit-identical output, ~24× faster on full init — opt-in when you need the speed.

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

You write the same Python API regardless; the C++ core is transparently used when present.

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.

Building the C++ extension (from source — scikit-build-core + pybind11, fetched automatically):

pip install ./src/chilmesh_cpp

Pre-built binary wheels (manylinux / macOS / Windows) via cibuildwheel are planned.


API Overview

from chilmesh import Mesh, examples

# Load
mesh = examples.annulus()
mesh = Mesh.read_from_fort14('mesh.14')
mesh = Mesh.read_from_2dm('mesh.2dm')

# Smooth, analyse, visualise
mesh.smooth_mesh(method='fem', acknowledge_change=True)
quality, angles, stats = mesh.elem_quality()
mesh.plot()             # wireframe
mesh.plot_quality()     # per-element quality
mesh.plot_layer()       # skeletonization layers

# Skeletonization output
layers = mesh.Layers    # {'OE', 'IE', 'OV', 'IV', 'bEdgeIDs'} per layer

# Spatial queries
elem_id = mesh.find_element([0.5, 0.0])
neighbors = mesh.nearest_vertices([0.5, 0.0], k=5)
in_radius = mesh.find_elements_in_radius([0.5, 0.0], radius=0.2)

Full reference: docs/API.md.


Mesh 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.

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.


Sibling Projects

CHILmesh is the shared mesh-data substrate for a small ecosystem of hydrodynamic mesh tooling. Each sibling depends on CHILmesh; CHILmesh depends on none of them.

Repo Language Description
ADMESH Python Advanced, automatic unstructured mesh generator for shallow water models (Conroy et al., 2012). Consumes CHILmesh for adjacency, smoothing, and quality analysis.
ADMESH-Domains Python Registry of ADMESH / ADCIRC-compatible hydrodynamic domains. Pairs with chilmesh.Mesh.from_admesh_domain() for one-call mesh loading.
QuADMesh MATLAB Original research project (OSU MSc thesis, 2017) on skeletonization-driven indirect tri-to-quad conversion. Pre-dates this Python ecosystem; CHILmesh's data structure descends from it.

Contributing

Issues and PRs welcome at github.com/domattioli/CHILmesh. Run pytest -v before opening a PR — see TESTING.md.


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.0.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}
}

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chilmesh-1.1.0.tar.gz (4.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chilmesh-1.1.0-py3-none-any.whl (182.7 kB view details)

Uploaded Python 3

File details

Details for the file chilmesh-1.1.0.tar.gz.

File metadata

  • Download URL: chilmesh-1.1.0.tar.gz
  • Upload date:
  • Size: 4.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for chilmesh-1.1.0.tar.gz
Algorithm Hash digest
SHA256 e22b3f85084c1e8acb3604870538392128b17de292aa0096f797de8a68a87068
MD5 a51fb3d823465940e878f18e898fb13f
BLAKE2b-256 02a683e9005b4f560fa1c5e134129e4cd60eb80cbd0cf172c2a456ca82e5cc88

See more details on using hashes here.

File details

Details for the file chilmesh-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: chilmesh-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 182.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for chilmesh-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d081c08ada101e89e51f61c5ddb8fa61ef6a6257e92dafba7cafd4308740d36f
MD5 6456ef13d79c5f732f9ea6827ad3914c
BLAKE2b-256 c6cd688e4ff8aa686cfee770c7580033fe438734b0180ff05e7952d3919cf23d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page