Skip to content

Particle stress history: refill reads the right rows after a removal (#784), and the inflow datum reaches the particles that entered (#783) - #785

Open
lmoresi wants to merge 3 commits into
feature/forward-parallelfrom
bugfix/lagrangian-inflow
Open

lmoresi wants to merge 3 commits into
feature/forward-parallelfrom
bugfix/lagrangian-inflow

Conversation

@lmoresi

@lmoresi lmoresi commented Sep 24, 2026

Copy link
Copy Markdown
Member

Two defects in the particle Lagrangian stress history, found on the cross-slot cell of the 2026-09-23 domain-of-applicability sweep.

#784, the refill after a removal. PETSc removes a point by copying the last point into the freed slot. Swarm.repopulate kept its coordinate array in the original order while reading the reconstruction values in storage order, so a particle created in a call that also removed took the values of unrelated particles. The Lagrangian flavour caps over-full cells every step, and any clamped outflow pile-up trips the cap, so on an open flow every refill was garbage. The proxy's per-cell least-squares fit averaged it down, which is why the closed-flow validations did not see it. Fix: replay the same moves on the local arrays.

#783, the inflow datum. The flavour declared applies_inflow_value = False; a refilled inlet cell carried a reconstruction from stale neighbours. The manager now runs the refill itself after the advection, so it knows which particles it created, and gives inflow_value to every particle whose back-trace leaves the domain where the boundary velocity crosses inward. The trace is one step for a particle that moved and one cell crossing for one created this step. A no-slip wall has no boundary velocity and a free-slip wall only a tangential one, so a trace through a wall does not count.

Maxwell Poiseuille channel, 50 steps, stress_transport="lagrangian":

per-particle shear-stress error, median / max inlet column, proxy error
before 0.12 / 4.8 (sign flips; field max 3.2)
#784 fixed, no datum 0.008 / 0.125 0.17
#784 and #783 0.008 / 0.125 0.002

Tests: test_0068::test_a_refill_after_a_removal_reads_the_right_neighbours (97 before, 1e-8 after) and test_0075_lagrangian_history_inflow_value (baseline 0.01 against 0.002 measured, negative control 0.1 against 0.17). The particle-history, stress-transport, restart and integration-point files pass (71 tests).

Also moved: _write_inflow (with its units reduction) and _nondim_timestep to the base class. One extra commit replaces the deprecated mesh.data in the forward flavour's geometry stamp, which failed the Charter gate on this branch.

Not fixed here, marked TODO(BUG): the particle flavours write the evaluated psi_fn into non-dimensional storage without a units reduction. Not covered: a parallel test with a rank that creates no particles.

The cross-slot cell is not rescued. Re-run with both fixes: clean to step 26, then a linear-solve divergence and a 329 s step, stalled by the guard, with the stagnation point jumping. That is the same failure family as the nodal flavour on that cell at solvent fraction zero, so it is a solver question, not a refill one. The sweep's lagrangian column ran with #784 present and is not a measurement of the scheme.

Fixes #783, fixes #784.

Underworld development team with AI support from Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo

lmoresi and others added 3 commits September 23, 2026 21:22
…emoval (#784)

PETSc removes a point by copying the last point into the freed slot, so a
removal reorders the surviving particles in storage. repopulate kept its
coordinate array in the original filtered order while reading the values for
the reconstruction fresh from PETSc, so a particle created in a call that
also removed took the values of unrelated particles. The same moves are now
replayed on the local coordinate and cell arrays.

Measured on a Maxwell Poiseuille channel with the particle stress history:
per-particle shear-stress error median 0.12, maximum 4.8 with sign flips on a
field whose maximum is 3.2; now median 0.008. The cells proxy averaged the
garbage down, which is why the closed-flow validations did not see it.

Regression test: a call that both thins a band and refills the emptied one
reproduces a linear field to 1e-8 (97 before).

Underworld development team with AI support from Claude Code

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo
…ntered (#783)

No particle arrives from outside: the population control creates the
particles of an emptied inlet cell and gives them a reconstruction from the
nearest old particles, the wrong state for fluid that has just entered. The
manager now runs the refill itself after the advection, so it knows which
particles it created, and gives inflow_value to every particle whose
back-trace leaves the domain where the boundary velocity crosses inward:
one step back for a particle that moved, one cell crossing for one created
this step. A no-slip wall has no boundary velocity and a free-slip wall only
a tangential one, so a trace through a wall does not count.

_write_inflow (with its units reduction) and _nondim_timestep move to the
base class; the Lagrangian flavour now carries _components and _psi_units.

Measured on a Maxwell Poiseuille channel, inlet column after 50 steps:
shear-stress error 0.17 with no datum, 0.002 with it.

Underworld development team with AI support from Claude Code

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo
mesh.data is the deprecated accessor and fails the Charter deprecated-pattern
gate on this branch (36eb788). Same shape and sum, so the stamp is unchanged.

Underworld development team with AI support from Claude Code

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo
@lmoresi

lmoresi commented Sep 24, 2026

Copy link
Copy Markdown
Member Author

Adversarial review before the push, two independent passes over the diff. What they found and what we did:

Defects, fixed in the pushed commits

  • The inflow datum was written into non-dimensional storage without the units reduction the integration-point flavour applies. _write_inflow moved to the base class and the particle flavour now carries _components and _psi_units; _nondim_timestep moved with it so dt is reduced too.
  • An MPI rank holding no particles raised on reshape(0, -1) before the collective calls and would have deadlocked the others. Reshapes are dimension-explicit.
  • The stated "no datum" baseline of 4.2 had been measured with Swarm.repopulate: after a removal the coordinate rows no longer match the value rows, so every refill in that call reads unrelated particles #784 present. Re-measured with Swarm.repopulate: after a removal the coordinate rows no longer match the value rows, so every refill in that call reads unrelated particles #784 fixed: 0.17. The test's negative control and the PR table use that number; the one-step-horizon figure quoted earlier is withdrawn.
  • The created-particle count was a swarm attribute set only inside repopulate, stale whenever the control was cleared. The manager now calls repopulate itself and uses the returned count.
  • The back-trace test counted every boundary. A trace along a resolved curved wall, at a corner, or where the flow separates from a wall leaves through that wall and would have stamped the inlet datum there. The boundary velocity where the trace left now decides; a wall has none, or only a tangential one.
  • After a removal the fix re-located the whole swarm. It now replays PETSc's swap-with-last on the local arrays.
  • The Charter deprecated-pattern gate fails on this branch on a line from 36eb788; fixed in its own commit.

Recorded, not fixed here

Checked and fine: PETSc's removal semantics (verified empirically), the descending removal order, storage order after advection, return_coords_to_bounds in place on box and facet paths, the collective sequence, the symmetric-tensor column layout, both tests failing on the old build for the stated reason.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant