Skip to content

The general 3-D outcrop cap: a zone may meet any boundary - #589

Open
lmoresi wants to merge 5 commits into
bugfix/fault-clip-boundaryfrom
feature/fault-outcrop-3d-cap
Open

The general 3-D outcrop cap: a zone may meet any boundary#589
lmoresi wants to merge 5 commits into
bugfix/fault-clip-boundaryfrom
feature/fault-outcrop-3d-cap

Conversation

@lmoresi

@lmoresi lmoresi commented Aug 16, 2026

Copy link
Copy Markdown
Member

Stacked on #582 (base is its branch); only the last three commits are this PR.

A fault zone specified past the mesh boundary now embeds whatever that boundary is: a tilted or rotated wall, a box edge, a faceted sphere. The NotImplementedError at the old _trace_wall_code — "the zone outcrops on a non-axis-aligned boundary" — is gone, and the function with it.

What the cap is now

The cap over the outcrop bowl is re-triangulated per coplanar boundary region, each piece meshed flat in its region's own plane, so the cap sits exactly on the faceted surface and volume conservation survives to 1e-12. Where the band crosses a crease between regions, the two sides segment the crease line differently — the bowl's nodes are mesh vertices, the band's crossing nodes are assembly nodes — so a 1-D overlay merges both node sets by arc coordinate and keeps each elementary sub-segment for the side(s) whose bowl covers it and the band does not. A sub-segment covered from one side only must be a whole mesh edge, because a cavity-shell face matches it in the fill's closed surface; anything else is a refusal, not a crack.

The frame rule (_outcrop_frame_3d) separates two notions the third dimension forces apart. Where the cavity may open is by smooth wall: coplanar regions grouped across low-dihedral creases (under 45 degrees), so a faceted sphere is one wall and its bowl legitimately spills onto facets beside the band's own, while a box's other walls stay refused across their sharp edges. What the carve may delete is by shape: band-covered vertices, single-region interiors, and interior vertices of straight creases between touched regions. A vertex where three or more regions meet — a box corner, every vertex of a faceted sphere — is the domain's shape and is never deleted off the band. A protected vertex whose whole cell star drops is not stranded: it is a collar node, and the gap fill's tets reference it. That is how a curved boundary keeps its faceting through the surgery.

Wall labels are restored per removed face (the 2-D per-segment rule of the corner fix, one level up), so a bowl spanning Top and Front restores each wall's own labels. The Euler gate now demands conservation of the input's Euler number rather than the value 1: a spherical shell is S²×I, Euler 2, and was refused before for its topology rather than for any defect. The same assumption remains in place_sheet and remove_embedded, marked TODO(BUG).

Evidence

  • The box oracle did not move: the full placement suite (0853–0856, 0859) passes unchanged, 62 tests.
  • New test_0860_outcrop_general_boundary_3d: a rotated box (no wall axis-aligned), a band across the Top/Front box edge (trace on both walls, each wall's labels restored on its side), and a spherical shell outer surface. Each runs its negative control first — the identical census on an interior twin counts no trace — and each ends in the P2 Poisson oracle, exact through the zone.
  • Parallel: the rotated-box outcrop added to ptest_0855 passes at np=2 and np=4; the trace count (28 facets) is identical at np=1, 2 and 4 with the info dict identical on every rank.

Known limits, stated as refusals

  • A band running along a domain crease (rather than across it) refuses with the reason.
  • A band outline node landing within rounding of a kept mesh vertex refuses: the 2-D imprint collapse (_collapse_boundary_imprints) has no 3-D counterpart yet.
  • place_sheet's outcrop stays box-framed, per the plan's own advice — unify after, not during.

Underworld development team with AI support from Claude Code

…h walls

The zone outcrop no longer needs an axis-aligned wall. The cap over the
bowl is re-triangulated PER COPLANAR BOUNDARY REGION, each piece meshed
flat in its region's own plane, so the cap stays exactly on the faceted
surface and volume conservation survives. Where the band crosses a
crease the two sides segment the line differently (mesh vertices against
assembly nodes), so a 1-D overlay merges both node sets by arc
coordinate and keeps each elementary sub-segment for the side(s) whose
bowl covers it and the band does not; a one-side segment must be a whole
mesh edge, because a cavity-shell face matches it.

The frame rule (_outcrop_frame_3d) separates the two notions the third
dimension forces apart. Where the cavity may OPEN is by SMOOTH WALL —
coplanar regions grouped across low-dihedral creases — so a faceted
sphere's bowl legitimately spills onto facets beside the band's own
while a box's other walls stay refused. What the carve may DELETE is by
shape: band-covered vertices, single-region interiors, and interior
vertices of straight creases between touched regions; a vertex where
three or more regions meet is the domain's shape and is protected. A
protected vertex whose whole cell star drops is not stranded: it is a
collar node, and the gap fill's tets reference it — that is how a
curved boundary keeps its faceting through the surgery.

Wall labels are restored per removed face (the 2-D per-segment rule one
level up): each new wall triangle takes the labels of the removed face
it lies on, so a bowl spanning several walls restores each wall's own.
The Euler gate now demands CONSERVATION of the input's Euler number
rather than 1 — a spherical shell is S^2 x I, Euler 2, and refused
before for its topology, not for any defect. The same assumption in
place_sheet and remove_embedded is marked TODO(BUG).

_trace_wall_code and its refusals are deleted; the box path runs
through the general machinery and the box oracle tests are unchanged.
Driven on a rotated box (no wall axis-aligned), a band across the
Top/Front box edge (trace on both walls), and a spherical shell outer
surface (75 trace facets, 6 vertices removed): volume conserved to
1e-12 in each.

Underworld development team with AI support from Claude Code
…n a sphere

Three configurations, each the failure mode of a different assumption
the box-framed cap made: a rotated box (no wall axis-aligned; the
single-region collar), a band across the Top/Front box edge (the crease
overlay conforms the two sides' differing segmentations, and each
wall's labels are restored on its own side), and a spherical shell
outer surface (every facet its own region, every vertex protected
faceting — the case the trace design exists for). Each runs its
negative control first — the identical census on an interior twin
counts no trace — and each ends in the P2 Poisson oracle, exact for a
quadratic through the zone. Volume conserved to 1e-12 throughout; the
shell's Euler number 2 comes through the conservation gate.

The parallel file gains the rotated-box outcrop at np>=2 with the same
mesh and patch as the serial test: the info dict is identical on every
rank and the trace count matches the serial value (28 facets at
np=1, 2 and 4), so the general path is partition-independent. No
boundary face is left without a wall label at any rank count.

The spherical control sits mid-gap of a 0.75-thick shell: a one-cell
chain from a victim corner spans h, so an interior zone needs
~(clearance + 1) * h to spare on both sides — thinner shells refuse
interior zones at this resolution by the carve's own clearance gate.

Underworld development team with AI support from Claude Code
The collar-vs-bowl consistency check raised on the surgery rank inside
the relabel block, which is outside any try — a hang at np>=2. It now
sets the block's failure and flows through the allgather like every
other refusal there.

Underworld development team with AI support from Claude Code
@lmoresi

lmoresi commented Aug 16, 2026

Copy link
Copy Markdown
Member Author

Adversarial review (self)

We reviewed the three commits against the plan's gates and our own claims. Findings, most severe first.

1. A rank-local raise shipped in the first commit and would hang at np≥2. The collar-vs-bowl consistency check raised on the surgery rank inside the relabel block, which is outside any try — exactly the defect class the file's own comments warn about. Found by re-reading the diff, not by any test: the parallel tests pass because the check never fires on healthy geometry. Fixed in the third commit by routing through the block's collective failure. A test that forces this refusal at np≥2 does not exist and would need deliberately inconsistent geometry; we did not construct one.

2. The general outcrops are 2–4× more slivery than the box outcrop. Minimum dihedral angles, same mesh scale (cellSize 0.12, width 0.05): interior zone 9.5°, axis-aligned box outcrop 13.8°, rotated box 6.4°, box-edge crossing 3.6°, spherical shell 3.1°. The mechanism is the one the 2-D corner work already met: the band outline lands where it lands, and a collar polygon between an outline node and a nearby kept mesh vertex is thin. The 2-D cure (_collapse_boundary_imprints) has no 3-D counterpart; until it does, near-coincidence refuses at rounding distance but produces slivers just above it. All fills pass the conformity gates and the P2 oracle is exact — the slivers are a quality cost, not a correctness one.

3. A dead end we built and removed. Our first treatment of stranded protected wall vertices kept one cell of the vertex's star ("rescue"). It produced floating kept islands the fill wrapped as bubbles (global Euler defect, measured on the sphere) and was replaced wholesale: a protected vertex needs no kept cell, because the collar re-triangulation references it and the gap fill's tets give it cells. The final code is simpler than what it replaced; the connectivity gate we wrote for the islands went with the rescue that caused them.

4. The Euler gate was wrong before this PR, for domains nobody could reach. != 1 encodes a ball; a spherical shell is Euler 2. The general clip made shells reachable, so the thin-volume gate now demands conservation of the input's number. The identical assumption remains live in place_sheet and remove_embedded — a sheet placed inside a spherical shell refuses today for its topology. Marked TODO(BUG) at both sites rather than fixed, per scope discipline.

5. Untested paths we know about. The polygon-nesting logic in _outcrop_collar_3d is exercised only at depth ≤ 1 (outer ring plus hole); depth-2 nesting (an island inside a hole) is written but unreached. The three refusal guards — band along a crease, outline node within rounding of a kept vertex, a band node splitting a one-side crease edge — fire on geometry none of our cases construct; they are read-verified only. The 45° smooth-wall threshold means a curved boundary faceted coarser than ~45° facet-to-facet splits into separate walls and refuses; documented at the constant, not tested.

6. Partition independence is asserted, not proven, for the sphere. The np=1/2/4 identity (trace 28) is measured on the rotated box only. The sphere runs serial-only; its parallel behaviour rests on the same gather-first mechanism the box exercises, which is an argument, not a measurement.

Underworld development team with AI support from Claude Code

The same gate place_thin_volume already fixed: demanding global Euler
number 1 encodes a ball-topology domain, and a spherical shell —
S^2 x I, Euler 2 — was refused for its topology rather than for any
defect of the surgery. Both gates now compare against the input mesh's
own number. Pinned by a regression test: a sheet embeds mid-gap in a
spherical shell and its removal clears the label again, both passing
their volume and conservation gates.

Underworld development team with AI support from Claude Code
@lmoresi

lmoresi commented Aug 17, 2026

Copy link
Copy Markdown
Member Author

Review finding 4 is resolved in 41eb60a rather than left as a TODO: place_sheet and remove_embedded now gate on conservation of the input's Euler number, the same fix place_thin_volume carries. A sheet embeds mid-gap in a spherical shell and removes again, pinned by a regression test in test_0854. Every placement primitive now works in non-ball domains.

Underworld development team with AI support from Claude Code

The gate catches unmeshed solids — an O(1) relative defect — but its
reference, OCC's getMass on the clipped boolean, is only accurate to
~5e-7 relative when the domain tool carries many faces (measured on a
16.6k-facet adapted spherical boundary: the honest mesh volume exceeds
the reported CAD mass before any snap runs). At 1e-9 the gate refused
correct assemblies; it now allows 1e-6, far above the kernel noise and
far below any real missing-solid defect.

Underworld development team with AI support from Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant