Skip to content

Conversation

@njzjz
Copy link
Member

@njzjz njzjz commented Jan 7, 2026

This class does not need torchscript, so we can reuse dpmodel codes to reduce redundancy.

Summary by CodeRabbit

  • Bug Fixes

    • Ensure tensors and masks are allocated on the same device as input data, fixing device-consistency issues across neighbor-list and neighbor-stat computations.
  • Refactor

    • Consolidated neighbor-stat computation into a shared implementation and simplified local orchestration while preserving public interfaces and behaviors.

✏️ Tip: You can customize this high-level summary in your review settings.

This class does not need torchscript, so we can reuse dpmodel codes to reduce redundancy.
Copilot AI review requested due to automatic review settings January 7, 2026 19:54
@github-actions github-actions bot added the Python label Jan 7, 2026
@dosubot dosubot bot added the enhancement label Jan 7, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

Device-consistency fixes and a small refactor: array creations in neighbor-list and neighbor-stat utilities now explicitly allocate on the input device; PyTorch-side NeighborStat now delegates to the dpmodel NeighborStatOP implementation.

Changes

Cohort / File(s) Summary
Device-aware arrays in dpmodel utils
deepmd/dpmodel/utils/neighbor_stat.py, deepmd/dpmodel/utils/nlist.py
New arrays (identity/eye, ones, pad, aidx, xi/yi/zi, xyz, shift vectors, etc.) are created with explicit device assignment via array_api_compat.device(...), ensuring masks, padding and ghost-extension tensors reside on the same device as inputs.
PyTorch neighbor-stat refactor
deepmd/pt/utils/neighbor_stat.py
Removed local NeighborStatOP implementation and torch.jit.script wrapping; module now imports and instantiates NeighborStatOP from deepmd.dpmodel.utils.neighbor_stat, preserving the public NeighborStat interface while delegating the operational logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • feat(jax): neighbor stat #4258: Edits to dpmodel/utils/neighbor_stat.py that change array construction and device/array-api handling, closely related to these device-allocation changes.

Suggested reviewers

  • wanghan-iapcm
  • iProzd
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor(pt): reuse dpmodel NeighborStatOP' clearly and accurately summarizes the main change—refactoring the PyTorch module to reuse the dpmodel implementation rather than maintaining a separate TorchScript version.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d15eab2 and 3b61ddf.

📒 Files selected for processing (1)
  • deepmd/pt/utils/neighbor_stat.py
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: njzjz
Repo: deepmodeling/deepmd-kit PR: 4144
File: source/api_cc/tests/test_deeppot_dpa_pt.cc:166-246
Timestamp: 2024-09-19T04:25:12.408Z
Learning: Refactoring between test classes `TestInferDeepPotDpaPt` and `TestInferDeepPotDpaPtNopbc` is addressed in PR #3905.
Learnt from: njzjz
Repo: deepmodeling/deepmd-kit PR: 4144
File: source/api_cc/tests/test_deeppot_dpa_pt.cc:166-246
Timestamp: 2024-10-08T15:32:11.479Z
Learning: Refactoring between test classes `TestInferDeepPotDpaPt` and `TestInferDeepPotDpaPtNopbc` is addressed in PR #3905.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (37)
  • GitHub Check: Build wheels for cp311-manylinux_x86_64
  • GitHub Check: Build wheels for cp311-win_amd64
  • GitHub Check: Build wheels for cp311-macosx_arm64
  • GitHub Check: Build wheels for cp310-manylinux_aarch64
  • GitHub Check: Build wheels for cp311-macosx_x86_64
  • GitHub Check: Analyze (c-cpp)
  • GitHub Check: Build C++ (rocm, rocm)
  • GitHub Check: Build C++ (cuda120, cuda)
  • GitHub Check: Test Python (8, 3.13)
  • GitHub Check: Test Python (11, 3.13)
  • GitHub Check: Test Python (10, 3.10)
  • GitHub Check: Test Python (8, 3.10)
  • GitHub Check: Test Python (12, 3.10)
  • GitHub Check: Test Python (2, 3.10)
  • GitHub Check: Test Python (2, 3.13)
  • GitHub Check: Test Python (11, 3.10)
  • GitHub Check: Test Python (3, 3.10)
  • GitHub Check: Test Python (5, 3.13)
  • GitHub Check: Test Python (9, 3.13)
  • GitHub Check: Test Python (6, 3.13)
  • GitHub Check: Test Python (1, 3.13)
  • GitHub Check: Test Python (5, 3.10)
  • GitHub Check: Test Python (10, 3.13)
  • GitHub Check: Test Python (12, 3.13)
  • GitHub Check: Test Python (7, 3.13)
  • GitHub Check: Test Python (7, 3.10)
  • GitHub Check: Test Python (4, 3.10)
  • GitHub Check: Test Python (4, 3.13)
  • GitHub Check: Test Python (9, 3.10)
  • GitHub Check: Test Python (1, 3.10)
  • GitHub Check: Test Python (6, 3.10)
  • GitHub Check: Test Python (3, 3.13)
  • GitHub Check: Test C++ (true, false, false, true)
  • GitHub Check: Test C++ (true, true, true, false)
  • GitHub Check: Test C++ (false, true, true, false)
  • GitHub Check: Test C++ (false, false, false, true)
  • GitHub Check: Build C library (2.18, libdeepmd_c.tar.gz)
🔇 Additional comments (3)
deepmd/pt/utils/neighbor_stat.py (3)

44-44: LGTM!

The instantiation correctly passes through the constructor parameters to the imported NeighborStatOP.


9-11: The concern about compatibility between dpmodel NeighborStatOP and torch tensors is unfounded. The dpmodel implementation uses array_api_compat, which is a standard Python library specifically designed to provide a unified array interface across different backends (NumPy, PyTorch, JAX, etc.). The array_api_compat.array_namespace() call automatically detects the array type and backend, and array_api_compat.device() properly extracts and respects device placement from input arrays. The pt module correctly handles the conversion by passing torch tensors to the dpmodel operation and converting results back to numpy, which is the intended pattern for this architecture.

Likely an incorrect or invalid review comment.


92-99: The code is correct. The dpmodel NeighborStatOP uses array_api_compat.array_namespace() to detect whether inputs are torch tensors or numpy arrays, automatically routing operations through the appropriate backend. Device handling is explicitly managed via array_api_compat.device() on line 90 of the dpmodel implementation. The PT wrapper's conversion pattern (numpy→torch→numpy) is intentional and correct. This code path is explicitly tested in the pytorch backend tests, confirming the implementation works as designed.

Likely an incorrect or invalid review comment.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
deepmd/pt/utils/neighbor_stat.py (1)

24-25: Minor: Update docstring to reflect implementation change.

The docstring states "Neighbor statistics using pure NumPy" but the implementation now uses NeighborStatOP from dpmodel, which operates via array_api_compat and can work with various backends including PyTorch tensors.

📝 Suggested docstring update
 class NeighborStat(BaseNeighborStat):
-    """Neighbor statistics using pure NumPy.
+    """Neighbor statistics using PyTorch.

     Parameters
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be3b876 and d15eab2.

📒 Files selected for processing (3)
  • deepmd/dpmodel/utils/neighbor_stat.py
  • deepmd/dpmodel/utils/nlist.py
  • deepmd/pt/utils/neighbor_stat.py
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: njzjz
Repo: deepmodeling/deepmd-kit PR: 4144
File: source/api_cc/tests/test_deeppot_dpa_pt.cc:166-246
Timestamp: 2024-09-19T04:25:12.408Z
Learning: Refactoring between test classes `TestInferDeepPotDpaPt` and `TestInferDeepPotDpaPtNopbc` is addressed in PR #3905.
Learnt from: njzjz
Repo: deepmodeling/deepmd-kit PR: 4144
File: source/api_cc/tests/test_deeppot_dpa_pt.cc:166-246
Timestamp: 2024-10-08T15:32:11.479Z
Learning: Refactoring between test classes `TestInferDeepPotDpaPt` and `TestInferDeepPotDpaPtNopbc` is addressed in PR #3905.
📚 Learning: 2024-10-08T15:32:11.479Z
Learnt from: njzjz
Repo: deepmodeling/deepmd-kit PR: 4160
File: deepmd/dpmodel/utils/env_mat.py:52-64
Timestamp: 2024-10-08T15:32:11.479Z
Learning: Negative indices in `nlist` are properly handled by masking later in the computation, so they do not cause issues in indexing operations.

