SHORE — Structured Hyperbolic Overlapping Remeshing Engine
Project description
SHORE — Structured Hyperbolic Overlapping Remeshing Engine
Hyperbolic mesh generation for Chimera CFD — body-fitted near-body grids and parametric backgrounds, in one tool.
| 🏗️ Full Chimera assembly in one tool Generate every grid an overset assembly needs — body-fitted near-body meshes and parametric backgrounds — in the same world frame. Pack them into the Xall solver bundle (.grd + cc.par + marker boxes) without leaving the SHORE CLI. Pipeline walkthrough |
📐 Body-fitted near-body meshes Three topologies for surface inputs (STL today; CAD on the roadmap) — single-block O-grid, 6-block cubed sphere with gnomonic cap k=0 seed and C1 cap-equator seam pinning, and a single-block C-grid for sharp-TE bodies (airfoils, hydrofoils) with auto TE detection and downstream wake branches. One shore mesh call from a triangulated body to Xall-compatible .geo files. Cubed sphere |
| 🧱 Parametric backgrounds Box, annular cylinder, and 5-block flat-caps cylinder primitives with per-axis spacing laws — fill the far field without an STL. Per-edge spacing on Box and Annulus, transfinite-interpolation blends; flat-caps cylinder is Chimera-fringe-free for GPU-friendly backgrounds. Primitives |
🌊 Seam-aware hyperbolic marching Each wall-normal layer advances along outward normals computed with centred differences across multi-block seams (ghost rows from partner blocks). Spacing continuity across block edges holds layer by layer; per-layer Laplacian smoothing + Jacobian guard catch any cell inversion immediately. Algorithm |
| 🔍 Focused CLI Nineteen commands cover the full chimera pipeline — generate ( mesh, primitive), subdivide and balance for parallel solvers (split, balance), pack for the solver (grd, cc-par, proc-input, boxes-from-stl), merge multi-component runs (grd-merge, cc-par-merge, proc-input-merge), inspect (info, check), and visualise (export, view, boxes-export). A Rich progress bar shows per-layer Jacobians during marching. CLI reference |
🎨 ParaView and Jupyter visualization Export to VTK StructuredGrid ( shore export) and MultiBlock (.vtm) for ParaView with per-cell Jacobian colour maps and overlaid marker boxes. Or use shore view for an immediate PyVista window, or shore.vis directly in Jupyter notebooks with the HTML backend. API reference |
| ✅ Fully tested pipeline Pytest suite covers every CLI command, geometric correctness, Jacobian inversion detection, multi-block adjacency wiring, axis-map orientation, VTK export round-trip, and geo / grd / cc.par format fidelity. Contributing |
🆓 Free and open source Released under the MIT license. Pure Python — depends only on NumPy, trimesh, Typer, and Rich. PyVista is an optional dependency for visualization. No compiled extensions, no C++ meshing backends. |
What is SHORE?
SHORE produces every structured grid a Chimera (overset) CFD assembly needs and packages them for the solver. Two product lines, one tool:
- Body-fitted near-body meshes by hyperbolic normal extrusion of a body surface. Surface input is a triangulated STL today; CAD (STEP / IGES / BREP) is on the roadmap.
- Parametric backgrounds that fill the far field — no STL needed, just analytic geometry. Box, annular cylinder, and flat-caps cylinder primitives.
Hole cutting, fringe identification, and donor search are the solver's responsibility — SHORE produces every grid and every descriptor the solver needs, then steps out of the way.
# Body-fitted near-body mesh (default: 6-block cubed sphere)
shore mesh fuselage.stl --ni 60 --nj 80 --nk 40 --ds 1e-4 --growth 1.15 -o fuselage -v
# Single-block O-grid alternative (one .geo, j-periodic)
shore mesh fuselage.stl --topology ogrid --ni 60 --nj 80 --nk 40 -o fuselage
# C-grid for sharp-TE bodies (airfoil, hydrofoil) with downstream wake branches
shore mesh naca0012.stl --topology cgrid \
--ni-body 120 --ni-wake 30 --n-stations 5 --wake-length 15 \
--nk 30 --ds 5e-4 --growth 1.15 -o naca0012
# Parametric background — no STL needed
shore primitive flat-caps --r-out 10 --z0 -10 --z1 50 --ni 16 --nc 24 --nk 60 -o background
# Inspect
shore info fuselage_sub0.geo
shore check fuselage_sub0.geo
Quick start
Installation
pip install shore-mesh # distribution name on PyPI
# the import / CLI name stays `shore`:
# import shore
# shore --help
Or from source for development:
git clone https://github.com/szaghi/shore.git
cd shore
python -m venv .venv && source .venv/bin/activate
make dev # pip install -e ".[dev]"
make test # currently ~588 passing
Your first body-fitted mesh
Given a body surface sphere.stl, generate a 6-block cubed-sphere mesh with 40 equator latitude points, 60 longitude points, and 30 wall-normal layers:
shore mesh sphere.stl --ni 40 --nj 60 --nk 30 --ds 1e-3 --growth 1.15 -o sphere -v
The -v flag shows a live progress bar:
⠸ Loading STL ████████████████ 1/1 5,120 triangles 0:00:00
⠸ Marching ████████████████ 29/29 jmin=2.30e-05 0:00:00
✓ Wrote 6 .geo files (sub: 40x16x30, caps: 16x16x30)
Validate the result:
shore check sphere_sub0.geo
✓ All Jacobians positive.
Your first parametric background
No STL required — primitives build their nodes from analytic geometry:
# 5-block flat-caps cylinder (Chimera-fringe-free; central square + 4 trapezoidal sub-blocks)
shore primitive flat-caps --r-out 10 --z0 -10 --z1 50 --ni 16 --nc 24 --nk 60 -o background
# → background_center.geo, background_sub_e.geo, background_sub_n.geo,
# background_sub_w.geo, background_sub_s.geo
Other primitives:
shore primitive box --min -10 -10 -10 --max 10 10 50 --ni 30 --nj 30 --nk 60 -o domain
shore primitive annulus --r-in 1.5 --r-out 5 --z0 -2 --z1 2 --ni 30 --nj 64 --nk 40 -o buffer
Xall pipeline
Once each component (near-body and / or background) is generated, package it for the Xall solver:
# Pack each component into binary .grd
shore grd wall_*.geo -o wall.grd
shore grd background_*.geo -o background.grd
# Generate the chimera descriptor (consumed by overset preprocessor)
shore boxes-from-stl fuselage.stl --block sub0 --max-outward-gap 0.10 -o boxes.json
shore cc-par wall.adjacency.json wall.cc.par --grd wall.grd --boxes boxes.json
shore cc-par background.adjacency.json background.cc.par --grd background.grd --free-bc -9
# Generate the runtime work-distribution descriptor (consumed by Xall)
shore proc-input wall.grd wall.proc.input --np 16
shore proc-input background.grd background.proc.input --np 16
# Merge multi-component runs into a single Xall job
shore grd-merge background.grd wall.grd -o assembly.grd
shore cc-par-merge background.cc.par wall.cc.par -o assembly.cc.par --grd assembly.grd
shore proc-input-merge background.proc.input wall.proc.input -o assembly.proc.input
The full walkthrough — including the examples/05-chimera-assembly/chimera_assembly.py reference script — is at the cc.par + boxes pipeline guide.
CLI reference
Nineteen commands, grouped by purpose:
| Group | Commands |
|---|---|
| Mesh generation | shore mesh, shore primitive, shore project |
| Adjacency / parallelism | shore split, shore balance |
| Xall pipeline | shore grd, shore grd-merge, shore cc-par, shore cc-par-merge, shore proc-input, shore proc-input-merge, shore boxes-from-stl |
| Inspection | shore info, shore check |
| Visualisation | shore export, shore view, shore boxes-export |
| Configuration | shore config |
All commands accept --help for full option lists. See the CLI reference for full documentation.
Key options for shore mesh
| Option | Default | Description |
|---|---|---|
--topology |
cubed_sphere |
cubed_sphere (6 blocks), ogrid (1 block, j-periodic), or cgrid (1 block, sharp-TE body with wake branches) |
--ni |
40 | Latitude / equator meridional node count |
--nj |
60 | Longitude node count (multiple of 4 for cubed sphere) |
--nk |
30 | Wall-normal node count (includes the wall row at k=0; the marcher extrudes nk - 1 cells) |
--ds |
1e-3 | First-layer thickness (geometric spacing) |
--growth |
1.15 | Geometric growth ratio |
--theta-cap-deg |
30° | Polar exclusion angle (cubed sphere) |
--volume-k-spacing |
geometric |
geometric, tanh, or tanh2 |
--smooth |
0.2 | Laplacian smooth strength [0–1] |
--smooth-iters |
2 | Laplacian sweeps per layer |
-o / --output |
<stem> |
Output stem (multi-block writes <stem>_<label>.geo) |
-v / --verbose |
off | Rich progress bar |
Algorithm overview
Body-fitted: surface projection + hyperbolic marching
For body-fitted meshes, SHORE runs two stages:
-
Surface projection. The body's anchor (centroid by default) is the origin of a structured ray-cast onto the STL. The 6-block cubed sphere uses gnomonic flat-square cap projection at each pole + great-circle slerp meridians for the equator, with C1 step matching at every cap-equator seam vertex. The single-block O-grid uses a uniform lat-lon ray template. Both require the body to be star-shaped from the anchor.
-
Hyperbolic marching. Each wall-normal layer is computed as
$$P_{i,j}^{k+1} = P_{i,j}^{k} + \Delta s_k \cdot \hat{n}_{i,j}^{k}$$
where $\Delta s_k$ comes from the chosen spacing law (geometric, tanh, or tanh2) and $\hat{n}$ is the outward normal. At multi-block seams, the boundary tangent uses a centred difference against ghost rows from partner blocks instead of a one-sided fallback — this is the seam-aware kernel that keeps spacing continuous across block edges layer by layer. Per-layer Laplacian smoothing and a Jacobian guard catch any cell inversion immediately.
Parametric backgrounds
Primitives build their nodes from analytic geometry — no projection, no marching. Each axis has its own spacing law (uniform / tanh / tanh2); per-edge overrides on Box and Annulus produce a transfinite-interpolation blend between the four parallel edges. The 5-block flat-caps cylinder pins its radial and tangential distributions geometrically (central square + 4 trapezoidal sub-blocks with conforming SHARED seams).
Marker boxes for hole-cutting
For chimera assemblies, SHORE generates marker boxes from the body STL via voxel-fill + greedy AABB merge: voxelise the body's AABB, include every voxel that overlaps the body, then greedy-merge face-adjacent grid blocks into slab-shaped AABBs whenever the merged corners stay within the user's max_outward_gap budget. The output is a small slab cover that contains the body and fits inside the near-mesh — both invariants enforced by construction. See Algorithm — marker boxes.
Roadmap
- Body-fitted topologies: 6-block cubed sphere (production default) + single-block O-grid
- Parametric primitives: box, annular cylinder, 5-block flat-caps cylinder
- Gnomonic flat-square cap k=0 projection with C1 seam-step pinning
- Seam-aware hyperbolic marching (centred-difference normals across block seams)
- Per-edge spacing data model (
Spacing1D,Edge.first_step/last_step,pinnedlaw) - Adjacency JSON sidecar with
axis_maporientation - Xall pipeline:
.geo→.grd(shore grd), chimera descriptor (shore cc-par), marker boxes (shore boxes-from-stl) - Multi-component merge (
shore grd-merge,shore cc-par-merge) for Xall assemblies - PyVista visualization (
shore view,shore export,shore boxes-export,shore.vis) - GitHub Actions CI + VitePress documentation site
- CAD surface input (STEP / IGES / BREP via pythonOCC or cadquery)
- Multi-block surface decomposition for non-star-shaped bodies
- Steger–Sorenson orthogonality source term for high-curvature bodies
- Box-shaped outer-boundary morphing (alternative to background overlap)
- Other CFD formats (Plot3D, CGNS)
Authors
Stefano Zaghi · stefano.zaghi@cnr.it
Chief Yak Shaver, Accidental Research Scientist, and HPC Farmer — CFD researcher who decided that one more day debugging Fortran build systems was one day too many, opened a Python REPL "just to prototype," and now finds himself maintaining a meshing library, a chimera assembler, an MPI load balancer, and the seven blog tabs he keeps meaning to read.
Andrea Di Mascio · andrea.dimascio@univaq.it
Sommo Vate & Resident Gandalf — responsible for the deep CFD intuitions SHORE pretends to know.
Claude (Anthropic)
Omniscient Code Oracle & Tireless Rubber Duck — AI pair programmer, responsible for writing the boring parts so humans don't have to.
License
SHORE is released under the MIT 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 shore_mesh-0.1.0.tar.gz.
File metadata
- Download URL: shore_mesh-0.1.0.tar.gz
- Upload date:
- Size: 238.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7f07923c989a83b0870241c67d13274875b95daf0137d363604268b050e4ff5
|
|
| MD5 |
a13fe3f3732dd62ea0e81309ed8216b3
|
|
| BLAKE2b-256 |
912feecceae562f9bf83fb76262969e8824b98ae5f47cb582d17106f5643c79c
|
Provenance
The following attestation bundles were made for shore_mesh-0.1.0.tar.gz:
Publisher:
python-package.yml on szaghi/shore
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shore_mesh-0.1.0.tar.gz -
Subject digest:
a7f07923c989a83b0870241c67d13274875b95daf0137d363604268b050e4ff5 - Sigstore transparency entry: 1409271470
- Sigstore integration time:
-
Permalink:
szaghi/shore@a759dc71e3e7a178163a8d6e3d35b14742f6cd27 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/szaghi
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-package.yml@a759dc71e3e7a178163a8d6e3d35b14742f6cd27 -
Trigger Event:
push
-
Statement type:
File details
Details for the file shore_mesh-0.1.0-py3-none-any.whl.
File metadata
- Download URL: shore_mesh-0.1.0-py3-none-any.whl
- Upload date:
- Size: 181.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c72c8ba73b14afeb19829342b5acf6fa877df33baf7c26dcd574e2ed7b5d2d03
|
|
| MD5 |
24b01a0e866473e024de788c8005c939
|
|
| BLAKE2b-256 |
4036facdbd5e867e01520781dc0fa2dc4f48ba5ab59c8f3f8615bb059a37253a
|
Provenance
The following attestation bundles were made for shore_mesh-0.1.0-py3-none-any.whl:
Publisher:
python-package.yml on szaghi/shore
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shore_mesh-0.1.0-py3-none-any.whl -
Subject digest:
c72c8ba73b14afeb19829342b5acf6fa877df33baf7c26dcd574e2ed7b5d2d03 - Sigstore transparency entry: 1409271476
- Sigstore integration time:
-
Permalink:
szaghi/shore@a759dc71e3e7a178163a8d6e3d35b14742f6cd27 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/szaghi
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-package.yml@a759dc71e3e7a178163a8d6e3d35b14742f6cd27 -
Trigger Event:
push
-
Statement type: