Fix per-atom error in the Laplacian meta-GGA nuclear gradient - #228
susilehtola wants to merge 1 commit into
Conversation
lapl(rho) = 2 X . lapl(B) + 2 sum_c X_c . d_c B, with X = fac P B and
X_c = fac P d_c B. One term of its nuclear derivative contracts the BARE
d_x B against 2 P lapl(B); the code contracted (2 P d_x B) against the
bare lapl(B) instead.
The two are equal only after summing over every basis function, so the
total gradient was right and translational invariance held -- but the sum
in exc_grad_local_work_ is restricted to the shells on one atom, so the
force on each individual atom was wrong. Measured against a central
difference of eval_exc over a displaced molecule and displaced basis
(benzene/cc-pVDZ/UltraFine, atom 0, worst of the three components):
before after
MGGA_X_BR89 1.595e-01 1.604e-09
MGGA_X_R2SCANL 1.383e-01 9.365e-08
MGGA_X_SCANL 1.608e-01 --
Three independent Laplacian functionals fail identically beforehand,
including BR89, which has none of SCAN's numerical difficulty; the sign
of the error also differs between them, which no fixed numerical defect
would do. LDA (5.1e-09), GGA (2.1e-09) and tau-only meta-GGA (4.3e-09)
are unaffected and unchanged, as are energies and potentials at every
rung.
The matrix contracted with the Laplacian is not otherwise formed, so it
is built with one extra eval_xmat and one extra block of host_data.zmat,
allocated only when needs_laplacian.
RKS only: exc_grad already refuses needs_laplacian with is_uks.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
I reproduced #227 and validated the exact change in this PR on base commit I used GauXC's benzene/cc-pVDZ fixture and density with builtin The FD rebuilds the molecule, displaced basis, grid, load balance and molecular weights for both geometries. With PR commit As an unaffected control, SVWN5 agrees with its molecular FD to I also instrumented the implicated host loop to export both contraction forms from that same molecular run. An AADC-NG call-site trace over the exported 12-atom state attributes atom 0 x as: The traced correction is Both all-atom sums remain near zero ( This supports the contraction diagnosis and patch already documented here. If useful, I can contribute the compact independent regression fixture and the live-state trace summary. For disclosure: the source-attributed replay used MatLogica AADC-NG. The GauXC molecular reproducer and central-difference oracle are independent and do not require proprietary tooling. The trace replays values exported inside GauXC's real host loop; it does not operator-overload the whole GauXC integrator. |
Fixes #227.
The defect
lapl(rho) = 2 X . lapl(B) + 2 sum_c X_c . d_c B, withX = fac P BandX_c = fac P d_c B(host driver,eval_uvvar_mgga_rks). Differentiating withrespect to a nuclear coordinate gives, per basis function on the moving atom,
(1) and (3) were correct. (2) was not — the code had
(2 P d_x B) . lapl(B),i.e. the two indices swapped:
The two forms coincide only after summing over every basis function (relabel
mu <-> nu, P symmetric). The sum in
exc_grad_local_work_is restricted to theshells on one atom, so the total gradient came out right — and translational
invariance held, being imposed explicitly by the parent-atom subtraction — while
the force on each individual atom was wrong by ~15%. A geometry optimisation
drifts; every invariance check passes.
The change
2 P lapl(B)is not otherwise formed, so it is built with one extraeval_xmatand one extra block ofhost_data.zmat, allocated only whenneeds_laplacian:+24 / -4, one file, RKS only (
exc_gradalready refusesneeds_laplacianwithis_uks).Verification
eval_exc_gradagainst a central difference ofeval_excover a displacedmolecule and displaced basis — the grid and its partition weights ride on
the atoms, so this is a total derivative that shares no algebra with the
gradient code. Benzene / cc-pVDZ / UltraFine, atom 0, h = 1e-4, worst relative
deviation over the three Cartesian components:
Three independent Laplacian functionals fail identically beforehand, including
BR89, which is plain Becke-Roussel exchange with none of SCAN's numerical
difficulty. The sign of the error differs between BR89 and r2SCANL/SCANL,
which no fixed numerical defect would do. The analytic value moves onto the
finite difference that was already there:
Energies and potentials were never affected and still are not:
VXCagainst acentral difference of
Excin the density matrix gives the ratio 2 (the RKSconvention) to 8 digits at every rung, Laplacian included.
ctest/gauxc_test: all 3640979 assertions in 56 test cases pass,unchanged. No test covers this path —
tests/ref_dataholds two Laplacianmeta-GGA reference files and neither contains a gradient, which is how the error
survived.
Not covered here
Laplacian functionals outright
(
"Device EXC Gradients + Laplacian Dependent MGGAs Not Yet Implemented"),so there is no device Laplacian gradient to correct.
GAUXC_GENERIC_EXCEPTION).Happy to follow up with that as a separate PR.
🤖 Generated with Claude Code