uw.function.evaluate returns large negative values for an expression whose range is
provably non-negative, at points inside the domain.
Unknowns.Einv2 is sympy.sqrt((E**2).trace()/2) — the square root of a sum of squares
of a real symmetric tensor. It cannot be negative for any velocity field.
Lid-driven cavity, UnstructuredSimplexBox at cellSize=1/8, P2/P1, direct solve:
negative in-domain samples:
coord [0.00536 0.86533] value -0.49758
coord [0.00783 0.83353] value -0.09049
coord [0.01006 0.87349] value -0.42628
All three hug the left wall just below the lid corner — the cavity's velocity
singularity, where Einv2 is large and varying sharply. Magnitudes of −0.1 to −0.5 are
not round-off.
Properties:
A negative square root means the value returned is not the expression evaluated at that
point. The plausible shape is that a representation of the scalar is being interpolated
rather than the expression being evaluated pointwise from the field, and interpolation of
a sharply peaked non-negative function undershoots. Not confirmed — it needs someone who
knows the evaluate path to say which branch is taken here.
Why this surfaced
tests/test_0112_swarm_add_particles.py::test_swarm_access_write_after_add_particles
accumulates 0.5 * evaluate(Einv2, swarm.data) and asserts the running total is
non-negative. That premise is unsound for as long as this bug exists. The test currently
passes only because the accumulation happens to stay positive; perturbing the velocity
field slightly (we hit it by changing Stokes.DEFAULT_PENALTY) flips it negative and the
test fails deterministically — 4/4 runs, while 4/4 pass unperturbed. It reads as a
penalty regression and is nothing of the sort.
Repro script: ~/+Simulations/penalty_default_evidence_2026-08-25/why_the_particle_test_fails.py
uw.function.evaluatereturns large negative values for an expression whose range isprovably non-negative, at points inside the domain.
Unknowns.Einv2issympy.sqrt((E**2).trace()/2)— the square root of a sum of squaresof a real symmetric tensor. It cannot be negative for any velocity field.
Lid-driven cavity,
UnstructuredSimplexBoxatcellSize=1/8, P2/P1, direct solve:All three hug the left wall just below the lid corner — the cavity's velocity
singularity, where
Einv2is large and varying sharply. Magnitudes of −0.1 to −0.5 arenot round-off.
Properties:
or one at a time, so it is not a batching or ordering effect.
all of those came back positive. The defect is not extrapolation.
penalty=0(min −0.4976) andpenalty=10(min −0.4838) alike.returning a value outside the expression's range.
A negative square root means the value returned is not the expression evaluated at that
point. The plausible shape is that a representation of the scalar is being interpolated
rather than the expression being evaluated pointwise from the field, and interpolation of
a sharply peaked non-negative function undershoots. Not confirmed — it needs someone who
knows the evaluate path to say which branch is taken here.
Why this surfaced
tests/test_0112_swarm_add_particles.py::test_swarm_access_write_after_add_particlesaccumulates
0.5 * evaluate(Einv2, swarm.data)and asserts the running total isnon-negative. That premise is unsound for as long as this bug exists. The test currently
passes only because the accumulation happens to stay positive; perturbing the velocity
field slightly (we hit it by changing
Stokes.DEFAULT_PENALTY) flips it negative and thetest fails deterministically — 4/4 runs, while 4/4 pass unperturbed. It reads as a
penalty regression and is nothing of the sort.
Repro script:
~/+Simulations/penalty_default_evidence_2026-08-25/why_the_particle_test_fails.py