Outcropping zones: the fault zone leaves its band on the surface - #526
Conversation
The thin-volume form of the outcrop, completing "get all the implementation done". The assembly is clipped against the domain box in OCC (specify-long: patches may protrude; clipped faces snap exactly onto the wall plane), and a clipped face left in ONE wall plane becomes the zone's BAND. The gap's boundary is then ONE closed surface of three discrete pieces — the interior shell, the pre-meshed CAP (an annulus in the wall plane: rim ring verbatim, the band outline as its HOLE, via the 2-D fill), and the interior part of the skin, rim-matched to the cap's hole. The band's triangles become boundary faces carrying BOTH the zone's skin label and the wall's own labels; the cap's annulus is relabelled the same way, full closures, counts gated. The volume carve gains open_wall (victims may lie in the open wall's plane; the shell may open there via the shared _closed_shell_3d); box-edge bands and multi-wall contact refuse with the reason. Measured serial and np=2,4: identical zone counts, P2 quadratic FE-exact (5e-11..7e-11) with Dirichlet gripping the remeshed Top, full Top coverage. Interior zones unchanged: suites 0853-0856 (45 serial) and the placement ptests green. Band contract test added to test_0855. Underworld development team with AI support from Claude Code
|
Adversarial review (self, posted per project practice): The three-piece boundary is the risk we attacked. The gap's closed surface is assembled from three independently produced triangulations sharing nodes only by tag identity: shell↔cap at the wall rim, cap↔skin at the band outline. Every sharing is gated — moved-nodes zero across all constrained sets, cap/skin triangle counts refused if remeshed, and every band and cap face recovered by join with the relabel count compared against the expectation. The FE oracle with Dirichlet on the remeshed Top then closes over the whole chain: a single mis-sewn edge or unlabelled patch cannot reproduce the quadratic. A subtlety we verified rather than assumed: OCC's clipped faces land within rounding of the wall plane, not on it; the band logic keys on EXACT plane values, so assembly nodes within 1e-9 snap onto the plane before anything reads them. Without the snap the band detection silently returns empty and the placement refuses at the wall — loud, but wrong. Stated residuals: removal of an outcropping object is the one asymmetry left (the removal carve does not yet pass open_wall — a spent outcropping fault currently refuses removal rather than clearing its band); box-edge bands and curved tops refuse with reasons as before. Underworld development team with AI support from Claude Code |
Underworld development team with AI support from Claude Code
There was a problem hiding this comment.
Pull request overview
Completes the “outcropping zones” path for place_thin_volume() by clipping the OCC-built zone assembly to the domain box and treating the clipped wall-face as a surface “band”, including explicit wall relabelling and a contract test that validates the full chain via a P2 Poisson exactness oracle.
Changes:
- Extend
_occ_assembly_3d()to optionally intersect the assembly solids with the domain box (“specify-long”) and snap clipped faces to exact wall-plane coordinates. - Add band/cap plumbing for outcropping thin volumes: split skin into interior vs band, allow the carve to open onto one wall, pre-mesh a cap annulus with a hole matching the band outline, and explicitly relabel new wall faces with the replaced wall-label closures.
- Add
test_an_outcropping_zone_leaves_a_band_on_the_surface()to assert band existence/labels and FE exactness after outcrop remeshing.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/underworld3/utilities/place_surface.py |
Implements outcropping-zone “band on wall” handling: box-clipped OCC assembly, band extraction, open-wall carve, cap-annulus gap fill, and explicit relabelling gates. |
tests/test_0855_place_thin_volume.py |
Adds a contract test covering the outcropping zone band + relabel + P2 exactness check chain. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if wall_code is not None: | ||
| axis, side = wall_code // 2, wall_code % 2 | ||
| open_wall = (int(axis), | ||
| float(box_hi[axis] if side else box_lo[axis])) | ||
| from collections import Counter as _Counter | ||
| band_edge = _Counter() | ||
| for t in skin_tris[band_idx]: | ||
| a, b, c = sorted(int(v) for v in t) | ||
| for e in ((a, b), (a, c), (b, c)): | ||
| band_edge[e] += 1 | ||
| band_outline = _single_loop( | ||
| [e for e, k in band_edge.items() if k == 1], | ||
| "zone's outcrop band outline") | ||
| skin_tris_fill = (skin_tris[interior_idx] if open_wall is not None | ||
| else skin_tris) |
Completes the outcrop implementation (with #525): the thin-volume form. A fault ZONE specified past the box is clipped in OCC; its clipped face becomes the BAND on the surface; the gap's boundary is one closed surface of three discrete pieces (interior shell + cap-annulus with the band outline as its hole, pre-meshed by the 2-D fill + interior skin, rim-matched). Band faces carry BOTH the zone's skin label and the wall's labels; the cap annulus is relabelled explicitly with full closures, counts gated.
Measured serial and np=2,4: identical zone counts, P2 FE-exactness (5e-11–7e-11) with Dirichlet gripping the remeshed Top, full Top-label coverage face-by-face. Interior zones byte-for-byte unaffected — suites 0853–0856 (45 serial) and the placement ptests green. Band contract test in test_0855.
Stated residuals (refuse with reasons): box-edge bands / multi-wall contact; curved or deformed tops (the manifold-prep slot); removal of an OUTCROPPING object (its cavity legitimately touches the wall — the removal carve does not yet take open_wall; next small instalment if needed).
Underworld development team with AI support from Claude Code