Skip to content

uw.function.evaluate returns wrong values for P1 fields at points exactly on cell edges (3D) #432

Description

@lmoresi

Found while validating an MG prolongation against evaluate as the reference — the reference was the thing that was wrong.

Symptom

Evaluating a degree-1 scalar MeshVariable at points lying exactly on coarse-cell edges (3D tetrahedral mesh) returns values that are not the FE interpolant at those points.

Independent check: each failing point lies on exactly one coarse edge (a,b), so the P1 value there is unambiguously 0.5*(u_a + u_b). Comparing that against evaluate:

point independent edge-truth evaluate
504 +0.700344 +0.923709
565 +0.323892 −0.728195
2175 −0.287598 −2.759645
2177 −2.122083 −6.128067
2178 −0.119434 +0.782410
2205 +0.361674 +0.739306

Errors are O(1), not round-off. Affected points are a small fraction (2–12 per few thousand) but the wrong values are badly wrong.

Why it matters

These are not exotic points. Every vertex introduced by edge bisection lies exactly on a parent edge, so any workflow evaluating a field at refined-mesh vertices, or at points shared between cells, is exposed. It is silent — no warning, no NaN.

Reproducer sketch

base  = uw.meshing.UnstructuredSimplexBox(minCoords=(0.,0.,0.), maxCoords=(1.,1.,1.),
                                          cellSize=0.5, refinement=1, qdegree=2)
child = base.adapt(metric, max_levels=2)          # child vertices lie on parent edges
uc = uw.discretisation.MeshVariable("uc", coarse_mesh, 1, degree=1)
uc.data[:, 0] = np.random.standard_normal(uc.data.shape[0])
fx  = child.dm.getCoordinatesLocal().array.reshape(-1, 3)
val = uw.function.evaluate(uc.sym[0], fx)         # wrong at points on coarse edges

Compare against 0.5*(u_a + u_b) for the coarse edge each point sits on.

Full script: /tmp/who_is_wrong.py pattern — locate the coarse edge whose midpoint matches the query point, take the P1 value along it.

Suspected cause

Point location for a query lying exactly on a cell boundary. The point is in the closure of several cells; if location picks a cell and the basis is then evaluated with reference coordinates slightly outside that cell, the result extrapolates rather than interpolates. This repo has prior form here — see the quad TOP-face silent-zeros issue.

Notes

  • 2D appears unaffected in the same test (0 disagreements across three refinement passes); 3D shows 2–12 per pass.
  • A correct-by-construction MG prolongation agrees with the edge-truth in every case, so the discretisation and the field data are fine — only evaluate disagrees.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions