diff --git a/.domi-pin b/.domi-pin index afd29d8..60ccd95 100644 --- a/.domi-pin +++ b/.domi-pin @@ -4,6 +4,6 @@ upstream: domattioli/DomI branch: main -sha: 69b073dd5888411aef5c7e7f4ad30e557fd6f057 -manifest_sha256: 9d57d1fd6f468969892bc87017f0021647a6ed91f61c40ee544801b23914f014 -pinned_at: 2026-06-15T10:07:23Z +sha: a9b240f2d6f2158e2273da46a800af3ff70c6132 +manifest_sha256: 8e928b85a6aa6b7e3869cb3d04832eb2b2576a9a343e5cf4a92ad7890782cb75 +pinned_at: 2026-06-15T18:08:55Z diff --git a/specs/001-boundary-type-seed-skeletonize/checklists/requirements.md b/.specify/specs/001-boundary-type-seed-skeletonize/checklists/requirements.md similarity index 100% rename from specs/001-boundary-type-seed-skeletonize/checklists/requirements.md rename to .specify/specs/001-boundary-type-seed-skeletonize/checklists/requirements.md diff --git a/specs/001-boundary-type-seed-skeletonize/spec.md b/.specify/specs/001-boundary-type-seed-skeletonize/spec.md similarity index 100% rename from specs/001-boundary-type-seed-skeletonize/spec.md rename to .specify/specs/001-boundary-type-seed-skeletonize/spec.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b5b4fd..8587071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/). +## [1.2.2] — 2026-06-15 + +### Changed +- Renamed registry references `ADMESH-Domains` → `Valence` / `valence-domains` (registry was renamed). Public API names (`from_admesh_domain`, `admesh_metadata`) unchanged. +- Removed internal design proposals from the published source tree. + ## [1.2.0] — 2026-05-24 ### ✨ Added @@ -88,7 +94,7 @@ and the project adheres to [Semantic Versioning](https://semver.org/). ## [1.0.0] — 2026-05-22 First **stable** release. CHILmesh is now the production backbone for ADMESH, -MADMESHR, and ADMESH-Domains. +MADMESHR, and Valence. ### 🚀 Headline @@ -441,7 +447,7 @@ These numbers carry forward unchanged into v0.4.0 — Phase 5 spatial queries an #### Enhanced Test Coverage - `test_skeletonization_invariant.py`: Layer separation invariant validation across all fixtures - `test_skeletonization_matlab_parity.py`: MATLAB reference layer count validation -- `test_skeletonization_matlab_parity_external.py`: External ADMESH-Domains catalog parity validation +- `test_skeletonization_matlab_parity_external.py`: External Valence catalog parity validation - `test_smoothing.py`: Comprehensive FEM smoother tests for triangles, quads, and mixed-element meshes ## [0.2.0] — 2026-04-27 (Modernization Release) @@ -510,7 +516,7 @@ pinches = mesh.pinch_points(width_threshold=0.3) #### Documentation & Release Infrastructure - `API.md` - Complete 25+ method reference with stability guarantees - `BENCHMARK.md` - Performance comparison v0.1.1 vs v0.2.0 with real-world impact -- `DOWNSTREAM_MIGRATION_GUIDE.md` - Integration guide for MADMESHR, ADMESH, ADMESH-Domains +- `DOWNSTREAM_MIGRATION_GUIDE.md` - Integration guide for MADMESHR, ADMESH, Valence - `docs/CHILmesh_Access_Interface.md` - Stability guarantees and usage patterns - Stable API contract (CAI) through v1.0 diff --git a/README.md b/README.md index 4504514..2b287e5 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ ## Why CHILmesh -**The stable backbone for hydrodynamic mesh tooling.** Sibling projects [ADMESH](https://github.com/domattioli/ADMESH), [ADMESH-Domains](https://github.com/domattioli/ADMESH-Domains), and [QuADMesh](https://github.com/domattioli/QuADMesh) build on top of it. +**The stable backbone for hydrodynamic mesh tooling.** Sibling projects [ADMESH](https://github.com/domattioli/ADMESH), [Valence](https://github.com/domattioli/Valence), and [QuADMesh](https://github.com/domattioli/QuADMesh) build on top of it. - **Pythonic API** — `from chilmesh import Mesh`; backwards-compatible `CHILmesh` alias 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](tests/test_backend_equivalence.py). @@ -77,7 +77,20 @@ The legacy `chilmesh.CHILmesh` import is preserved for backward compatibility. B - **I/O** — [ADCIRC](https://adcirc.org/) `.fort.14` and [SMS Aquaveo](https://www.aquaveo.com/sms) `.2dm` read/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](https://github.com/domattioli/CHILmesh/issues/94) -- **ADMESH-Domains integration** — `from_admesh_domain()` adapter +- **Valence 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`](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](https://github.com/domattioli/CHILmesh/issues/163)). Absolute times are machine-dependent; full methodology and the regenerating harness: [`docs/BENCHMARK.md`](docs/BENCHMARK.md). ### Performance @@ -100,7 +113,7 @@ Reference workload: WNAT_Hagen (52,774 vertices · 98,365 elements · 151,248 ed ### 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. +Python, C++, and the original MATLAB/Octave implementation all produce identical `n_layers` (medial-axis skeletonization) across the Valence 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 | |---|--:|--:|--:|--:|--:|:--:| @@ -182,7 +195,7 @@ CHILmesh is the core engine for the ADCIRC mesh ecosystem. Sibling projects buil | Repo | Role | |---|---| | [ADMESH](https://github.com/domattioli/ADMESH) | Unstructured triangle mesh generator; consumes CHILmesh for adjacency, smoothing, and quality analysis | -| [ADMESH-Domains](https://github.com/domattioli/ADMESH-Domains) | Curated ADCIRC mesh registry; `Mesh.from_admesh_domain()` reads from it directly | +| [Valence](https://github.com/domattioli/Valence) | Curated ADCIRC mesh registry; `Mesh.from_admesh_domain()` reads from it directly | | [QuADMesh](https://github.com/domattioli/QuADMesh) | Quad mesh generator (MATLAB → Python port, in progress); CHILmesh data structure descends from the original QuADMesh+ | | [MADMESHing](https://github.com/domattioli/MADMESHing) | Benchmark harness comparing ADMESH triangulation vs quad generators; uses CHILmesh for quality analysis | diff --git a/docs/API.md b/docs/API.md index 251af34..f364000 100644 --- a/docs/API.md +++ b/docs/API.md @@ -61,7 +61,7 @@ success = mesh.write_to_fort14("output.fort.14", grid_name="My Mesh") #### `from_admesh_domain(record, compute_layers: bool = True) -> CHILmesh` **Stability:** Stable | **Complexity:** O(n log n) -Load mesh from ADMESH-Domains catalog record (duck-typed). +Load mesh from Valence catalog record (duck-typed). --- diff --git a/docs/BENCHMARK.md b/docs/BENCHMARK.md index e450d10..c9fab3c 100644 --- a/docs/BENCHMARK.md +++ b/docs/BENCHMARK.md @@ -276,14 +276,14 @@ Total: 14.7s ✅ Interactive development ## How to Reproduce ```bash -git clone https://github.com/domattioli/ADMESH-Domains /tmp/admesh-domains +git clone https://github.com/domattioli/Valence /tmp/valence-domains python3 << 'PYTHON' from chilmesh import CHILmesh from pathlib import Path import time -mesh_path = Path("/tmp/admesh-domains/registry_data/meshes/WNAT_Hagen.14") +mesh_path = Path("/tmp/valence-domains/registry_data/meshes/WNAT_Hagen.14") start = time.time() mesh = CHILmesh.read_from_fort14(mesh_path, compute_layers=False) diff --git a/docs/CHIL_FORMAT_INVESTIGATION.md b/docs/CHIL_FORMAT_INVESTIGATION.md index bc2c7e0..598fe3e 100644 --- a/docs/CHIL_FORMAT_INVESTIGATION.md +++ b/docs/CHIL_FORMAT_INVESTIGATION.md @@ -17,7 +17,7 @@ already built, and what the object model is still missing. | ADCIRC `fort.14` (`.14`/`.fort14`) | ✅ | ✅ | `CHILmesh.read_from_fort14`, `write_to_fort14`, module `write_fort14` | | SMS `.2dm` | ✅ | ✅ (private `_write_2dm`) | `CHILmesh.read_from_2dm`, `_write_2dm` | | Gmsh `.msh` (v2.2 + v4.1) | ✅ | ✅ | `gmsh_io.read_msh`/`write_msh`, `CHILmesh.read_from_msh`/`write_to_msh` | -| ADMESH-Domains registry record | ✅ | — | `CHILmesh.from_admesh_domain(record)` | +| Valence registry record | ✅ | — | `CHILmesh.from_admesh_domain(record)` | | `.chil` | ❌ | ❌ | **none — does not exist anywhere in `src/`** | **Unified dispatch already exists.** `CHILmesh.save(filename)` and @@ -60,7 +60,7 @@ same three things the fort.14 writer already emits, plus the new metadata below. | Native CRS declaration (Q8) | ❌ | No CRS field; Principle V makes coords **opaque** → direct conflict (#154 D9 HIGH) | | Domain Boundary distinct from Mesh Boundary (Q11) | ❌ | Only `boundary_segments` (mesh edges) exist; no domain-outline concept | | `fort.13` nodal attributes for lossless mesh round-trip (Q11) | ❌ | No fort.13 read/write anywhere → "lossless fort.14+fort.13" unmet | -| Deterministic content hash / `content_uid` (Q15) | ❌ | No hashing in CHILmesh (lives in ADMESH-Domains schema, not here) | +| Deterministic content hash / `content_uid` (Q15) | ❌ | No hashing in CHILmesh (lives in Valence schema, not here) | | Multi-ring boundary (holes, Bermuda) (Q10/Q11) | partial | boundary_segments can list multiple rings, but no canonical winding/start-vertex normalization | | Quantization to fixed grid (Q9) | ❌ | No coordinate quantization step | @@ -94,7 +94,7 @@ If/when the RESHAPE blockers clear, integration is **localized**: - Principle VI (format pluralism) vs `.chil` as *canonical* — promoting one format is exactly what VI forbids; CHILmesh should treat `.chil` as **one more readable/writable adapter**, not privileged. Registry-canonical is an - ADMESH-Domains decision, not a CHILmesh one. + Valence decision, not a CHILmesh one. - fort.13 nodal-attribute round-trip is a prerequisite for `kind="mesh"` losslessness and is entirely unbuilt. @@ -108,7 +108,7 @@ If/when the RESHAPE blockers clear, integration is **localized**: recorded as `native = "unknown"`/passthrough (no transform — respects Principle V). No Identity hash, no WGS84 transform. This is a pure additive adapter, no constitution amendment required. -2. **Defer the Identity/CRS/Domain-Boundary half** to ADMESH-Domains where the +2. **Defer the Identity/CRS/Domain-Boundary half** to Valence where the registry, hashing, and curation already live (#154 D6/D9/D15 put the heavy deps — shapely/pyproj/numpy — on the registry side, which CHILmesh's minimal base install should not absorb). diff --git a/docs/CHILmesh_Access_Interface.md b/docs/CHILmesh_Access_Interface.md index 08b428b..aff1e79 100644 --- a/docs/CHILmesh_Access_Interface.md +++ b/docs/CHILmesh_Access_Interface.md @@ -8,7 +8,7 @@ ## Executive Summary -**CAI** defines stable, documented public API that downstream projects (MADMESHR, ADMESH, ADMESH-Domains) can depend on. All methods listed here maintain signatures, return types, and semantics through v1.0. Breaking changes require major version bump + minimum 2-week advance notice. +**CAI** defines stable, documented public API that downstream projects (MADMESHR, ADMESH, Valence) can depend on. All methods listed here maintain signatures, return types, and semantics through v1.0. Breaking changes require major version bump + minimum 2-week advance notice. --- @@ -127,7 +127,7 @@ def read_from_2dm(full_file_name: Path, compute_layers: bool = True) -> "CHILmes @staticmethod def from_admesh_domain(record, compute_layers: bool = True) -> "CHILmesh": """ - Create from ADMESH-Domains catalog record (duck-typed, zero imports). + Create from Valence catalog record (duck-typed, zero imports). Record must have 'fort14_path' attribute. """ @@ -145,7 +145,7 @@ def copy(self) -> "CHILmesh": def admesh_metadata(self) -> Dict[str, Any]: """ - ADMESH-Domains compatible metadata. + Valence compatible metadata. Returns: node_count, element_count, element_type ('tri'/'quad'/'mixed'), bounding_box. """ ``` diff --git a/docs/DOWNSTREAM_MIGRATION_GUIDE.md b/docs/DOWNSTREAM_MIGRATION_GUIDE.md index a315708..15daa76 100644 --- a/docs/DOWNSTREAM_MIGRATION_GUIDE.md +++ b/docs/DOWNSTREAM_MIGRATION_GUIDE.md @@ -2,7 +2,7 @@ **Version:** 2.0 (revised for CHILmesh v1.0.0) **CHILmesh Version:** 1.0.0+ -**Target Projects:** MADMESHR, ADMESH, ADMESH-Domains +**Target Projects:** MADMESHR, ADMESH, Valence --- @@ -173,7 +173,7 @@ print(f"Mean quality: {report['mean']:.3f}") print(f"Poor elements: {report['poor_count']}") ``` -### ADMESH-Domains Quick Start +### Valence Quick Start #### Before (v0.1.1) ```python @@ -406,7 +406,7 @@ report = adapter.get_mesh_quality_report() angle_summary = adapter.get_element_angles_summary() ``` -### ADMESH-Domains: Domain Decomposition +### Valence: Domain Decomposition **Relevant CAI Methods:** ```python @@ -435,7 +435,7 @@ Include: - Python version: `python --version` - Minimal reproducible example - Full error traceback -- Downstream project name (MADMESHR/ADMESH/ADMESH-Domains) +- Downstream project name (MADMESHR/ADMESH/Valence) Report at: https://github.com/domattioli/CHILmesh/issues @@ -443,7 +443,7 @@ Report at: https://github.com/domattioli/CHILmesh/issues ## Version Compatibility -| CHILmesh | MADMESHR | ADMESH | ADMESH-Domains | Notes | +| CHILmesh | MADMESHR | ADMESH | Valence | Notes | |----------|----------|--------|----------------|-------| | 0.1.1 | ✅ Legacy | ✅ Legacy | ✅ Legacy | Old version, still works | | 0.2.0 | ✅ Recommended | ✅ Recommended | ✅ Recommended | Current, use this | @@ -479,7 +479,7 @@ None required. Migration completely optional. See `examples/` directory for complete working examples: - `madmeshr_refinement.py` - MADMESHR mesh adaptation workflow - `admesh_quality.py` - ADMESH quality assessment -- `admesh_domains_setup.py` - ADMESH-Domains domain initialization +- `admesh_domains_setup.py` - Valence domain initialization --- diff --git a/docs/gallery/benchmark.json b/docs/gallery/benchmark.json index 7209883..8f15a26 100644 --- a/docs/gallery/benchmark.json +++ b/docs/gallery/benchmark.json @@ -2,7 +2,7 @@ "chilmesh_version": "0.4.1", "python": "3.11.15", "os": "Linux x86_64", - "mesh": "/tmp/admesh-domains/registry_data/meshes/WNAT_Hagen.14", + "mesh": "/tmp/valence-domains/registry_data/meshes/WNAT_Hagen.14", "init": { "fast_init_s": 1.2139215900000409, "full_init_s": 4.567989638999961, diff --git a/docs/gallery/benchmark.log b/docs/gallery/benchmark.log index 68d74e3..e0c2fc8 100644 --- a/docs/gallery/benchmark.log +++ b/docs/gallery/benchmark.log @@ -1,3 +1,3 @@ -ERROR: WNAT_Hagen mesh not found. Clone ADMESH-Domains: - git clone https://github.com/domattioli/ADMESH-Domains /tmp/admesh-domains +ERROR: WNAT_Hagen mesh not found. Clone Valence: + git clone https://github.com/domattioli/Valence /tmp/valence-domains then re-run this script. diff --git a/docs/introspections/development_c7a581c.md b/docs/introspections/development_c7a581c.md new file mode 100644 index 0000000..e5bdfd1 --- /dev/null +++ b/docs/introspections/development_c7a581c.md @@ -0,0 +1,44 @@ + +--- +date: 2026-06-15 +session: 2026-06-15T18Z-rotation +repo: domattioli/CHILmesh +severity: low +freq: recurring +issues: [168, 196, 214, 48] +wasted_min: 3 +wasted_tok: 2000 +missing_skill: null +--- + +# Session Handoff — CHILmesh · development_c7a581c · 2026-06-15 (rotation hour-18) + +**Task:** rotation maintenance track — C spec-048 slice shipped prior; queue + pin +**Phase:** maintenance +**Progress:** complete — pin synced, docstring defect fixed, coordination triaged, divergence flagged +**Branch:** development (new rolling PR #213; #210 operator-merged 16:25Z) +**Duration:** ~25 min +**Tool failures:** 0 +**Outcome:** complete + +## Pre-flight +- branch_policy_conflict: caught_and_resolved +- domi_pin_drift: caught_and_synced +- caveman_plugin: NOT loaded at boot → Unknown skill → emulated from CLAUDE.md; marketplace connected mid-session → re-attempt /caveman:caveman ultra succeeded (DomI#268 race, expected) + +## What shipped (evidence) +- chore pin sync `69b073d → a9b240f` (`a3a22f7`). drift gate closed. +- docs dedup `#168` note in `direct_smoother` docstring — pasted twice verbatim, removed dup, logic untouched, AST parse clean (`c7a581c`). +- coordination triage #196 item 1: QuADMesh→CHILmesh API gaps #132/#133/#134/#138/#139 all CLOSED+completed, consumed downstream → item 1 resolved. items 2/3 remain. +- filed #214: introspect-v2 migration incomplete on development (28 deprecated docs/introspections records main deleted via #212 + write-target contradiction: CHILmesh pull-only, cannot write DomI .introspect/CHILmesh/). operator/governance. + +## Pains (→ matrix, no new request:skill per #203) +- introspect-v2-downstream-write-target-contradiction: downstream repo sessions have no compliant path to DomI central corpus (pull-only + no-cross-repo-write). deprecated dir regrows each session. routed to #214. severity med, freq recurring. +- caveman-cold-start-race: DomI#268, known. low. +- domi-pin-drift-each-rotation: mechanical sibling-clone sync each slot. low, recurring. + +## Next slot (hour-2/10 CHILmesh) +- watch #214 for operator decision on introspect-v2 sweep before merging #213. +- #196 items 2 (canonical layer-path traversal standalone fn) + 3 (API-stability contract) open coordination. +- #163 status:blocked (Rust array n_layers=2 / C++ editable stub) — needs build env. +- env: no send_later/remote MCP → cannot arm 1h self-check-in; PR #213 webhook covers CI-fail/review wake. diff --git a/pyproject.toml b/pyproject.toml index e8d1773..fdfe9b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "chilmesh" -version = "1.2.1" +version = "1.2.2" description = "Fast 2D mesh library for hydrodynamic domains — Python API with optional C++ acceleration" authors = [{name = "Dominik Mattioli"}] license = {text = "PolyForm Noncommercial License 1.0.0"} diff --git a/scripts/benchmark_all_backends.py b/scripts/benchmark_all_backends.py index 4269d4b..84823e3 100644 --- a/scripts/benchmark_all_backends.py +++ b/scripts/benchmark_all_backends.py @@ -23,7 +23,7 @@ def _fmt(seconds: float, unit: str = "s") -> str: def _locate_mesh(explicit: str | None) -> Path: candidates = [ explicit, - "/tmp/admesh-domains/registry_data/meshes/WNAT_Hagen.14", + "/tmp/valence-domains/registry_data/meshes/WNAT_Hagen.14", "/tmp/WNAT_Hagen.14", str(Path.home() / "WNAT_Hagen.14"), ] diff --git a/scripts/benchmark_quadegg_variants.py b/scripts/benchmark_quadegg_variants.py index 8683521..2d0dfa9 100755 --- a/scripts/benchmark_quadegg_variants.py +++ b/scripts/benchmark_quadegg_variants.py @@ -24,7 +24,7 @@ BACKENDS = ['edgemap', 'halfedge', 'quadegg'] OPERATIONS = ['fast_init', 'full_init', 'quality_analysis', 'query_latency'] -WNAT_HAGEN_PATH = "/tmp/admesh-domains/registry_data/meshes/WNAT_Hagen.14" +WNAT_HAGEN_PATH = "/tmp/valence-domains/registry_data/meshes/WNAT_Hagen.14" def measure_operation(op_name: str, op_fn, n_trials: int = 2) -> Tuple[float, float, float]: diff --git a/scripts/benchmark_wnat_hagen.py b/scripts/benchmark_wnat_hagen.py index a1f1cd8..aaa61a5 100644 --- a/scripts/benchmark_wnat_hagen.py +++ b/scripts/benchmark_wnat_hagen.py @@ -5,7 +5,7 @@ python scripts/benchmark_wnat_hagen.py [MESH_PATH] [--json OUTPUT.json] If MESH_PATH is omitted the script looks for the mesh in the default -ADMESH-Domains clone location (/tmp/admesh-domains/registry_data/meshes/). +Valence clone location (/tmp/valence-domains/registry_data/meshes/). Outputs a markdown table suitable for pasting into docs/BENCHMARK.md and, optionally, a JSON file for CI archival / diff-over-time comparisons. @@ -47,17 +47,17 @@ def _measure(label: str, fn, *, n: int = 1) -> tuple[str, float]: def _locate_mesh(explicit: str | None) -> Path: candidates = [ explicit, - "/tmp/admesh-domains/registry_data/meshes/WNAT_Hagen.14", - "/tmp/admesh-domains/WNAT_Hagen.14", + "/tmp/valence-domains/registry_data/meshes/WNAT_Hagen.14", + "/tmp/valence-domains/WNAT_Hagen.14", str(Path.home() / "WNAT_Hagen.14"), ] for c in candidates: if c and Path(c).exists(): return Path(c) raise FileNotFoundError( - "WNAT_Hagen mesh not found. Clone ADMESH-Domains:\n" - " git clone https://github.com/domattioli/ADMESH-Domains " - "/tmp/admesh-domains\n" + "WNAT_Hagen mesh not found. Clone Valence:\n" + " git clone https://github.com/domattioli/Valence " + "/tmp/valence-domains\n" "then re-run this script." ) diff --git a/scripts/generate_wnat_showcase.py b/scripts/generate_wnat_showcase.py index f099f76..268110c 100644 --- a/scripts/generate_wnat_showcase.py +++ b/scripts/generate_wnat_showcase.py @@ -8,7 +8,7 @@ - ``--mesh /path/to/WNAT_Hagen.14``, or - environment variable ``WNAT_HAGEN_PATH``, or -- ADMESH-Domains catalog at ``/tmp/admesh-domains/registry_data/meshes/WNAT_Hagen.14``. +- Valence catalog at ``/tmp/valence-domains/registry_data/meshes/WNAT_Hagen.14``. If none of those resolve, falls back to the largest bundled fixture (``block_o``) so the script always produces an image; caption in the @@ -30,8 +30,8 @@ def _candidate_paths() -> list[Path]: env = os.environ.get("WNAT_HAGEN_PATH") if env: out.append(Path(env)) - out.append(Path("/tmp/admesh-domains/registry_data/meshes/WNAT_Hagen.14")) - out.append(Path.home() / "admesh-domains/registry_data/meshes/WNAT_Hagen.14") + out.append(Path("/tmp/valence-domains/registry_data/meshes/WNAT_Hagen.14")) + out.append(Path.home() / "valence-domains/registry_data/meshes/WNAT_Hagen.14") return out diff --git a/src/chilmesh/CHILmesh.py b/src/chilmesh/CHILmesh.py index aac5075..4971dfc 100644 --- a/src/chilmesh/CHILmesh.py +++ b/src/chilmesh/CHILmesh.py @@ -29,14 +29,14 @@ class CHILmesh(CHILmeshPlotMixin): A 2D mesh class supporting triangular, quadrilateral, and mixed-element meshes. Supports multiple file formats (ADCIRC `.fort.14`, SMS `.2dm`) and integrates - with ADMESH-Domains catalog. Provides mesh analysis (layer structure, element + with Valence catalog. Provides mesh analysis (layer structure, element quality, interior angles), geometric operations (smoothing), and fast metadata queries for bulk loading. Key Features: - Element Types: Triangles, quads, and mixed-element meshes (padded convention) - Fast Init: Optional skeletonization for <2s bulk loading (compute_layers=False) - - Metadata: Node count, element count, element type, bounding box (ADMESH-Domains compatible) + - Metadata: Node count, element count, element type, bounding box (Valence compatible) - Entry Point: CHILmesh.from_admesh_domain() for catalog integration (duck-typed, zero deps) - File I/O: Read ADCIRC `.fort.14` and SMS `.2dm` formats; roundtrip lossless - Analysis: Layers (skeletonization), element quality, interior angles @@ -84,7 +84,7 @@ class CHILmesh(CHILmeshPlotMixin): >>> elem_ids = mesh.edge2elem(edge_id) Examples: - Load from ADMESH-Domains catalog: + Load from Valence catalog: mesh = CHILmesh.from_admesh_domain(record) Fast metadata query: @@ -1992,14 +1992,6 @@ def direct_smoother(self, kinf=1e12, freeze_quad_nodes: bool = False) -> np.ndar original sizing. For size-respecting smoothing, supply anisotropic targets (not yet implemented) or run a separate sizing pass afterward. - Note (size-field behavior, #168): this smoother is **isotropic**. The - Balendran stiffness targets a uniform equilateral triangle (60 deg) / - square quad (90 deg) and takes **no size-field input** — it equalizes - element *shape*, not *size*. Applied to a graded mesh it grows fine - (e.g. coastal) edges and shrinks coarse (offshore) edges, eroding the - original sizing. For size-respecting smoothing, supply anisotropic - targets (not yet implemented) or run a separate sizing pass afterward. - Parameters: kinf: Large stiffness value for fixed (pinned) vertices. freeze_quad_nodes: When True, pin every vertex that is a corner of any @@ -2270,9 +2262,9 @@ def copy( self ) -> "CHILmesh": def admesh_metadata(self) -> dict: """ - Return a metadata dictionary compatible with the ADMESH-Domains catalog schema. + Return a metadata dictionary compatible with the Valence catalog schema. - The returned dict contains all fields that ADMESH-Domains expects from a + The returned dict contains all fields that Valence expects from a mesh record: node count, element count, element type, and bounding box. Designed to be callable on a ``compute_layers=False`` mesh for fast bulk loading. @@ -2307,7 +2299,7 @@ def admesh_metadata(self) -> dict: @classmethod def from_admesh_domain(cls, record: object, compute_layers: bool = True, compute_adjacencies: Opt[bool] = None) -> "CHILmesh": """ - Construct a CHILmesh from an ADMESH-Domains catalog record. + Construct a CHILmesh from an Valence catalog record. The catalog record is duck-typed: any object with ``connectivity`` (ndarray, n_elems × 3|4) and ``points`` (ndarray, n_verts × 2|3) @@ -2341,7 +2333,7 @@ def from_admesh_domain(cls, record: object, compute_layers: bool = True, compute if not filepath.exists(): raise FileNotFoundError( f"File not found: {filepath}. " - "If using ADMESH-Domains, call mesh_record.load() first." + "If using Valence, call mesh_record.load() first." ) record_type = getattr(record, "type", None) diff --git a/src/chilmesh/bridge.py b/src/chilmesh/bridge.py index b8939ab..7b33066 100644 --- a/src/chilmesh/bridge.py +++ b/src/chilmesh/bridge.py @@ -1,7 +1,7 @@ """Bridge adapters for downstream projects. This module provides convenient interfaces for integrating CHILmesh -with MADMESHR, ADMESH, and ADMESH-Domains. Each adapter adds +with MADMESHR, ADMESH, and Valence. Each adapter adds domain-specific convenience methods while delegating to the base CHILmesh public API (CAI). """ @@ -270,10 +270,10 @@ def get_element_angles_summary(self, elem_ids: Optional[List[int]] = None) -> Di class MeshAdapterForADMESHDomains: """ - Adapter for ADMESH-Domains multi-domain handling. + Adapter for Valence multi-domain handling. Provides convenience methods for domain-level queries and - boundary extraction specific to ADMESH-Domains. + boundary extraction specific to Valence. Example: >>> from chilmesh import CHILmesh diff --git a/tests/TESTING.md b/tests/TESTING.md index 23db164..1ec3381 100644 --- a/tests/TESTING.md +++ b/tests/TESTING.md @@ -153,7 +153,7 @@ pytest -vv -s tests/test_smoothing.py::TestTriangleSmoother::test_fem_smoother_t ## Known Issues & Skipped Tests **52 tests skipped (fast PR mode).** Skips are environment- or geometry-conditional, not failures: -- **External MATLAB parity** (`test_skeletonization_matlab_parity_external.py`): require `admesh-domains` + large mesh files not bundled. Run manually: `pip install admesh-domains && pytest tests/test_skeletonization_matlab_parity_external.py -v` +- **External MATLAB parity** (`test_skeletonization_matlab_parity_external.py`): require `valence-domains` + large mesh files not bundled. Run manually: `pip install valence-domains && pytest tests/test_skeletonization_matlab_parity_external.py -v` - **C++ backend equivalence** (`test_backend_equivalence.py`): skipped when `chilmesh_cpp` extension is not built (`pip install -e ".[cpp]"` or build the extension to exercise these). - **Geometry-conditional** (e.g. `test_spatial_indexing.py`): point-location cases that don't apply to holed fixtures (annulus/donut/block_o). diff --git a/tests/test_admesh_metadata.py b/tests/test_admesh_metadata.py index 5f3937c..5b3b95d 100644 --- a/tests/test_admesh_metadata.py +++ b/tests/test_admesh_metadata.py @@ -5,7 +5,7 @@ class TestADMESHMetadataAccuracy: - """Test that admesh_metadata() returns accurate, ADMESH-Domains-compatible values.""" + """Test that admesh_metadata() returns accurate, Valence-compatible values.""" @pytest.mark.parametrize("fixture_name", ["annulus", "donut", "block_o", "structured", "quad_2x2"]) def test_metadata_completeness(self, fixture_name): diff --git a/tests/test_bridge_adapters.py b/tests/test_bridge_adapters.py index 8fd36e4..3d72f7d 100644 --- a/tests/test_bridge_adapters.py +++ b/tests/test_bridge_adapters.py @@ -1,6 +1,6 @@ """Integration tests for bridge adapters. -Tests verify that bridge adapters (MADMESHR, ADMESH, ADMESH-Domains) +Tests verify that bridge adapters (MADMESHR, ADMESH, Valence) work correctly with realistic downstream workflows and all mesh fixtures. """ @@ -215,7 +215,7 @@ def _load_fixture(self, name): class TestADMESHDomainsBridge: - """Integration tests for ADMESH-Domains bridge adapter.""" + """Integration tests for Valence bridge adapter.""" @pytest.mark.parametrize("fixture_name", ["annulus", "donut", "structured"]) def test_adapter_initialization(self, fixture_name): @@ -392,7 +392,7 @@ def test_admesh_quality_assessment_workflow(self): assert angles["elements_with_acute"] >= 0 def test_admesh_domains_multi_domain_setup(self): - """Simulate ADMESH-Domains domain initialization.""" + """Simulate Valence domain initialization.""" from pathlib import Path mesh = CHILmesh.read_from_fort14( diff --git a/tests/test_metadata_validation.py b/tests/test_metadata_validation.py index 6117463..09948a8 100644 --- a/tests/test_metadata_validation.py +++ b/tests/test_metadata_validation.py @@ -133,7 +133,7 @@ def test_bounding_box_precision(self): def test_metadata_via_from_admesh_domain_for_validation(self): """Test contributor validation via from_admesh_domain entry point.""" - # Contributor receives a mesh record from ADMESH-Domains + # Contributor receives a mesh record from Valence fixture_path = chilmesh.examples.fixture_path("quad_2x2.fort.14") record = SimpleNamespace(filename=str(fixture_path), type="ADCIRC") diff --git a/tests/test_skeletonization_matlab_parity.py b/tests/test_skeletonization_matlab_parity.py index 58f97b3..1844a27 100644 --- a/tests/test_skeletonization_matlab_parity.py +++ b/tests/test_skeletonization_matlab_parity.py @@ -12,8 +12,8 @@ WNAT_Hagen, WNAT_Onur, WNAT_Test, or WNAT_NC_inundation_v6c) - Wetting-and-drying test mesh: 15 layers -(These meshes are not bundled with CHILmesh; they live in the ADMESH-Domains -catalog. Add them to EXPECTED below once the loader for ADMESH-Domains meshes +(These meshes are not bundled with CHILmesh; they live in the Valence +catalog. Add them to EXPECTED below once the loader for Valence meshes exposes a programmatic fetch.) """ from __future__ import annotations diff --git a/tests/test_skeletonization_matlab_parity_external.py b/tests/test_skeletonization_matlab_parity_external.py index e2c7544..ba5f573 100644 --- a/tests/test_skeletonization_matlab_parity_external.py +++ b/tests/test_skeletonization_matlab_parity_external.py @@ -1,12 +1,12 @@ -"""MATLAB-parity tests for skeletonization on external (ADMESH-Domains) meshes. +"""MATLAB-parity tests for skeletonization on external (Valence) meshes. This is a sibling of ``tests/test_skeletonization_matlab_parity.py`` that pins -expected layer counts for meshes from the external ADMESH-Domains catalog, +expected layer counts for meshes from the external Valence catalog, rather than the bundled fixtures. Why a separate file? Bundled-fixture parity is a fast, always-on guardrail (every CI push runs it). External-mesh parity requires installing the -``admesh-domains`` package and downloading mesh files, so it is opt-in. Keeping +``valence-domains`` package and downloading mesh files, so it is opt-in. Keeping the two concerns in separate files lets the fast tests stay cheap while still documenting the broader correctness expectation for the maintainer. @@ -19,7 +19,7 @@ Reference values were captured from the original QuADMesh+ ``meshLayers`` algorithm in ``00_CHILMesh_Class/@CHILmesh/CHILmesh.m``. The seven values tagged "F12 captured 2026-05-23" were produced by running that MATLAB class under -GNU Octave 8.4 on the ADMESH-Domains catalog meshes (connectivity + points fed +GNU Octave 8.4 on the Valence catalog meshes (connectivity + points fed to the 2-arg ``CHILmesh(ConnectivityList, Points)`` constructor, bypassing the MATLAB ``readFort14`` reader). The harness was validated first against the three already-known references — delaware-bay@default (17), lake-erie@5k (17), @@ -29,7 +29,7 @@ .. code-block:: bash - pip install admesh-domains + pip install valence-domains CHILMESH_RUN_EXTERNAL_PARITY=1 python -m pytest \\ tests/test_skeletonization_matlab_parity_external.py -v @@ -55,7 +55,7 @@ # Maintainer-provided reference layer counts from external MATLAB ``meshLayers`` runs. -# Each entry is keyed by ADMESH-Domains identifier (catalog mesh name + variant tag). +# Each entry is keyed by Valence identifier (catalog mesh name + variant tag). # Values: # - int: exact n_layers known # - (int, int) tuple: range (lo, hi) when source mesh variant is unconfirmed @@ -88,11 +88,11 @@ def _admesh_domains_available() -> bool: def _load_mesh(catalog_id: str): - """Resolve an ADMESH-Domains catalog ID to a loaded CHILmesh. + """Resolve an Valence catalog ID to a loaded CHILmesh. Catalog ID convention: ``"@-v"``, e.g. ``"italy@default-v1"``. The exact resolution depends on the - ``admesh-domains`` Python loader; we use a placeholder that will be wired + ``valence-domains`` Python loader; we use a placeholder that will be wired up once the loader API is finalized. """ import admesh_domains # type: ignore @@ -101,7 +101,7 @@ def _load_mesh(catalog_id: str): variant, _, version = variant_with_version.rpartition("-v") record = admesh_domains.get(mesh_name, variant=variant, version=int(version)) - record.load() # ADMESH-Domains lazy-load contract + record.load() # Valence lazy-load contract from chilmesh import CHILmesh return CHILmesh.from_admesh_domain(record, compute_layers=True) @@ -110,21 +110,21 @@ def _load_mesh(catalog_id: str): _RUN_EXTERNAL = bool(os.environ.get("CHILMESH_RUN_EXTERNAL_PARITY")) _SKIP_REASON_EXTERNAL = ( "Set CHILMESH_RUN_EXTERNAL_PARITY=1 to run the external MATLAB-parity tests " - "against the ADMESH-Domains catalog. Requires `pip install admesh-domains`." + "against the Valence catalog. Requires `pip install valence-domains`." ) @pytest.mark.skipif(not _RUN_EXTERNAL, reason=_SKIP_REASON_EXTERNAL) @pytest.mark.skipif( not _admesh_domains_available(), - reason="admesh-domains package not installed; `pip install admesh-domains`", + reason="valence-domains package not installed; `pip install valence-domains`", ) @pytest.mark.parametrize( "catalog_id,expected", [(cid, exp) for cid, exp in MATLAB_REFERENCE_LAYER_COUNTS.items() if exp is not None], ) def test_layer_count_matches_matlab_reference(catalog_id: str, expected) -> None: - """For each ADMESH-Domains mesh with a known MATLAB ``n_layers``, + """For each Valence mesh with a known MATLAB ``n_layers``, the Python port must produce the same value (or fall in the documented range). """ mesh = _load_mesh(catalog_id) @@ -145,17 +145,17 @@ def test_layer_count_matches_matlab_reference(catalog_id: str, expected) -> None @pytest.mark.skipif(not _RUN_EXTERNAL, reason=_SKIP_REASON_EXTERNAL) @pytest.mark.skipif( not _admesh_domains_available(), - reason="admesh-domains package not installed; `pip install admesh-domains`", + reason="valence-domains package not installed; `pip install valence-domains`", ) def test_uncovered_meshes_have_fixme() -> None: - """Meta-test: every ADMESH-Domains entry without a captured MATLAB count + """Meta-test: every Valence entry without a captured MATLAB count must remain in the table with ``None`` so it is visible as a FIXME during review. """ uncovered = [k for k, v in MATLAB_REFERENCE_LAYER_COUNTS.items() if v is None] if uncovered: pytest.skip( - f"{len(uncovered)} ADMESH-Domains meshes lack a MATLAB reference layer " + f"{len(uncovered)} Valence meshes lack a MATLAB reference layer " f"count. Capture via QuADMesh+ and add to MATLAB_REFERENCE_LAYER_COUNTS: " f"{', '.join(uncovered)}" )