ADMESH: an advanced, automatic unstructured mesh generator for 2D shallow-water models.
Project description
ADMESH
An advanced, automatic unstructured mesh generator for 2D shallow-water models.
Python port of the MATLAB ADMESH library, with native ADCIRC fort.14 round-trip and a Pythonic API.
Western North Atlantic / Gulf / Caribbean — meshed with curvature-driven sizing and dominant-tide refinement.
Contents
- Why ADMESH
- Install
- Quickstart
- The pipeline
- Boundary types
- Status & roadmap
- Documentation
- Citation
- Upstream & related projects
- Contact
- License
Why ADMESH
For shallow-water modelers who need ADCIRC-ready meshes from Python:
- MATLAB-faithful port. 13 stages reproduced 1:1 from the OSU CHIL Lab
01_ADMESH_Library, with numerical agreement tracked by a 250+ test suite. Switching from MATLAB to this library does not change your meshes. - Native ADCIRC
fort.14I/O. Read, mesh, write — bit-faithful round-trip including paired-edge boundary records (IBTYPE 3 / 4 / 13 / 24). - Curvature + medial-axis + bathymetry + tide-aware sizing. Size field is a
min-stack of physical drivers, not a hand-tuned scalar. Custom contributions compose on top. - Pythonic surface, faithful internals.
Domain/Mesh/BoundarySegmentare frozen dataclasses with typed fields; the gnarly numerics stay inside the faithful-port modules and stay testable. - Cross-repo by design. Pairs with ADMESH-Domains (mesh registry) and the upstream MATLAB reference for lineage tracking.
Not the right tool if you need 3-D, anisotropic, or non-triangular elements — use gmsh for those.
Install
pip install admesh2D # core
pip install admesh2D[viz] # adds matplotlib for mesh.plot()
From source:
git clone https://github.com/domattioli/ADMESH.git
cd ADMESH
pip install -e ".[dev]"
Requires Python ≥ 3.10. Core deps: NumPy, SciPy, Numba, Shapely. The import name is admesh (the admesh2D on PyPI is the distribution name — the admesh namespace on PyPI is an unrelated STL library).
Install hiccups (Numba on Apple Silicon, SciPy wheels on older Python): see open issues and file a new one if you hit a fresh failure.
Quickstart
Built-in domain
import admesh
from admesh import domains
mesh = admesh.triangulate(domains.UNIT_DISK, h_max=0.1)
mesh.to_fort14("disk.14")
mesh is a frozen Mesh dataclass — typed nodes, elements, boundaries (each a BoundarySegment with a BoundaryType code), optional bathymetry, per-element quality.
Round-trip with ADCIRC fort.14
import admesh
mesh = admesh.read_fort14("input.14")
mesh.to_fort14("output.14")
assert mesh.equals(admesh.read_fort14("output.14")) # bit-faithful
Re-mesh an existing fort.14
import admesh
from admesh.api import Domain
source = admesh.read_fort14("coarse.14")
domain = Domain.from_mesh(source)
refined = admesh.triangulate(domain, h_max=500.0, h_min=50.0)
refined.to_fort14("refined.14")
Custom size-field contribution
import numpy as np
import admesh
def refine_near_breaker(pts: np.ndarray) -> np.ndarray:
return 50.0 + 0.2 * np.abs(pts[:, 0] - 1500.0)
mesh = admesh.triangulate(
"coast.14",
user_contribs=(refine_near_breaker,),
)
Built-in size-field stages (curvature, medial axis, bathymetry, tide) min-stack identically to MATLAB. User contributions compose on top via combine= (default: elementwise minimum).
Build a Domain directly from an SDF
import numpy as np
from admesh.api import Domain, triangulate
def sdf_disk(p: np.ndarray) -> np.ndarray:
return np.linalg.norm(p, axis=1) - 1.0
mesh = triangulate(Domain(sdf=sdf_disk, bbox=(-1, -1, 1, 1)), h_max=0.1)
The pipeline
Each call to triangulate(...) flows through the 13-stage ADMESH pipeline (faithful port of the MATLAB modules under 01_ADMESH_Library):
| # | Stage | Module | Purpose |
|---|---|---|---|
| 1 | Distance | admesh.distance |
Signed-distance grid from the domain SDF |
| 2 | Curvature | admesh.curvature |
Refines near sharp boundary curvature |
| 3 | Medial axis | admesh.medial_axis |
Adds sizing pressure in narrow channels |
| 4 | Bathymetry | admesh.bathymetry |
Element size scales with depth gradient |
| 5 | Dominant tide | admesh.dominate_tide |
Resolves tidal wavelength on the shelf |
| 6 | Boundary | admesh.boundary |
Enforces BC labels at boundary edges |
| 7 | Mesh size | admesh.mesh_size |
Numba-JIT iterative solver (min-stack) |
| 8 | distmesh2d | admesh.distmesh |
Truss-equilibrium point placement |
| 9 | Quality | admesh.quality |
Per-element shape metric, gate at q ≥ 0.3 |
| 10 | In-polygon | admesh.in_polygon |
Winding-number containment tests |
| 11 | Inpaint | admesh.inpaint |
Fills NaN holes in bathymetry / size grids |
| 12 | Background grid | admesh.background_grid |
Anisotropic background field |
| 13 | Valence | admesh.valence |
Edge-flip rebalancing (new in 0.2.0, issue #27) |
The Numba-JIT iterative solver replaces the C MEX from the MATLAB original — no compile step at install time.
Boundary types
BoundaryType is an IntEnum over the ADCIRC IBTYPE codes that the fort.14 reader/writer names. Unmapped codes round-trip as plain int on BoundarySegment.bc_type.
| Code | Name | Meaning |
|---|---|---|
| 0 | OPEN |
Open ocean / external water |
| 1 | MAINLAND (alias WALL) |
Mainland boundary, no normal flux |
| 11 | ISLAND |
Island boundary |
| 20 | MAINLAND_FLUX |
Mainland with specified normal flux |
| 3 / 4 / 13 / 24 | (preserved as int) |
Paired-edge / weir-type — read and written faithfully, not yet named in the enum |
| other | (preserved as int) |
Round-tripped, not interpreted |
from admesh import BoundaryType, read_fort14
mesh = read_fort14("coast.14")
for seg in mesh.boundaries:
if seg.bc_type == BoundaryType.ISLAND:
...
Status & roadmap
- Shipped (v0.2.1). Pythonic API + fort.14 round-trip + 13-stage faithful port + valence balancing + custom size-field hooks. Published to PyPI and archived on Zenodo.
- In flight. Spec 009 release-readiness (CI workflows, mkdocs site, stage-module reorg into
admesh/_stages/). Spec 008 Gmsh I/O. - Next. Default size-field stack consolidation, paired-edge IBTYPE 3 / 4 / 13 / 24 promoted to named
BoundaryTypemembers, downstream consumer migration (MADMESHR,CHILMESH).
Open epics live as labeled issues — see planning-required.
Documentation
- API reference: docstrings on
Domain,Mesh,BoundarySegment,triangulate,read_fort14,write_fort14, and the 13 stage modules. - Architecture + porting notes:
docs/(governance, persistence journal, porting notes, domain I/O). - Specs (design + acceptance criteria for each feature):
specs/. - Constitution (project principles + faithful-port invariants):
docs/governance/CONSTITUTION.md. - A mkdocs site with auto-generated API reference lands with spec 009 R3.
Citation
Algorithm / theory (cite the original paper):
Conroy, C.J., Kubatko, E.J., West, D.W. (2012). ADMESH: an advanced, automatic unstructured mesh generator for shallow water models. Ocean Dynamics 62, 1503–1517. https://doi.org/10.1007/s10236-012-0574-0
This software (cite the archived release):
Mattioli, D., Conroy, C.J., Kubatko, E.J., West, D.W. (2026). ADMESH: An advanced, automatic unstructured mesh generator for 2D shallow-water models (Python port). Zenodo. https://doi.org/10.5281/zenodo.20264101
The DOI 10.5281/zenodo.20264101 resolves to the latest release; version-specific DOIs are listed on the Zenodo record. A CITATION.cff is provided at the repo root for tools that consume it (GitHub's "Cite this repository" button, Zotero, etc.). Paper copy: papers/Conroy-2012-ADMESH.pdf.
Upstream & related projects
- coltonjconroy/ADMESH — reference MATLAB implementation, maintained by the original author. New functionality is pulled across as it lands upstream.
- ADMESH-Domains — federated registry of ADCIRC-compatible meshes for discovery, lineage tracking, and community contribution. Built as a companion to this library.
Contact
- Theory (algorithm, size-field formulation, ADCIRC integration): Ethan J. Kubatko — kubatko.3@osu.edu
- Python port (this repository): Dominik Mattioli — github.com/domattioli
License
Apache 2.0 — see LICENSE.
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 admesh2d-0.2.1.tar.gz.
File metadata
- Download URL: admesh2d-0.2.1.tar.gz
- Upload date:
- Size: 135.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd2dad968ead61c01fd82fc7e09fadffb32f810684663117a9ecd98eff9c8312
|
|
| MD5 |
40ec295e5ad117bf2620f584389e1241
|
|
| BLAKE2b-256 |
b7576a90f766e937a0c730df0905349ab8f0c9bf6e3b43a1d48cb736fd64e950
|
File details
Details for the file admesh2d-0.2.1-py3-none-any.whl.
File metadata
- Download URL: admesh2d-0.2.1-py3-none-any.whl
- Upload date:
- Size: 97.4 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 |
523ffb4a8a1fbdb09b0e029803ec83807ce54355ff3a3a7ed1db8e163734889b
|
|
| MD5 |
7ad119b5cd66182c3501a1ba32884c50
|
|
| BLAKE2b-256 |
d22bafdf9032ed788518659e5ef92d97187bf0cbf09ede54d2b9afaf41610dc1
|