Applied to files:

  • deepmd/dpmodel/utils/nlist.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (42)
  • GitHub Check: CodeQL analysis (python)
  • GitHub Check: Agent
  • GitHub Check: Test Python (10, 3.10)
  • GitHub Check: Test Python (11, 3.10)
  • GitHub Check: Test Python (12, 3.13)
  • GitHub Check: Test Python (9, 3.10)
  • GitHub Check: Test Python (12, 3.10)
  • GitHub Check: Test Python (5, 3.13)
  • GitHub Check: Test Python (11, 3.13)
  • GitHub Check: Test Python (6, 3.10)
  • GitHub Check: Test Python (6, 3.13)
  • GitHub Check: Test Python (10, 3.13)
  • GitHub Check: Test Python (8, 3.13)
  • GitHub Check: Test Python (3, 3.13)
  • GitHub Check: Test Python (9, 3.13)
  • GitHub Check: Test Python (8, 3.10)
  • GitHub Check: Test Python (4, 3.10)
  • GitHub Check: Test Python (1, 3.10)
  • GitHub Check: Analyze (python)
  • GitHub Check: Test Python (1, 3.13)
  • GitHub Check: Test Python (2, 3.10)
  • GitHub Check: Analyze (c-cpp)
  • GitHub Check: Test Python (2, 3.13)
  • GitHub Check: Test Python (3, 3.10)
  • GitHub Check: Test Python (5, 3.10)
  • GitHub Check: Test Python (7, 3.10)
  • GitHub Check: Test Python (7, 3.13)
  • GitHub Check: Test Python (4, 3.13)
  • GitHub Check: Build wheels for cp310-manylinux_aarch64
  • GitHub Check: Test C++ (true, true, true, false)
  • GitHub Check: Test C++ (false, false, false, true)
  • GitHub Check: Test C++ (true, false, false, true)
  • GitHub Check: Build C++ (cuda120, cuda)
  • GitHub Check: Test C++ (false, true, true, false)
  • GitHub Check: Build wheels for cp311-win_amd64
  • GitHub Check: Build C++ (clang, clang)
  • GitHub Check: Build wheels for cp311-macosx_x86_64
  • GitHub Check: Build C++ (cpu, cpu)
  • GitHub Check: Build C++ (rocm, rocm)
  • GitHub Check: Build wheels for cp311-manylinux_x86_64
  • GitHub Check: Build wheels for cp311-macosx_arm64
  • GitHub Check: Build C library (2.18, libdeepmd_c.tar.gz)
🔇 Additional comments (8)
deepmd/dpmodel/utils/neighbor_stat.py (1)

90-90: LGTM! Device-aware array creation for cross-backend compatibility.

The explicit device=array_api_compat.device(diff) ensures the identity matrix is allocated on the same device as the input-derived diff tensor. This is essential for PyTorch backend usage where device mismatches would cause runtime errors.

deepmd/dpmodel/utils/nlist.py (5)

120-122: LGTM! Device-consistent identity matrix for zero-distance correction.

The device=array_api_compat.device(diff) ensures the eye matrix is on the same device as the computed differences, preventing device mismatch errors on GPU backends.


132-154: LGTM! Device-aware padding for neighbor list extension.

Both padding arrays correctly inherit the device from their source arrays (rr and nlist respectively), ensuring consistent device placement when extending the neighbor list.


238-243: LGTM! Device-aware padding in multiple neighbor list builder.

The padding array correctly uses device=array_api_compat.device(nlist) to ensure it resides on the same device as the input neighbor list.


300-305: LGTM! Device-aware atom index creation.

The aidx array correctly uses device=array_api_compat.device(atype) to ensure the index array resides on the same device as the atom types.


317-351: LGTM! Consistent device propagation for ghost coordinate generation.

All intermediate arrays (xi, yi, zi, and the unit vectors for outer products) are correctly allocated on the same device as the input coord tensor. The unit vectors appropriately use the device from their corresponding index arrays, maintaining device consistency throughout the ghost extension computation.

deepmd/pt/utils/neighbor_stat.py (2)

92-98: LGTM! Correct tensor conversion flow.

The conversion chain from NumPy arrays to PyTorch tensors on DEVICE, through the NeighborStatOP call, and back to NumPy via .detach().cpu().numpy() is correct.


19-21: Verify array-api-compat torch tensor compatibility through existing test suite.

The refactoring to reuse NeighborStatOP from dpmodel is sound—the implementation correctly uses array_api_compat.array_namespace() to abstract array operations (line 72 of dpmodel/utils/neighbor_stat.py), and the PyTorch wrapper properly converts tensors to/from numpy. However, ensure that the pytorch backend tests (test_neighbor_stat_pt in source/tests/consistent/test_neighbor_stat.py) pass to confirm that array-api-compat handles torch tensors correctly across all operations, particularly xp.bool dtype specification and device handling with xp.eye().

@codecov
Copy link

codecov bot commented Jan 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.13%. Comparing base (be3b876) to head (3b61ddf).
⚠️ Report is 5 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5137      +/-   ##
==========================================
- Coverage   82.14%   82.13%   -0.01%     
==========================================
  Files         709      709              
  Lines       72511    72480      -31     
  Branches     3615     3615              
==========================================
- Hits        59565    59534      -31     
- Misses      11782    11783       +1     
+ Partials     1164     1163       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@njzjz njzjz requested review from iProzd and wanghan-iapcm January 8, 2026 02:43
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

njzjz added a commit to njzjz/deepmd-kit that referenced this pull request Jan 8, 2026
@iProzd iProzd added this pull request to the merge queue Jan 9, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jan 9, 2026
@njzjz njzjz added this pull request to the merge queue Jan 9, 2026
Merged via the queue into deepmodeling:master with commit 8f021aa Jan 9, 2026
70 checks passed
@njzjz njzjz deleted the refact=pt-neigh-stat branch January 9, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants