Teaching example: listric faults over a common detachment — the two-representations comparison - #527
Teaching example: listric faults over a common detachment — the two-representations comparison#527lmoresi wants to merge 5 commits into
Conversation
…ns teaching example The classic rift geometry built both ways on the same base mesh, with the junction treatment as the lesson: ribbons sole into the detachment natively (junctions are cells of the union) and reproduce the linked block tectonics; zero-thickness surfaces with the junction gap localise individually but under-connect the system — the detachment barely engages. Scripts in ~/+Simulations/listric_extension/; figures committed. Underworld development team with AI support from Claude Code
There was a problem hiding this comment.
Pull request overview
Adds a new advanced documentation lesson comparing Underworld3’s two fault-placement representations (finite-width ribbons via place_thin_volume vs zero-thickness surfaces via place_along_lines) using the classic “two listric faults soling into a common detachment” rift geometry, emphasizing how junction handling controls system connectivity and resulting kinematics.
Changes:
- Added a new advanced page walking through the geometry, setup, and side-by-side interpretation of the two representations.
- Added the page to the advanced docs toctree so it builds and is discoverable.
Reviewed changes
Copilot reviewed 2 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| docs/advanced/listric-fault-extension.md | New teaching page describing the two-representations comparison, including code snippets, figures, and a comparison table. |
| docs/advanced/index.md | Adds the new page to the advanced documentation toctree. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| ```python | ||
| DETACH_Y = 0.4 # the common detachment depth | ||
| LAM = 0.18 # flattening length | ||
|
|
||
| def listric_trace(x0, y_lo, n=30): | ||
| y = np.linspace(1.0 - TOP_GAP, y_lo, n) | ||
| x = x0 + LAM * np.log((1.0 - DETACH_Y) / (y - DETACH_Y)) |
…n to come Terminology and scope per the maintainer's direction: the zero-thickness fault MEANS the split mesh (true discontinuity + contact), and the useful comparison for this geometry is ribbons vs split mesh — arriving with the fault-contact machinery. The conforming weak band is named for what it is and dropped from the page (its junctions under-connect; not a useful model of a detachment system). The ribbon presentation stands alone, with the glancing-junction note. Underworld development team with AI support from Claude Code
Adversarial review — PR #527: listric faults over a common detachment (teaching example)Reviewed at head Verdict: request changes. The page is sound and its claims reproduce, but the 1. MAJOR — the strain-rate panel plots negative values of a nonnegative invariantThe committed This is the known composite-evaluate trap — Fix per the house recipe (recover components, invariants in numpy): evaluate the 2. MAJOR — figure is not reproducible from the repository; #502 sets the opposite precedentThe PR commits the PNG but the generating scripts live only in 3. MODERATE — the PR body describes the previous version of the pageThe head commit ("reshape ... ribbons now, split-mesh comparison to come") removed 4. MODERATE — overtaken by #502; no cross-linksDevelopment merged the split-node fault + fault-contact machinery (#502) after this Forward note for the promised comparison: the listric trace is a sampled curve — 5. MINOR
CI
Verified good (live, PR-head build)
— review run in |
Split-node faults landed on development (#502), so the second half of this teaching example can be built. Both representations now run from the SAME raw traces, the SAME uniform base mesh and the SAME drive, with the interface law matched to the band (eta_f = eta_band / w). What the comparison shows: - the kinematics agree: same blocks, same subsidence pattern, peak vertical velocity -0.648 (ribbon) against -0.635 (split); - the strain rate cannot agree, and that is the point — the ribbon spends deformation as strain inside a band, the split spends it as a jump no strain measure can see; - peak slip agrees to 7-20% on the listric faults, but the detachment slips half as much in the split model. That halving is the JUNCTION, not the law. Controls: removing the interface law entirely moves slip by 2-4%; doubling the ligament costs the sole 16%. A listric sole is a glancing junction, so the offset form's pull-back is ligament*h/sin(theta) — 0.10 of trace here, three times what the same setting costs at an orthogonal crossing. Figures: the junction close-up (both constructions at one scale), the three-field comparison, and the slip profiles. Solver note recorded on the page: the split runs warn that an inner velocity KSP hits its cap; checked against the direct-LU route (0.2%) and against a 1000x tighter tolerance (unchanged). Underworld development team with AI support from Claude Code
Adversarial review — the completed comparisonWe built the second half against our own case. What survives, and what we would not yet claim. Holds up
Does not, and is stated on the page or here
CI: the four failures on this branch ( Underworld development team with AI support from Claude Code |
…e claim The first version of this page said the detachment's halved slip IS the junction gap. A refinement sweep shows that is too strong, and the follow-up controls refute two further explanations, so the page now carries the whole parameter study instead of the tempting conclusion. Sole peak slip, one knob at a time (ribbon reference 0.317): interface law removed (eta_f = 0) 0.154 -> 0.161 +5% ligament 1h -> 2h 0.154 -> 0.130 -16% refine h 0.035 -> 0.0233 -> 0.0175 0.154 -> 0.187 +21%, converging ~0.19 glue dial 0.05 -> 0.01 -> 0.002 0.181 -> 0.210 +16%, saturating glue plug made LARGER at fixed strength 0.181 -> 0.167 -8% best case (finest h, dial at ceiling) 0.216 68% of the ribbon The gap is the biggest single lever, but closing it converges to ~0.19, not to 0.317, and the ribbon is h-independent over the same range (0.3173 -> 0.3155) — a clean control, since its width is physical. Two explanations tested and DISCARDED, both recorded on the page: - band stretching (a weak sub-horizontal layer extending along its own length, read by our probe as slip): shrinking w 4x at fixed eta_f = eta_band/w moves the sole 4.5%. Not it — and the near w-independence at fixed eta_f is itself a good result, confirming eta_f as the similarity parameter between the formulations. - the plug shrinking away under refinement leaving a strong corner: pinning the plug LARGER makes transfer WORSE (-8%). A junction plug is a hinge, not a bridge. A ~30% residual survives every control. Stated as unexplained, with a warning to calibrate transfer rather than assume it, and the practical guidance sharpened: ribbons for junction-dominated systems (a detachment fed by splays is exactly that), split nodes for slip on individual faults, where the two agree to 86-97%. Control scripts kept with the study in ~/+Simulations/listric_extension/ (probe_h.py, probe_w.py, probe_dial.py). Underworld development team with AI support from Claude Code
Correction: the junction is most of it, not all of itThe refinement sweep we said was running has landed, and it does not support the claim we made two comments ago. Correcting it here, and on the page (653930f). What we claimed: the detachment's halved slip is the junction gap. What the sweep says: the gap is the largest single lever, but closing it recovers only about half the deficit.
The split rises in the predicted direction and converges to ≈0.19 — not to 0.317. The ribbon is flat over the same range (0.6%), which is the control we wanted: its width is a physical parameter, so it should be h-independent, and it is. Two follow-up explanations, both refuted.
Best case — finest mesh, glue at the ceiling — is 0.216 against the ribbon's 0.3155: 68%. A ~30% residual survives every control we have, and we are stating it as unexplained rather than attributing it to the last thing we tried. This is a better result for the page than the original: the two formulations agree on what a fault is (the listric faults reach 86–97% at the ceiling) and disagree on what a junction is, structurally rather than through mistuning. The sole is the only fault that must receive slip through two junctions, and it is the one that stays short. The practical guidance sharpens accordingly — ribbons for junction-dominated systems, split nodes for slip on individual faults — with a warning to calibrate transfer rather than assume it. Control scripts are kept with the study ( Underworld development team with AI support from Claude Code |
Some Azure runners advertise an InfiniBand verbs device (mana_0) that UCX cannot open; MPI_Init aborts inside the import smoke test before any underworld3 code runs. Four hits in a week across #466/#526/#527 (issues #461/#528), each fixed by re-rolling the runner lottery. A single-node CI runner needs only shared memory and TCP, so pin the transports at the workflow level - it covers the smoke test and every pytest batch alike. Underworld development team with AI support from Claude Code
The classic continental-rift geometry (two listric normal faults soling into a common detachment) built BOTH ways on the same base mesh — finite-width ribbons via
place_thin_volumeand zero-thickness surfaces viaplace_along_lines— solved under identical extension and rendered side by side.The comparison is the lesson: junctions decide the tectonics. The ribbons sole INTO the detachment (junctions are just cells of the union, resolved in the CAD stage) and reproduce the linked hanging-wall block structure with the detachment active between the junctions. The zero-thickness version needs the gap convention at the sole, localises on each fault individually, and under-connects the system — the detachment barely engages. The page closes with the when-to-use-which table and notes both representations share the placement family's lifecycle and (3-D) outcrop support.
New page
docs/advanced/listric-fault-extension.md+ two committed figures + toctree entry; generating scripts in~/+Simulations/listric_extension/(named subdir with README, per the working conventions).Underworld development team with AI support from Claude Code