Skip to content

fix(dpmodel): materialize fitting buffers on active backend#5841

Merged
njzjz merged 3 commits into
deepmodeling:masterfrom
njzjz-bot:fix/dpmodel-general-fitting-buffers-5642
Jul 25, 2026
Merged

fix(dpmodel): materialize fitting buffers on active backend#5841
njzjz merged 3 commits into
deepmodeling:masterfrom
njzjz-bot:fix/dpmodel-general-fitting-buffers-5642

Conversation

@njzjz-bot

@njzjz-bot njzjz-bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Fixes #5642

Summary

  • retain fitting statistics and constants as portable serialized state
  • materialize default fparam, fparam/aparam normalization statistics, case embeddings, and atomic output biases in the runtime namespace, dtype, and device immediately before use
  • apply the same boundary to PolarFitting.scale and constant_matrix, which had the identical failure mode during polar postprocessing
  • avoid mutating persistent attributes during forward calls, preserving serialization and backend-wrapper behavior

The complete affected set is nine arrays: default_fparam_tensor, fparam_avg, fparam_inv_std, aparam_avg, aparam_inv_std, case_embd, bias_atom_e, polar scale, and polar constant_matrix.

Why existing tests missed this

Cross-backend fitting tests already exercise default fparam, parameter statistics, biases, and polar outputs, but they instantiate backend wrappers that eagerly convert every NumPy attribute. Those objects are homogeneous before forward execution and therefore never expose the generic dpmodel boundary.

Direct dpmodel fitting tests use NumPy descriptors, atom types, parameters, and buffers, so the selected namespace is also NumPy and all operations are valid. Dedicated PyTorch, Paddle, and TensorFlow implementations maintain their own backend-native state and do not exercise this shared dpmodel implementation. No previous test combined a raw dpmodel fitting object, backend-native runtime inputs, and still-NumPy portable buffers.

Validation

  • 21 common dpmodel fitting tests passed
  • direct invariant-fitting regression covers all seven GeneralFitting buffers, default fparam, explicit aparam normalization, case embedding, and nonzero atomic biases
  • direct polar regression covers nontrivial per-type scale and diagonal shift buffers
  • both regressions assert Torch output backend/dtype/device and numerical parity with NumPy
  • ruff format .
  • ruff check .

Coding agent: Codex
Codex version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning effort: xhigh

Summary by CodeRabbit

  • Bug Fixes

    • Improved backend-safe handling of fitting constants for correct dtype/device placement during runtime (including normalization, case embeddings, and atom bias application).
    • Updated polarizability scaling/shift logic to use properly materialized buffers for consistent results across prediction backends.
  • Tests

    • Added regression tests validating runtime buffers follow the active backend for PyTorch inputs.
    • Added polarizability backend-boundary regression coverage for NumPy vs PyTorch parity.
    • Added JAX fitting tests to ensure stable outputs and gradient/tracing support.

Convert portable fitting constants locally into the runtime namespace, dtype, and device before default-fparam handling, parameter normalization, case embedding, atomic bias gathering, and polar scale/shift postprocessing.

Add direct dpmodel regressions with Torch runtime inputs while all nine persistent buffers remain NumPy, verifying backend identity and numerical parity without eager wrapper conversion.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@dosubot dosubot Bot added the bug label Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@njzjz, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7e527db1-3ee1-468f-9ed5-2276e5f1a1bd

📥 Commits

Reviewing files that changed from the base of the PR and between 6070a7e and e83155e.

📒 Files selected for processing (1)
  • source/tests/jax/test_fitting.py
📝 Walkthrough

Walkthrough

GeneralFitting and PolarFitting now materialize stored buffers on the active backend, dtype, and device before runtime operations. New Torch and JAX tests validate backend outputs and tracing behavior.

Changes

Backend buffer materialization

Layer / File(s) Summary
GeneralFitting runtime buffers
deepmd/dpmodel/fitting/general_fitting.py, source/tests/common/dpmodel/test_fitting_invar_fitting.py
Default and runtime fparams, aparams, case embeddings, and atom biases are converted to the active backend before use; a Torch boundary test validates output type, dtype, device, and values.
PolarFitting scale and shift buffers
deepmd/dpmodel/fitting/polarizability_fitting.py, source/tests/common/dpmodel/test_fitting_polar_backend.py
Scale and constant-matrix buffers are materialized before atom-type gathering; a Torch regression test compares polarizability with the NumPy result.
JAX fitting tracing validation
source/tests/jax/test_fitting.py
JAX fitting is tested under NNX JIT for forward execution and gradient tracing with portable buffer values.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: wanghan-iapcm

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: materializing fitting buffers on the active backend.
Linked Issues check ✅ Passed The PR addresses #5642 by materializing GeneralFitting buffers before backend operations and adds regression tests for backend-native execution.
Out of Scope Changes check ✅ Passed The PolarFitting and JAX test changes still support the same backend-buffer portability goal and do not appear unrelated.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.63%. Comparing base (6c3b985) to head (e83155e).
⚠️ Report is 27 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5841      +/-   ##
==========================================
+ Coverage   78.58%   78.63%   +0.05%     
==========================================
  Files        1050     1054       +4     
  Lines      120637   121768    +1131     
  Branches     4356     4404      +48     
==========================================
+ Hits        94801    95754     +953     
- Misses      24278    24441     +163     
- Partials     1558     1573      +15     

☔ View full report in Codecov by Harness.
📢 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 commented Jul 18, 2026

Copy link
Copy Markdown
Member

Possible reviewers based on changed lines, exact file history, and exact-file review history:

  • @wanghan-iapcm — 20 commits on changed files; 22 reviews on exact changed files (deepmd/dpmodel/fitting/general_fitting.py, deepmd/dpmodel/fitting/polarizability_fitting.py, source/tests/common/dpmodel/test_fitting_invar_fitting.py).
  • @anyangml — 12 commits on changed files (deepmd/dpmodel/fitting/general_fitting.py, deepmd/dpmodel/fitting/polarizability_fitting.py).

No review request was made automatically.

Coding agent: Codex
Codex version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning effort: xhigh

@njzjz
njzjz requested review from anyangml and wanghan-iapcm and removed request for anyangml and wanghan-iapcm July 18, 2026 07:18

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The fix is correct — all 9 buffers are materialized to the right float runtime reference's dtype/device, self.<buffer> is never mutated (numpy serialization preserved), and I confirmed the JAX side is safe: array_api_compat.device() on a traced tensor returns None (not a crash), so the pattern runs cleanly under jax.jit/jax.grad. One coverage note inline.

Comment thread deepmd/dpmodel/fitting/general_fitting.py
Exercise default frame parameters, frame/atom normalization buffers, case embeddings, and atom biases through an EnergyFittingNet forward and gradient under nnx.jit.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/tests/jax/test_fitting.py`:
- Around line 30-37: Strengthen the fitting test around the forward/gradient
invocation by snapshotting every configured portable buffer, including values
and namespace/type, then assert they are unchanged after execution. Add a
reference or differential-output check demonstrating that changing each
non-default buffer affects the result, while preserving the existing shape, NaN,
and gradient assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 70c6a27b-d4c3-4b96-8246-9e0af1df9dbb

📥 Commits

Reviewing files that changed from the base of the PR and between 44b79c5 and 6070a7e.

📒 Files selected for processing (1)
  • source/tests/jax/test_fitting.py

Comment thread source/tests/jax/test_fitting.py Outdated
Assert portable fitting buffers retain identity, namespace, and values across traced forward/gradient calls. Neutralize each configured buffer independently to prove it affects the output.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@njzjz
njzjz requested a review from wanghan-iapcm July 24, 2026 15:07

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The JAX-tracing gap is closed: test_runtime_buffers_support_nnx_jit_and_grad_tracing exercises the forward under nnx.jit and takes a parameter gradient through nnx.grad, with non-default values for every materialized buffer and fparam omitted so default_fparam_tensor is covered too. Both commits are test-only, no production change.

The follow-up test is a better one than I asked for. Asserting assertIs(current, original) on each buffer pins the numpy-storage-preserved invariant, and substituting a neutral value per buffer and requiring the output to change proves each materialization is load-bearing rather than the test passing vacuously.

For the record on the earlier concern about this reintroducing the #5736 device-lookup crash: I checked it directly rather than by inspection - array_api_compat.device() returns None on a JAX tracer, and this PR's xp.asarray(buf, dtype=..., device=device(t)) pattern runs clean under both jax.jit and jax.grad. The difference from #5736 is that the device is taken from a computed runtime value rather than a raw NNX variable. The new test locks that behaviour in.

@njzjz
njzjz added this pull request to the merge queue Jul 25, 2026
Merged via the queue into deepmodeling:master with commit c63bb90 Jul 25, 2026
60 of 61 checks passed
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.

[Code scan] Materialize GeneralFitting buffers on the active backend

3 participants