Skip to content

Swarm.repopulate: after a removal the coordinate rows no longer match the value rows, so every refill in that call reads unrelated particles #784

Description

@lmoresi

`Swarm.repopulate` removes the surplus of an over-full cell with `dm.removePointAtIndex` and keeps its own coordinate array as `X[keep]`, in the original order. PETSc removes a point by copying the LAST point into the freed slot (`DMSwarmDataBucketRemovePointAtIndex`), so the surviving rows are reordered in storage. The variable values for the reconstruction are then read fresh from PETSc (`raw_old`, storage order) while the kd-tree, the RBF operator and `nearest_row` are built on `X[keep]`: the neighbour indices point at the wrong rows, and a particle created in the same call takes the values of unrelated particles.

Evidence, Poiseuille flow of a Maxwell fluid with `stress_transport="lagrangian"` (`Lagrangian` installs a population control with a cap, and the clamped outlet pile-up trips it every step): after 50 steps the per-particle shear-stress error has median 0.12, 99th percentile 0.72 and maximum 4.8 with sign flips, on a field whose maximum is 3.2; with `max_per_cell` set to `None` the same run gives median 0.011 and maximum 0.125. The cells proxy averages the garbage down (0.06 at the inlet against 0.002 without the cap), which is why the closed-flow validations did not see it.

Fix: after the removals, re-read the coordinates from PETSc and re-locate them, so the tree, the operator and the nearest-neighbour rows share the storage order the values are read in.

Activity

  1. lmoresi commented on Oct 7, 2026

    @lmoresi
    MemberAuthor

    Labelled fixed-in-PR. The fix is in #785, which is not merged and cannot be: its base feature/forward-parallel has no PR of its own.

    #785 is green and mergeable against its base after today's stack refresh. What is needed is a PR for the root branch.

    The label means the fix is written, not released. scripts/triage.py reports which PR and whether it has merged.

  2. added a commit that references this issue on Oct 8, 2026
  3. removed
    fixed-in-PRA PR carries the fix; the issue names it
    on Oct 8, 2026
  4. lmoresi commented on Oct 8, 2026

    @lmoresi
    MemberAuthor

    Fixed by #785, merged to development (719ef12d).

    Swarm.repopulate now reads the coordinate rows that belong to the value rows after a removal. The defect was PETSc's swap-with-last: a removal moves the last particle into the freed slot, so every refill later in that same call read coordinates from one particle and values from another.

    Worth keeping the measurement, because it is the reason this was hard to see: the particle-level stress error was median 0.12, max 4.8 — and the proxy hid it, because projecting garbage onto the mesh averages it away. Look at particle-level error before blaming the method.

    Closing manually: Closes lines here fire when development reaches main, and merges to main are infrequent. Removing the fixed-in-PR label.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions