Skip to content

2-D fault zones cannot reach a boundary — the outcrop machinery exists but is never wired into the ribbon path #549

Description

@lmoresi

Why this matters

Faults reaching boundaries — especially the top — is the desired use case, not an edge case. A megathrust, any surface-breaking fault, and the Barr & Houseman benchmark configuration all require it. Today neither 2-D representation can do it, and this has been raised before.

What happens

RuntimeError: the ribbon's cavity reached the domain wall; the volume must be
              interior, with clearance to spare

Why — and it is not a fundamental obstacle

The outcrop mechanism is already built and working, and is used by two of the three placement paths in the same file. open_wall = (axis, value) lets the carve open onto one flat wall and be capped (place_surface.py, the open_wall plumbing around the cavity/fill helpers).

path clips to the box identifies the wall sets open_wall
place_sheet _clip_sheet_to_box _outcrop_chain yes
place_thin_volume 3-D occ.intersect with the box (the specify-long contract) _split_skin_band yes
place_thin_volume 2-D no — raises instead

_place_thin_volume_2d never clips its assembly and never computes an open_wall, so the carve hits the wall and refuses. The docstring asserts "ribbons are interior by construction", which is an assumption rather than a constraint — nothing about a ribbon requires it.

What it would take

All three pieces have a working analogue to copy, and the 2-D case is the simpler one:

  1. Clip the assembly to the box in _occ_assembly_2d — an occ.intersect against a rectangle, mirroring the 3-D box= path.
  2. Identify the outcrop edge — skin edges lying exactly in a wall line, the 2-D analogue of _split_skin_band's triangles-in-a-wall-plane. The band outline is then a pair of points rather than a closed loop, so _single_loop is not even needed.
  3. Set open_wall and let the existing carve/cap path run unchanged.

The area gate and the skin-loop logic need the same care they get in 3-D (a clipped ribbon's skin is no longer a closed loop on the wall side).

The contact side is a separate problem

fault_split also refuses:

fault_split: the fault touches the domain boundary. Only strictly interior
             faults, with both tips ...

but for a different reason — the code says "the slit would reach the boundary, where the tip-clamping argument fails". That is an argument about tips. A daylighting fault's boundary end is not a tip: it is an edge where the boundary condition differs above and below the slit, which is exactly how Barr & Houseman drive slip (velocity +u0/2 above the fault on the right-hand boundary, -u0/2 below). So the refusal is over-broad rather than wrong, and needs its own design pass — probably a distinction between "a tip lands on the boundary" (refuse) and "the slit crosses the boundary transversally" (allow, and let the BC differ across it).

Benchmark context

Barr & Houseman (1992, GRL 19, 1145-1148; 1996, GJI 125, 473-490) give closed-form near-tip asymptotics for a fault in a viscous medium — for n = 1, strain rate and stress as r^(-1/2), velocity as r^(+1/2), dissipation as r^(-1) for all n, and a dissipation exponent that moves continuously from -1 (free-slipping fault) to 0 (locked) as the fault's shear stress rises. Their fault runs to the boundary. The near-tip results are explicitly stated to be insensitive to the boundary distribution, so an interior two-ended fault can test the asymptotics without this fix — but the exact configuration, and the real use case, both need it.

Underworld development team with AI support from Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions