Repository navigation
Conversation
…a datum-only solve ThinSheet.normal_velocity sets the datum of the sheet-tangency constraint, so a sheet on a manifold can move along its normal (the radial motion of a tidally flexed shell over an ocean) and its in-plane strain rate carries the curvature term through the nodal normals. In the rotated nonlinear loop a cold start whose only forcing is the prescribed datum had a zero residual at u = 0 and returned converged in zero iterations before the lift was applied; the convergence test now waits for the lift and takes its reference scale from the lifted iterate. tests/test_1092: breathing (u = W rhat exactly, stress 6 eta W P) and the degree-2 membrane closed form (tangential velocity 3/11 of the radial pattern's surface gradient; 7.2, 3.4, 2.5 percent at h 0.3, 0.2, 0.15). scripts/sessions/tidal_shell/tidal_shell.py: the eccentricity-tide driver (degree 2, viscous or Maxwell sheet, collective diagnostics against the closed form, Mollweide maps). Underworld development team with AI support from Claude Code
… sphere, in-plane principal stresses The maps were drawn from a rank-local evaluation of the whole grid (garbage outside rank 0's cells) and the largest principal stress picked up the zero normal eigenvalue where both in-plane stresses were compressive. Underworld development team with AI support from Claude Code
… datum on fault pairs When rigid rotations are a genuine null space (a drag-free sheet on a sphere, a free-slip shell) the inner solve cannot reduce the residual's component along them, so the outer nonlinear residual is now measured in that quotient space, as it already was for the pressure gauge. A viscoelastic stress history on the faceted surface leaves such a component (measured: a tidally flexed Maxwell sheet floored at a relative residual of 1e-4 with every linear solve converged; one iteration per step after the change). The projected-out magnitude is kept on the solver as _rotated_rotation_gauge_residual. A split-fault pair on a manifold takes its tangency through the pair block, so a prescribed sheet normal velocity now rides the pair's mean-normal row (sqrt2 w, signed against the analytic normal); before, the fault nodes stood still while the sheet breathed (datum error 0.018 against an amplitude of 0.1). Tidal driver: tiger-stripe faults (count, length, spacing, latitude, interface law), per-step stress diagnostics on a collective grid through nodal stress components (the stress expression's velocity gradients cannot cross ranks), the objective-rate option, and the sweep plot script. Underworld development team with AI support from Claude Code
…, shear invariant, speed) and the faulted-versus-unfaulted comparison script Underworld development team with AI support from Claude Code
…re stress against a reference run Underworld development team with AI support from Claude Code
…circle optimum) beside the stripe-parallel receivers Underworld development team with AI support from Claude Code
…rden, driving-traction probes on virtual stripes, stripe azimuth, cycle plots and the Berne et al. figure analogue CoulombFaultLaw takes a constant effective normal stress added to the reaction-fed one (compression positive), the clamped-but-modulated fault of Berne et al. 2024. Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
…ckness to the sheet's resultant units; clamping reported as a stress Underworld development team with AI support from Claude Code
…et topology On a sheet on a sphere the fault is an edge carried by a 3-vector; the de-smearing mass picked the triangle's weights by the component count and gave the mid-edge nodes an eighth of their mass, so the effective normal stress the interface laws read (and the friction they produced) was off by node-dependent factors of 5 to 8. The reaction is the membrane resultant, L sigma_nn, now to 0.4 percent on every pair of the breathing sphere (test_1092). Underworld development team with AI support from Claude Code
…he prediction in the sweep plot Amplitude (24/11) mu A wt/sqrt(1+wt^2) and lag atan(1/wt): measured at 128 steps per period 0.0195 against 0.0193 and 32 against 28 degrees at De 0.3; the lag excess is first order in the step (15 degrees at 32 steps per period). Underworld development team with AI support from Claude Code
…tion coefficient Underworld development team with AI support from Claude Code
… saved per step for the site analysis Underworld development team with AI support from Claude Code
…pe-plane tractions (phase of the clamping, Coulomb asymmetry index); the overlay takes labelled runs Underworld development team with AI support from Claude Code
… azimuth Underworld development team with AI support from Claude Code
…ycle, the excess and the slip it drives Underworld development team with AI support from Claude Code
…and polar grids, saved at cycle boundaries Underworld development team with AI support from Claude Code
…ulted Underworld development team with AI support from Claude Code
…rules A fault placed as a ladder on a copy of the base's finest level gets only the welded tail (A); in a yielding, convecting box its velocity sub-solve caps at 200 once the lid mobilises. Building C by hand, the same ladder at 4S and 2S on the coarser base levels, each split along its own rungs, keeps the Newton-phase velocity iterations at 29-38 with no caps (A: 71-200, 2 caps) at A's cost per cycle. New capability guide guides/faults-in-convection.md (skill link included): the lean tail, the rotated loop's warm-start rules (first solve from rest; newton_switch_rtol measured from each solve's own residual, so warm solves need it at 1), rebuilding for a moving trench (shifted warm start, Picard first, rebuild every few rungs), and the measured traps. The design note records the A / C comparison and lists the ribbon replay as not yet done. Underworld development team with AI support from Claude Code Claude-Session: https://claude.ai/code/session_019aromUkeWWPzcL2Kb8365E
…le-integrated activity and net offset), saved at orbit boundaries Underworld development team with AI support from Claude Code
… profiles (Berne et al. Fig. 4 style) Underworld development team with AI support from Claude Code
… kinked chain of arcs lost part of its cut silently) Underworld development team with AI support from Claude Code
…polar view Underworld development team with AI support from Claude Code
…pe block Underworld development team with AI support from Claude Code
…noise floor (the unfaulted shell's residual) Underworld development team with AI support from Claude Code
…before the cycle's first step (it missed one step) Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
Three fixes found by the tumbling-fault Mohr sweep, brought onto this branch for the box fault study: - fault_contact: the 3-D fault normal traction is recovered pointwise (a linear fit of the P2-triangle consistent load on the facet vertices) rather than by dividing by P1 sub-lumped masses, which read zero at every vertex and 4/3 of the value at every midpoint. The branch is keyed on the facet topology (mesh.dim), not the coordinate dimension, so the edge fault on a surface mesh keeps its lumped path. - place_surface: the sheet cavity is closed in the three shapes that defeated it on adapted meshes (an enclosed kept cell, a pinched shell vertex, a flat fill tet), with a bounded refill loop. - fault_split: a single split_fault keeps the mesh's multigrid tail, as the network path already did. Tests: the pointwise 3-D traction and the multigrid-tail checks in test_0848; the adapted-mesh placement cases as test_0867 (0864 was taken on this branch). Underworld development team with AI support from Claude Code
…links) Two owners kept every faulted rebuild alive: the default model's _meshes, _variables and _solvers (strong dicts; now WeakValueDictionary, as _swarms already was), and the coordinate objects' strong link to their mesh, pinned through sympy's function caches (UWCoordinate, CoordinateSystem and its accessors now hold the mesh weakly). test_0077 failed on both counts before and passes after; full validation and the memory probe still to run. Underworld development team with AI support from Claude Code (cherry picked from commit 8ce92ea)
…h dies Weak variable registration changed what a variable's lifetime means (a mesh holds its variables weakly, so a variable the caller did not keep vanished: 22 tier-A failures). The registry holds variables strongly again and a finalizer on each mesh drops its variables when it is freed. MeshVariable no longer keeps its constructor arguments (_init_params held the mesh strongly). test_0077 passes; one remaining failure, test_0864, is being checked against the base. Underworld development team with AI support from Claude Code (cherry picked from commit dd7545c)
petsc4py defers destroying collected objects in parallel until a collective PETSc.garbage_cleanup; nothing called it, so every dropped mesh's DMs, matrices and vectors lived on (52.7 MB per rebuild at np 2 with every Python object freed; 2217 live DMs after five rebuilds against 98 in serial). Mesh.__init__, collective over its DM's communicator, now collects and cleans up on that communicator. tests/parallel/test_0078 (written first: 39.6 MB per rebuild against a 10 MB bound) passes. Underworld development team with AI support from Claude Code (cherry picked from commit 8a955f5)
Each faulted-mesh rebuild kept the whole previous mesh: 53.7 MB per rebuild in serial and 56.0 MB at np 2 on the moving-fault fixture, ~7 GB per node per rebuild in kaiju production (an OOM kill after 24 rebuilds). Four owners: - the default model's _meshes and _solvers registries (now weak; _variables stays the variables' owner and drops a mesh's variables when it is freed); - sympy's caches holding coordinate symbols that held their mesh (UWCoordinate, CoordinateSystem and its accessors now hold it weakly); - MeshVariable._init_params, the constructor arguments kept with the mesh; - in parallel, petsc4py's deferred destroy list, never emptied: Mesh.__init__ now collects and runs PETSc.garbage_cleanup on its DM's communicator. After: 0.1 MB per rebuild in serial and at np 2. tests/test_0077 and tests/parallel/test_0078, both written first and failing, pass. Tier A level 1: 1495 passed, 1 failed (test_0864, failing identically on the base); np 2 custom-MG / rotated / fault-split: 19 passed, 4 skipped. Numbers and method in scripts/sessions/rebuild_leak/README.md. Underworld development team with AI support from Claude Code (cherry picked from commit 547c2e5)
…exes Review findings on the leak fix: - Model._part_objects (the step transcript's part -> object map) was a strong dict keyed by instance: every solver that solved inside model.step was kept, with its mesh. Now weak. - A variable no longer kept its mesh (a helper returning only a variable lost the mesh). A variable now holds its mesh; the mesh owns its variables (mesh._vars a plain dict, the cycle collected with the mesh); the model's _variables is a weak index, so the finalizer purge (and the stale stats() temporaries it missed) is gone. Variable symbols hold the variable weakly, so sympy's caches pin neither. - _primary_mesh_id outlived its mesh and could be taken by a reused address, differently per rank: the primary mesh is now a weak reference, a freed primary is replaced by the next mesh, and set_primary_mesh always sets it. - The .msh path's cleanup now uses the communicator the reader uses. test_0077 gains three tests (a variable keeps its mesh; a solver that solved in a step with transcripts on is freed; the primary mesh is released and replaced), each failing on 547c2e5 and passing here. Underworld development team with AI support from Claude Code (cherry picked from commit 56df136)
A mesh now owns its variables, so a model reset no longer releases one and the tests' orphan never appeared (3 tier-A failures, premise only). The orphan is made the way the statistics helpers make it: the variable taken off mesh.vars and collected, its DM field left behind. The assertions on packing around the orphan are unchanged. Underworld development team with AI support from Claude Code (cherry picked from commit ff782c4)
Underworld development team with AI support from Claude Code (cherry picked from commit 5b4e365)
Underworld development team with AI support from Claude Code (cherry picked from commit fb9b1ba)
Underworld development team with AI support from Claude Code (cherry picked from commit b8624a4)
Underworld development team with AI support from Claude Code
WIP, hyperion shutdown 2026-10-27 Underworld development team with AI support from Claude Code
WIP, hyperion shutdown 2026-10-27 Underworld development team with AI support from Claude Code
# Conflicts: # src/underworld3/utilities/rotated_bc.py # tests/test_1018_rotated_freeslip.py
…' into HEAD # Conflicts: # src/underworld3/utilities/rotated_bc.py
- A snapshot collects before it visits the registered meshes (Model._live_meshes). A dropped mesh with variables is a reference cycle and stays in the weak registry until the cyclic collector runs, at a different moment on each rank; write_snapshot's per-mesh collective checkpoint write then hung at np 2 (test_0079 hangs before, passes after; the in-memory snapshot raised "duplicate mesh name" in serial). - A swarm holds its mesh. Found by id in the weak registry, a mesh nobody else held was freed under the swarm (swarm.mesh returned None). - The base variable holds its user-facing wrapper, so the variable the model indexes lives as long as the mesh that owns the base. A dropped wrapper vanished from the registry, and units, scaling and the adjoint skipped it. - MeshVariable no longer destroys its vectors in __del__: it is freed by the cyclic collector at per-rank times, where an explicit destroy of the parallel vector is a collective call by one rank. petsc4py defers it to the cleanup the next mesh construction runs. The three serial tests in test_0077 fail before and pass after. Underworld development team with AI support from Claude Code
It read /proc/self/statm and failed with FileNotFoundError on macOS. On macOS the resident set does not track freed memory: with the fix, PETSc's object table is unchanged between 4 and 8 rebuilds (284 DMs, 221 Mats, 298 Vecs on rank 0 at np 2) while the resident set rises 14-26 MB per rebuild, so the bound is a Linux assertion. Underworld development team with AI support from Claude Code
…ords out The ownership rules review 3 added (the base variable holds its wrapper, a swarm holds its mesh, collective traversals collect first, no parallel destroy from __del__) go into docs/developer/subsystems/model-orchestration.md beside the rest. The probes, run records and README under scripts/sessions/ rebuild_leak leave the repository (Louis, 2026-10-28: library and expertise in underworld3, campaign drivers and run outputs outside it); they are kept in ~/+Simulations/rebuild_leak, and the review record goes on the PR. Underworld development team with AI support from Claude Code
… per snapshot - A proxied swarm variable's remesh callback held the variable strongly; the proxy's mesh owns the proxy (through the base variable and its wrapper), so a swarm moved off a long-lived mesh left that mesh keeping the variable and the swarm's new mesh. The callback holds it weakly (test_0077, fails before). - The variable statistics destroy their temporary's vectors where they discard it, a point every rank reaches; left to the collector they waited on petsc4py's deferred list until the next mesh, one vector per call. - Each snapshot entry point collects once, on every rank, and passes the list down; _solvers_of and the metadata writer no longer collect again, which they did inside rank-0-only blocks. - test_0077 is level 2 and tier B (two tests solve; all are new and proven); test_0079 uses the thread timeout and gains the in-memory snapshot case; the orchestration doc states the Swarm.__del__ exception; a stale comment in Swarm.__init__ and test_1058's docstring corrected. Underworld development team with AI support from Claude Code
… the review fixes) Six conflicts, resolved: - constitutive_models.py (two hunks) and ddt.py (two): development's _etd_maxwell_time / _update_exp_values (#851: the step as its own constant, the declared vanishing floor, expm1, units) supersede this lineage's 9e97670, which made the same repair (a viscosity varying in space keeps its elastic response); test_1093 from 9e97670 stays and checks it. - solvers.py: development's #850 guard in _check_velocity_preconditioner, with this lineage's fault-contact marker kept (a faulted solve with no walls takes the same rotated loop). - thin_sheet.py: the lineage's normal_velocity property, then the review's add_basal_drag(conds, ...). - scripts/test.sh: the review's comment on the test_108*/test_109* batch. - fault-split-multigrid.md: the lineage's text (it removed co-location: the add-on is partitioned once), not the review's co-location bullet. Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code # Conflicts: # scripts/sessions/fault_mg/fig_parallel_load.py
…gauge vectors - guides/faults-in-convection.md (a capability guide, read as a skill) said solve(picard=N) raises on the rotated path and that the Newton switch reads the warm start's own residual, with newton_switch_rtol = 1.0 as the workaround; on this branch picard=N stages Picard then Newton and the switch reads the convergence reference (371d3bd). Corrected. - Campaign drivers and probes leave the repository (Louis, 2026-10-28): scripts/sessions/parallel_addon, tidal_shell, box_fault_cyclic, and the last fault_mg file; the design note's probe references say where they live. - test_1093 duplicated development's test_1053 (same fixture and checks) and is removed. New tests start at tier B: test_1098, test_1100's table test, and the two newest tests of test_1018, whose tiers now go on each test. - The rotated solve destroys its rotation-gauge mode vectors (one leaked per mode per solve) and warns when the projected-out rigid-rotation component dominates a converged residual, as the pressure gauge does (a net torque on free-slip walls has no solution and reported converged in silence). - FAULT_MULTIGRID_HIERARCHIES no longer lists co-location as to come. Underworld development team with AI support from Claude Code
Member
Author
Adversarial reviewThe parallel-addon lineage had its own review on 2026-10-17 ( Fixed
Merge resolutions (c842c11)
Left open (filed)
Attacks that failed
Merge conditions
|
🔍 Architectural Review ChecklistThank you for submitting an architectural review! Reviewers should validate: Design & Architecture
Implementation
Testing & Validation
Documentation
Review Process: See CODE-REVIEW-PROCESS.md Approval: This PR merge = Review formally approved |
|
✅ Test Suite: success |
…base level The prose placed the 2S and 4S ladders one and two levels below the finest. The guide's own code (host = base_levels[len - k] for k = chain..1) and its cell counts (lean chain 642, 2924, 10950, 11612) put 2S on the finest base level beside the S ladder and 4S one level down; the coarser levels stay welded. Underworld development team with AI support from Claude Code
|
✅ Test Suite: success |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The rest of the fault-split work, stacked on #889 (split-level fault multigrid); retarget to
developmentwhen that merges. Together with #882 (the rebuild leak) this is everything UWTN 2026-018 and 2026-022 describe.What it adds
utilities/addon_partition.py,docs/developer/design/parallel-addon-distribution-2026-10.md): the finest mesh built on a static base byadapt, a cut, a placement or a split is partitioned for load once, with its add-on levels, and every transfer to it is partition-agnostic (recorded provenance, not location). A second partition keeps a split fault whole; faults are glued by name. Reviewed 2026-10-17 (record indocs/reviews/2026-10/).ThinSheet.normal_velocity): the breathing of a tidally flexed shell._plex_topology.pyx).Measured
UWTN 2026-022's fixture on this head: split 5 / welded 13 velocity iterations at k = 3, peak slip 0.1589860839 / 0.1589859512 (the note's figures); the note's "Using it" recipe runs as written. On the head before today's merges, the note's README numbers reproduced at np 1 (all of them) and np 4 (same hierarchies; iterations within one; slip within 2.4e-6).
Review
The parallel-addon lineage was reviewed on 2026-10-17. Today a pass on the whole of this PR's delta (the merged rotated solve, today's merges, the add-on and empty-rank code, the tests) found two must-fix items and several should-fix ones; the first comment lists them and what was done.
Suites (laptop, macOS, this head): tier A level 1 serial 1498 passed, 44 skipped, 0 failed;
tests/parallelat np 2 180 passed, 15 skipped, 1 failed; at np 4 191 passed, 4 skipped, 1 failed; no hangs. The one failure istest_1063_constrained_freeslip_parallel[ti](#826), as on development. Until #882 merges this PR's diff includes it; it drops out when #882 lands on development and #889 takes development in.Issues
Left open by this PR, found in its review: #883 (the cold-start datum lift's convergence reference), #884 (the rotation-gauge projection measured from the second assembly), #885 (
custom_mg.last_builder_statsis module-global; curved boundaries trigger the cross-partition rebuild), #886 (a rank-local exception decidesbuild_transfers' retry), #887 (docs and messages behind the code), #888 (test reach: the cross-partition builder, an np 2 empty-rank case, test_1094's clamp).Underworld development team with AI support from Claude Code