`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.
`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.