Skip to content

Reset component caches when forces get a new positions tensor - #278

Open
thebreadishard wants to merge 2 commits into
grimme-lab:mainfrom
thebreadishard:reset-caches-new-positions
Open

thebreadishard wants to merge 2 commits into
grimme-lab:mainfrom
thebreadishard:reset-caches-new-positions

Conversation

@thebreadishard

Copy link
Copy Markdown

Fixes #277.

requires_positions_grad now keeps a weak reference to the positions tensor that the last graph was built for. When forces (or
another method behind that decorator) gets a different tensor, it first clears the classical, interaction and integral caches. These are
the caches Calculator.reset() clears, apart from the result cache, which is already keyed on the tensor id. Calls with the same tensor
keep using the caches, so repeated derivatives of one graph are not slowed down.

Test: test/test_calculator/test_cache/test_positions_graph.py covers forces after energy, and forces twice with a new tensor,
for GFN1 with the PyTorch driver and, when libcint is available, for GFN1 and GFN2 with libcint. All 6 cases fail on main (2070660) and
pass on this branch.

Other tests run locally (Python 3.11, torch 2.14.1 CPU, the tad versions main pins, tad-libcint 0.3.0):

  • test/test_calculator: 60 passed
  • test/test_singlepoint/test_grad_gfn1.py: 42 passed
  • test/test_singlepoint/test_grad_gfn2.py: 18 passed
  • test/test_singlepoint/test_hess.py: 3 passed
  • test/test_properties/test_hessian.py: 7 passed
  • test/test_properties/test_vibration.py: 3 passed
  • test/test_properties/test_dipole_deriv.py: 8 passed

The rest of the suite was not run.

🤖 Generated with Claude Code

thebreadishard and others added 2 commits October 18, 2026 17:13
The classical, interaction and integral caches are validated by the values of
the positions only. A second positions tensor with equal values - for example
after energy(), which builds the caches without a graph, or a second forces()
call with a fresh tensor - reused caches tied to another tensor, so autograd
missed their dependence on the new positions and the forces were wrong (water,
GFN2: z(O) +0.0755 instead of -0.0030 E_h/bohr).

requires_positions_grad now clears those caches when the positions tensor is
not the one the last graph was built for (tracked by a weak reference). Calls
with the same tensor keep using the caches.
@codecov

codecov Bot commented Oct 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.38%. Comparing base (2070660) to head (53caca8).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #278   +/-   ##
=======================================
  Coverage   88.38%   88.38%           
=======================================
  Files         215      215           
  Lines       10784    10791    +7     
  Branches     1241     1242    +1     
=======================================
+ Hits         9531     9538    +7     
  Misses        902      902           
  Partials      351      351           

☔ 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.

@marvinfriede

Copy link
Copy Markdown
Member

Thanks! Can this be merged?

This branch was successfully deployed

1 active deployment
codecov — 53caca81 Deployed Oct 18, 2026 by pre-commit-ci[bot] via Upload to Codecov #331
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.

Forces are wrong when the calculator already holds caches from another positions tensor with the same values

2 participants