Say so when evaluate() answers for points this rank does not own (#606) - #655
Open
lmoresi wants to merge 1 commit into
Open
Say so when evaluate() answers for points this rank does not own (#606)#655lmoresi wants to merge 1 commit into
lmoresi wants to merge 1 commit into
Conversation
`uw.function.evaluate` is rank-local: it answers from the calling rank's
portion of the mesh. In parallel a point owned by another rank cannot be
located here, so the locator extrapolates and returns a plausible number that
is wrong -- and two ranks asked the identical question return different
answers. Nothing in the signature, docstring or return value said so.
Measured on a P2 field holding x^2 + 2y^2, which P2 represents exactly, so any
discrepancy is location and not approximation. Query set = every rank's own
DOF coordinates allgathered, i.e. every point is a mesh node:
np=1 all coords max error 8.9e-16
np=2 own coords max error 6.7e-16
np=2 all coords, rank 0 / rank 1 1.48 / 0.54
np=4 all coords, worst rank 2.59
on a field whose whole range is [0, 3], with two thirds of the points wrong at
np=4. `global_evaluate` is exact throughout.
The fix is to stop being silent, not to change the answer. The extrapolation
mask turns out to be an EXACT detector of the affected points -- 69 flagged and
69 wrong at np=2, 120 and 120 at np=4, with no wrong-but-unflagged and no
flagged-but-fine, and a worst unflagged error of 8.9e-16 -- so a warning built
on it has neither false negatives nor false positives here.
It is now requested unconditionally, because asking costs nothing: 0.0073 s per
call against 0.0075 s without, on 1969 points, i.e. inside the noise. The
locator must decide whether it located a point in order to fall back, so the
mask is already known.
Serial is deliberately NOT warned about: there an extrapolated point is one
genuinely outside the domain, which is a legitimate request.
The regression asserts both directions, since a warning that fired on correct
rank-local use would be noise on every properly written parallel script: own
coordinates must stay exact AND silent; a cross-rank query must warn. It fails
without the guard (verified by disabling it in the installed copy) and passes
with it, at np=1 and np=2.
Not fixed here: the underlying inability to answer for a non-owned point.
`global_evaluate` already does that correctly, and this points callers at it.
Underworld development team with AI support from Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the silent half of #606.
The defect
uw.function.evaluateis rank-local — it answers from the calling rank's portion of the mesh. In parallel, a point owned by another rank cannot be located here, so the locator extrapolates and returns a plausible number that is wrong. Nothing in the signature, docstring or return value said so.Reproduced exactly, including the rank disagreement. P2 field holding
x^2 + 2y^2(exact in P2, so any discrepancy is location, not approximation); query set is every rank's own DOF coordinates allgathered, so every point is a mesh node:on a field whose entire range is [0, 3].
global_evaluateis exact throughout.The fix is to stop being silent, not to change the answer
global_evaluatealready answers correctly; this points callers there. Two measurements made that clean:The extrapolation mask is an exact detector. 69 flagged / 69 wrong at np=2, 120 / 120 at np=4 — no wrong-but-unflagged, no flagged-but-fine, worst unflagged error 8.9e-16. Checked before building on it, because a warning with false negatives would be worse than none.
Asking for it is free. 0.0073 s/call with, 0.0075 s/call without, on 1969 points — inside the noise. The locator has to decide whether it located a point in order to fall back, so the mask already exists. It is now requested unconditionally.
Scope
Serial is deliberately not warned about. There an extrapolated point is one genuinely outside the domain — a legitimate request, and warning would be noise.
The regression asserts both directions, because a warning that fired on correct rank-local use would be noise in every properly written parallel script:
It fails without the guard (verified by disabling it in the installed copy and re-running at np=2) and passes with it, at np=1 and np=2.
The docstring now carries the contract as a
.. warning::with the measured numbers. That absence was half of what #606 was actually reporting.Not fixed here: the underlying inability to answer for a non-owned point. That is what
global_evaluateis for, and #551 covers the locator work.Tests:
level_1 and tier_a1074 passed, 0 failed; six evaluate-focused suites 57 passed; new parallel regression green at np=1 and np=2.Underworld development team with AI support from Claude Code