Skip to main content

CHILmesh pipeline: peel layers, quality, truss, FEM smooth, peel layers

CHILmesh

2D mesh I/O, layer peel, smoothing, and quality analysis for triangular, quadrilateral, and mixed-element hydrodynamic meshes; C++ backend 8.6× to 14.7× faster than Python on full init.

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 maintained successor to the original MATLAB code. The MATLAB code is no longer maintained; it is at src/@CHILmesh/CHILmesh.m and on MATLAB File Exchange. To call the Python library from MATLAB, run pip install chilmesh and use the py. bridge, for example py.chilmesh.Mesh.read_from_fort14('ocean.14'). No MEX build is needed.


Table of Contents

  1. Status & Roadmap
  2. Why CHILmesh
  3. Installation
  4. Quick start
  5. Capabilities
  6. Performance
  7. Backends
  8. Examples and CLI
  9. Limitations
  10. Documentation
  11. Citation
  12. Contributing
  13. License

1. Status & Roadmap

Shipped: chilmesh 1.5.0 on PyPI (2026-10-02). The v1.x API is stable; downstream projects can pin chilmesh>=1.0,<2. Version 1.5.0 adds prebuilt C++ wheels (pip install "chilmesh[cpp]"), a size function for the FEM and angle-based smoothers, and an experimental GPU renderer (pip install "chilmesh[gpu]"). The full feature list is in Capabilities; release notes are in CHANGELOG.md.

  • Now: a native .chil container format, built on a sandbox branch first (#201).
  • Next: a documentation site; a streaming GPU mesh view for live mesh generation (#167).
  • Research: a medial-axis skeletonize() (#223); size-controlled mesh cartograms (#219).
  • Later: one ecosystem with ADMESH PyPI version and QuADMESH PyPI version.

2. Why CHILmesh

CHILmesh began in 2015-2017 at The Ohio State University as the data structure behind QuADMESH+, a layer-peel-driven indirect triangle-to-quadrilateral conversion heuristic for hydrodynamic models (Mattioli, MSc thesis, 2017; see Citation). The mesh generator needed three things no single tool provided: one adjacency model that treats triangles, quadrilaterals and mixed meshes identically; a concentric layer decomposition of the domain, from the boundary inward; and the ADCIRC and SMS file formats that coastal-ocean models read.

The Python library keeps that scope and adds the engineering the MATLAB code lacked. Seven adjacency tables are built once (docs/ARCHITECTURE.md), giving O(1) edge lookup, O(n) layer peel and O(log n) spatial queries. Every algorithm has one reference implementation in Python. The C++ backend reproduces it bit-for-bit, verified by 76 parametrized equivalence cases in tests/test_backend_equivalence.py. Terminology is fixed in docs/CONCEPTS.md: a layer is a concentric band of elements, distinct from a distance field, a medial axis or a skeleton ("vertex", "node" and "point" are interchangeable throughout this documentation).

3. Installation

pip install chilmesh             # PyPI, pure Python
pip install "chilmesh[cpp]"      # adds the prebuilt C++ backend
pip install "chilmesh[gpu]"      # adds the experimental GPU renderer
uv pip install chilmesh          # uv
pip install -e ".[dev]"          # from source, with the test suite

The [cpp] extra installs chilmesh-cpp, a prebuilt binary wheel for CPython 3.10 to 3.14 on Linux x86_64, macOS x86_64 and arm64, and Windows x86_64. No compiler is needed. Check the result with chilmesh.backend_info(); it reports 'selected': 'cpp'. On any other platform, pip builds chilmesh-cpp from source, which needs a C++ toolchain and CMake. To build from a clone of this repository:

pip install ./src/chilmesh_cpp    # or: bash scripts/build_cpp.sh

Python 3.10 or newer is required.

4. Quick start

import numpy as np
from chilmesh import Mesh

mesh = Mesh.read_from_fort14("ocean.14")          # ADCIRC grid, boundaries preserved
mesh.smooth_mesh(method="fem", acknowledge_change=True)
quality, angles, stats = mesh.elem_quality()      # per-element skew quality
elem = mesh.find_element(np.array([-75.2, 35.1]))  # O(log n) point location
mesh.write_to_fort14("ocean_smoothed.14")

chilmesh.CHILmesh remains as an alias of Mesh. Four fixtures ship with the package: chilmesh.examples.{annulus, donut, block_o, structured}().

5. Capabilities

Area What ships Entry points
File formats ADCIRC fort.14 (lossless round trip, boundary records kept), fort.13 nodal attributes, fort.15 control file; SMS Aquaveo .2dm; Gmsh .msh 2.2 and 4.1; header-only summary() for fort.14, .2dm, fort.13, fort.15, .msh, .npy and .npz without loading the mesh Mesh.read_from_fort14, read_fort13, read_fort15, Mesh.read_from_2dm, Mesh.read_from_msh, chilmesh.summary
Topology Triangular, quadrilateral and mixed meshes on one API; seven adjacency tables; concentric layer peel with per-layer OE, IE, OV, IV and boundary-edge IDs Mesh.peel_layers, mesh.layers
Quality Skew quality and interior angles per element; per-edge Courant number and a CFL gate from depths and a time step Mesh.elem_quality, courant_number, cfl_gate
Smoothing Balendran direct FEM; Zhou-Shimada angle-based; ADMESH spring-based truss against a signed distance function; plain Laplacian. FEM, angle-based and truss accept an optional target size function. Boundary nodes fixed, topology unchanged, mixed meshes accepted Mesh.smooth_mesh(method=...), Mesh.smooth
Mutation 13 topology operations: split triangle, split edge, split boundary edge, swap edge, merge elements, remove vertex, collapse edge, insert vertex, move boundary node, split triangles, topological smoothing, local re-peel, layer diff chilmesh.mutations
Boundary editing Advancing-front element addition, boundary-loop removal, pinch-point detection in narrow channels Mesh.add_advancing_front_element, Mesh.remove_boundary_loop, Mesh.pinch_points
Spatial queries Point-in-element, radius search, k-nearest vertices, all O(log n) after a one-time index Mesh.find_element, Mesh.find_elements_in_radius, Mesh.nearest_vertices
Geometry Haversine distance, convex hull, Hausdorff distance, antimeridian-aware bounding boxes chilmesh.geometry
Interop ADMESH domain adapter and truss warm start; renumbering-tolerant node matching between two meshes with nodal-field deltas Mesh.from_admesh_domain, chilmesh.admesh_warmstart, match_nodes
Plotting Mesh, per-element quality map, matched-colormap quality histogram, layer paths; experimental GPU rendering through the [gpu] extra Mesh.plot, Mesh.plot_quality, Mesh.plot_quality_histogram, chilplotting.render_image(backend="gpu")

6. Performance

The C++ backend full-initializes the 531,680-element ENPAC2003 mesh in 1.44 s against 12.30 s in Python, an 8.6× speedup; on the 98,365-element WNAT_Hagen mesh the ratio is 14.7× (1.65 s → 0.112 s). Reference workload: EasternPacific_ENPAC2003, 272,913 vertices, 531,680 elements, 75 layers, from the Valence registry. Medians of 3 runs on one machine at chilmesh 1.2.2; the algorithms have not changed since, and a 1.4.1 rerun on a second machine gave Python 11.89 s and C++ 0.803 s for full init.

Stage MATLAB (Octave 8.4) Python C++ Rust
Fast init (adjacency, no peel) 2.738 s 6.454 s 0.769 s not exposed
Peel only 12.771 s 5.814 s 0.669 s not exposed
Full init (adjacency + peel) 16.677 s 12.300 s 1.438 s 11.98 s †
Quality (signed area) 75 ms 51 ms 7 ms 2 ms †

Every backend runs the same operation on the same in-memory arrays; fort.14 parsing and rendering are excluded. All four resolve n_layers = 75, and Python and C++ layers are bit-identical. Octave builds adjacency 2.4× faster than Python through sparse() accumulation, and Python peels 2.2× faster than Octave. † Rust measured at chilmesh 1.4.1 on the second machine, where the same-machine controls were Python 11.89 s and C++ 0.803 s. Method, raw data and a 557-to-273k-vertex layer-parity catalog: docs/BENCHMARK.md.

EasternPacific_ENPAC2003 quality plot and distribution
Figure 1. EasternPacific_ENPAC2003 (272,913 vertices, 531,680 elements). plot_quality() renders per-element skew quality; plot_quality_histogram() draws the matched-colormap distribution beneath. Reproduce with python scripts/generate_enpac_showcase.py.

distance field vs medial axis vs skeleton vs layers
Figure 2. Distance is a scalar field; its ridge is the medial axis; the skeleton is a thinned discrete curve; layers are the concentric element bands CHILmesh peels. Definitions and algorithms: docs/CONCEPTS.md. Reproduce with python scripts/illustrate_mesh_concepts.py.

7. Backends

Backend Role Status How to get it
Python Reference implementation; every other backend is validated against it Default pip install chilmesh
C++ (half-edge) Accelerator, bit-identical output, 8.6× to 14.7× on full init Recommended pip install "chilmesh[cpp]" (prebuilt wheel), or pip install ./src/chilmesh_cpp (source build)
Rust (quad-edge) Output-equivalent on all four fixtures (rust-equivalence CI); measured 2× to 5× slower than C++ on full init Frozen, not developed further (docs/RUST_EVALUATION.md) maturin build in src/chilmesh_core, not recommended
MATLAB Original 2017 implementation Archived src/@CHILmesh/CHILmesh.m

With CHILMESH_BACKEND unset, CHILmesh selects the fastest available backend in the order C++, Rust, Python. Force one with CHILMESH_BACKEND=python|cpp|rust and inspect the choice with chilmesh.backend_info():

import chilmesh
chilmesh.backend_info()
# After `pip install "chilmesh[cpp]"` or a source build of the C++ extension:
# {'available': ['cpp', 'python'], 'selected': 'cpp',
#  'versions': {'cpp': '0.6.0', 'python': '1.5.0'}}

chilmesh 1.5.x requires chilmesh-cpp>=0.6,<0.7; both version numbers change together when the extension API changes. Platform coverage is listed in Installation.

Parity is gated in CI. The cpp-equivalence and rust-equivalence jobs build each extension and run the equivalence suite on every pull request to main and every push to main. After each chilmesh-cpp release, a further CI job installs the published wheel from PyPI on Linux, macOS and Windows and runs the same suite.

8. Examples and CLI

python examples/01_quickstart.py        # load, stats, plot
python examples/02_fort14_roundtrip.py  # fort.14 read and write
python examples/03_smoothing.py         # angle-based smoother
python examples/04_spatial_queries.py   # find_element, radius search, k-nearest
chilmesh info mesh.fort.14                                   # vertex, element and layer counts
chilmesh summary mesh.fort.14                                # header-only metadata, no full parse
chilmesh convert mesh.2dm mesh.fort.14                       # format conversion
chilmesh smooth mesh.fort.14 -o out.fort.14 --method fem     # smooth and write
chilmesh plot mesh.fort.14 -o mesh.png --quality             # render

python -m chilmesh is equivalent; every subcommand takes --help.

9. Limitations

  • Two-dimensional only. Vertices carry a z value for bathymetry, but all topology, quality and smoothing operate in the plane. Surface and volume meshes are out of scope.
  • A plain install runs at Python speed. pip install chilmesh has no compiled code. Add the [cpp] extra for the C++ column of the table above. Prebuilt C++ wheels cover Linux x86_64, macOS x86_64 and arm64, and Windows x86_64 only; Linux on ARM builds from source.
  • The GPU renderer is experimental. The [gpu] extra draws a static mesh and a per-element scalar. Streaming views and element picking are not available yet (#167). Off-screen rendering is tested; the interactive window is not.
  • Rust is frozen. It stays output-equivalent to Python but receives no new work. It exposes no separate fast-init or peel timing.
  • Smoothing does not change topology. Quality gains come from vertex moves only; the ADMESH truss smoother is triangle-only. Topological repair is the separate mutation API.
  • The size function can trade worst-element quality for size accuracy. On the 1.5.0 benchmark it lowers the mean size error by 4% to 20% but can lower the minimum aspect ratio, for example 0.614 → 0.453 on Test_Case_2 with FEM. Its two strength constants were tuned on the same meshes (docs/benchmarks/size_smoothing.md).
  • The .2dm writer drops boundary records. save('.2dm') then read_from_2dm is lossless for geometry and topology but not for fort.14 boundary metadata (#228).
  • Benchmarks are single-machine medians of three runs. Absolute times are machine-dependent; ratios between backends are the reproducible quantity.
  • The layer peel is not a medial axis, skeleton or distance transform. docs/CONCEPTS.md defines what the layers represent and what they do not.

10. Documentation

11. Citation

Software

Cite via Zenodo DOI

@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.5.0},
  doi       = {10.5281/zenodo.20263853},
  url       = {https://github.com/domattioli/CHILmesh}
}

Original method

QuADMESH Thesis

@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}
}

CHILmesh is a by-product of a project funded by Aquaveo at The Ohio State University in 2015-2017.

12. Contributing

Issues and pull requests at github.com/domattioli/CHILmesh. Run pytest -v before opening a PR; markers and backend setup are in tests/TESTING.md.

13. License

Noncommercial and research use only. PolyForm Noncommercial License 1.0.0 with an additional No-AI/ML-training restriction; see LICENSE and docs/AI-USAGE.md. Commercial use, and use as training, fine-tuning or evaluation data for any model, require a separate written license from github.com/domattioli.

Metadata

Release files for chilmesh 1.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chilmesh 1.5.0
File Size Uploaded
chilmesh-1.5.0.tar.gz 290.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for chilmesh 1.5.0
File Interpreter ABI Platform
chilmesh-1.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 533.7 kB

Release files / chilmesh-1.5.0.tar.gz

Download URL chilmesh-1.5.0.tar.gz
Size 290.0 kB
Tags Source
SHA-256 checksum
How to use checksums
bde4bba617fa0b56e85a586e45f96b7cbe88b9598172d245c13597ddb8003c18
BLAKE2b-256 checksum
How to use checksums
58d1989337d890534f8c78d99afbfbe673dd6f8d1c5c85f42351754100fc5224
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release files / chilmesh-1.5.0-py3-none-any.whl

Download URL chilmesh-1.5.0-py3-none-any.whl
Size 243.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d179b98bd770955b0585c652fc73df71a0deae8f88ad628a9128a97bf72ff7b5
BLAKE2b-256 checksum
How to use checksums
f56750d4a060ab89e52ff3584aa922f284a4ada1b4a6348587e6365acadfb3c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release history Release notifications | RSS feed

1.6.0

2 release files

This release

1.5.0 This release

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.1

2 release files

1.1.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page