Skip to content

interpolation_matrix(nnn=1, order=1) silently returns a nearest-neighbour operator where the value path raises #443

Description

@lmoresi

Found in a retrospective adversarial review of #430 after merge.

The inconsistency

KDTree.rbf_interpolator_local rejects nnn=1 with order=1, because one neighbour cannot determine an affine tail:

kdt.rbf_interpolator_local(tgt, f, 1, 2, False, order=1)
# ValueError: order=1 needs at least dim + 2 neighbours ...

KDTree.interpolation_matrix does not:

T = kdt.interpolation_matrix(tgt, nnn=1, order=1)
# no error; nnz/row = 1 -- a nearest-neighbour operator

Measured on development at 4d043aeb.

Why it matters

The caller asked for a linear-exact operator and silently got a nearest-neighbour one, which reproduces constants only. Nothing in the returned object records the downgrade. The whole point of the order=1 path is a guarantee; handing back an operator that does not have it, without saying so, is the failure mode the rest of that PR was written to avoid.

It also contradicts the PR's own claim that the value and operator paths are built on one core and "cannot drift apart". They share _local_stencil, but _local_stencil early-returns for nnn == 1 before reaching the order handling, and only rbf_interpolator_local_from_kdtree carries the guard — interpolation_matrix does not.

Fix

Move the nnn == 1 and order == 1 guard into _local_stencil, so both callers inherit it. That is where the rest of the shared behaviour already lives.

Also worth tightening while there

  • interpolation_matrix with nnn > self.n raises RuntimeError: Error in rbf_interpolator_local_from_kdtree - a nearest neighbour wasn't found, naming a function the caller never invoked. Correct behaviour, confusing message.
  • The degenerate-fallback warnings.warn(..., stacklevel=3) is tuned for the value path's call depth; from interpolation_matrix the depth differs by one, so attribution is off by a frame.

Test gap

test_0102_kdtree_linear_rbf.py::test_interpolation_matrix_agrees_with_the_value_path parametrises order but not nnn, and never exercises nnn=1. A guard test on both entry points would have caught this.

Activity

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

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