Skip to content

evaluate() returns large negative values for a non-negative expression (sqrt invariant) at in-domain points near a boundary singularity #641

Description

@lmoresi

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

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