Skip to content

Checkpoint round-trip corrupts fault-adjacent DOFs on split meshes #640

Open

Description

@lmoresi

On a split (add_fault) mesh, write_timestep -> fresh Mesh(h5) -> read_timestep corrupts velocity DOFs at the cut: the coincident duplicated fault nodes are mixed on read-back, so part of the slip discontinuity is smeared into the first element ring.

Evidence (2-D S-fault rig, 4-strand network, rotated free-slip contact, coarse): raw in-cell fault-frame stress probed at ±0.006 from the main trace, same solve, A/B:

probe |tau_nt| mean |tau_nn| mean
A — in-memory after solve 0.12 0.86
B — after checkpoint round-trip 27.1 14.1

A is correct physics (shear traction released on the frictionless contact; normal deviatoric stress below the far-field value of 2). B is ~200x garbage at the slip/h scale (jump 0.4 over one 0.01 element), and decays over ~2 rings. Velocity probed at ±0.006 also shows a ~13% jump deficit after reload — consistent with cut-node values partially swapped between sides, most likely a coordinate-matched read-back that is ambiguous at coincident duplicates.

Consequences: any post-hoc stress/strain-rate recovery from split-mesh checkpoints is unusable near faults (we caught it rendering a stress field that showed a bright fault line the in-memory solve does not have). Far-field quantities and on-trace slip profiles sampled at band-scale offsets (±0.03) are only mildly biased.

Reproduction: ~/+Simulations/s_fault_rig/diagnostics/rt_probe.py (self-contained A/B; solve converges, prints the table above).

Likely fix territory: read_timestep DOF matching for meshes with duplicated (coincident) vertices — match by plex index/section, not by coordinate. Should land after #638 merges to avoid churning that PR.

Underworld development team with AI support from Claude Code

Activity

  1. added 2 commits that reference this issue on Oct 6, 2026
    41f6091
    a34269b
  2. lmoresi commented on Oct 6, 2026

    @lmoresi
    MemberAuthor

    Fixed by #714, merged to development (7c9cbbfd). Split-mesh checkpoints are read through the PETSc section rather than the coordinate KD-tree, so fault-adjacent DOFs survive the round trip. Covered by tests/test_0864_split_checkpoint_roundtrip.py and tests/parallel/ptest_0864_split_checkpoint_parallel.py.

  3. lmoresi commented on Oct 12, 2026

    @lmoresi
    MemberAuthor

    Reopened and labelled fixed-in-development, under the policy now in CLAUDE.md:

    While the fix is in an open PR, label the issue fixed-in-PR; when the PR merges, relabel it fixed-in-development, comment with the PR and the merge commit, and leave it open. Issues are closed when development is released to main.

    The fix stands and the evidence above is unchanged — this is a bookkeeping correction, not a reversal. Closing it on merge was wrong because development has not been released, so anyone running the release still has the defect; the label says where the fix is and the release sweep closes it.

  4. added
    fixed-in-developmentFix merged to development; the issue closes when it is released to main
    on Oct 12, 2026
  5. lmoresi commented on Oct 13, 2026

    @lmoresi
    MemberAuthor

    This regressed on development and the label was wrong. PR #847 restores it.

    Probed rather than taken on the merge reference, which is what found it:

    commit tests/test_0864_split_checkpoint_roundtrip.py
    42f93470 — the merge before #756 5 passed
    f414da63 — after #756 1 failed

    #756 moved the reload payload from the file root into /restart/petsc. The writer still emits the per-field section and its global vector — both are on disk, one group deeper — but the reader's existence check stayed at the root, so a file written with petsc_reload=True was reported as having no native payload. The #640 guard then refused the good path along with the bad, advising a re-write with the flag the caller had already used. Split-mesh checkpoints could not be read back at all.

    So the fix from #714 was still present but disarmed. The fixed-in-development label was accurate when applied and stopped being true when #756 merged, which no probe would have caught except one run against development after the fact.

    Staying open and fixed-in-development is right again once #847 merges. It should not be closed by the release sweep until #847 is in, or the release closes a defect that reproduces.

    Underworld development team with AI support from Claude Code

  6. added 2 commits that reference this issue on Oct 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    fixed-in-developmentFix merged to development; the issue closes when it is released to main

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions