Skip to content

Add regular-lattice point deformation functional#1810

Draft
loliverhennigh wants to merge 1 commit into
codex/grid-to-point-interpolation-fixesfrom
codex/lattice-deformation
Draft

Add regular-lattice point deformation functional#1810
loliverhennigh wants to merge 1 commit into
codex/grid-to-point-interpolation-fixesfrom
codex/lattice-deformation

Conversation

@loliverhennigh

@loliverhennigh loliverhennigh commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

PhysicsNeMo Pull Request

Description

Adds physicsnemo.nn.functional.lattice_deform_points, a differentiable functional that deforms unbatched 1D, 2D, or 3D points from displacement controls stored on a regular lattice.

The public functional provides:

  • Torch and Warp implementations through FunctionSpec;
  • linear, C1 smooth-step, and C2 smooth-step interpolation;
  • optional per-point floating weights or boolean masks;
  • gradients with respect to points, control displacements, and floating weights;
  • benchmark hooks, public exports, focused API tests, and a checked-in visualization PNG.

The implementation composes grid_to_point_interpolation rather than adding another raw Warp kernel surface. A separate lattice functional is intentional: its dense regular-grid and bounds contract is distinct from the sparse control-point/radius contract of morph_points.

The functional documentation follows the existing geometry-page pattern: autofunction, a short visualization description, and the image. It contains no Python example block and no checked-in image-generation script.

Validation

  • 77 passed in test_lattice_deform_points.py
  • 47 passed in the prerequisite interpolation suite
  • 167 passed, 16 skipped across geometry functionals and grid-to-point interpolation
  • Torch full-graph forward/backward and Warp compiled-forward tests pass
  • all changed-file pre-commit hooks pass

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The functional documentation is up to date with these changes.
  • The CHANGELOG.md is up to date with these changes.
  • An issue is linked to this pull request.
  • Model implementation standards are not applicable.

Dependencies

@copy-pr-bot

copy-pr-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@loliverhennigh
loliverhennigh marked this pull request as ready for review July 8, 2026 21:15
@mehdiataei

Copy link
Copy Markdown
Collaborator

Hey Oliver, this is great! We were just chatting with Peter about this. I’m wondering whether it would be better to wait until the morph is merged, and whether this PR can adapt the API exposed to users under transformations.deform (we can discuss the details). Could you maybe start by pulling that PR and applying the API exposure in a similar way?

@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces lattice_deform_points, a differentiable geometry functional that displaces unbatched 1–3D points using control values stored on a regular lattice, and fixes two prerequisite bugs in grid_to_point_interpolation: inclusive-boundary stride-2 stencils could select a zero-padding cell on two-point grids, and torch.Tensor construction without explicit dtype was inheriting the process-wide default and promoting float32 outputs.

  • Boundary stencil fix (Torch): _grid_knn_idx now clamps center_idx to the last real-to-real cell at inclusive grid boundaries, and interpolation_torch snaps dist_vec entries to exact 0/1 fractions via the x - x.detach() gradient-retaining trick.
  • Boundary stencil fix (Warp): New select_padded_stencil_center / padded_stencil_fraction helpers in _warp_common.py replace bare wp.int32(pos) casts with tolerance-guarded boundary checks applied symmetrically to all 1D/2D/3D stride-2 forward and backward kernels.
  • New functional: LatticeDeformPoints / lattice_deform_points normalizes world coordinates to [0, 1], delegates to grid_to_point_interpolation for displacement lookup, and adds the displacement to the original points, with full Torch and Warp dispatch, optional per-point weights/masks, and an empty-batch short-circuit that preserves autograd edges.

Important Files Changed

Filename Overview
physicsnemo/nn/functional/geometry/lattice_deform_points/utils.py New validation and normalization helpers; empty_lattice_deformation uses sum() * 0 to retain gradient edges which will produce NaN gradients if control displacements contain Inf values.
physicsnemo/nn/functional/geometry/lattice_deform_points/lattice_deform_points.py New public API class using FunctionSpec with Warp/Torch dispatch; well-documented with complete parameter, return, and notes sections.
physicsnemo/nn/functional/interpolation/grid_to_point_interpolation/_torch_impl.py Two bugfixes: dtype propagation in nearest_neighbor_weighting and boundary stencil snapping for stride-2 grids to prevent zero-padding cell selection at inclusive boundaries.
physicsnemo/nn/functional/interpolation/_warp_common.py Adds select_padded_stencil_center and padded_stencil_fraction Warp functions fixing the boundary stencil bug with a tolerance of 4x eps x size.
physicsnemo/nn/functional/interpolation/grid_to_point_interpolation/_warp_impl/kernels.py All stride-2 forward and backward kernels updated to use the new boundary helpers instead of bare wp.int32(pos) casts across all 1D/2D/3D paths.
physicsnemo/nn/functional/interpolation/grid_to_point_interpolation/_warp_impl/launch_backward.py All wp.from_torch calls now pass requires_grad=False, preventing Warp-side gradient allocation warnings.
test/nn/functional/geometry/test_lattice_deform_points.py Comprehensive 1021-line test suite covering oracles, boundary gradients, dtype/device checks, empty-points, and Torch/Warp parity.
test/nn/functional/interpolation/test_grid_to_point_interpolation.py New tests validate the two boundary fixes: exact interpolation at inclusive grid boundaries and absence of Warp UserWarning.

Reviews (1): Last reviewed commit: "Add regular-lattice point deformation fu..." | Re-trigger Greptile

Comment on lines +269 to +271
zero = control_displacements.sum() * 0
if point_weights is not None and point_weights.is_floating_point():
zero = zero + point_weights.sum() * 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Gradient edge via sum() * 0 is NaN-unsafe for Inf inputs. If any value in control_displacements is ±Inf, then sum() is Inf and Inf * 0 = NaN under IEEE 754. The empty-output tensor itself carries no elements, but NaN propagates through the autograd graph so control_displacements.grad becomes all-NaN on backward instead of all-zero. The idiomatic alternative is to form the scalar through a zero-valued linear combination that stays finite.

Suggested change
zero = control_displacements.sum() * 0
if point_weights is not None and point_weights.is_floating_point():
zero = zero + point_weights.sum() * 0
zero = (control_displacements.reshape(-1)[:1] * 0.0).sum()
if point_weights is not None and point_weights.is_floating_point():
zero = zero + (point_weights.reshape(-1)[:1] * 0.0).sum()

@loliverhennigh
loliverhennigh marked this pull request as draft July 8, 2026 21:33
@loliverhennigh
loliverhennigh force-pushed the codex/lattice-deformation branch from a51d6f6 to 26ac4c6 Compare July 8, 2026 22:02
@loliverhennigh
loliverhennigh changed the base branch from main to codex/grid-to-point-interpolation-fixes July 8, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants