XC nuclear Hessian: basis, moving-grid and partition-weight classes - #230
Open
susilehtola wants to merge 1 commit into
Open
susilehtola wants to merge 1 commit into
susilehtola wants to merge 1 commit into
Conversation
eval_exc_hess(P, settings) returns the 3N x 3N second derivative of the
XC energy at fixed density matrix, on the host replicated integrator.
IntegratorSettingsEXC_HESS mirrors IntegratorSettingsEXC_GRAD:
- include_weight_derivatives = true (default): the basis functions ride
their atoms, the grid points ride their parent atoms, and the
partition weights change. A task's energy depends on R_A - R_C only
(C its parent atom), so each task is accumulated in coordinates
excluding C and C's rows and columns are restored by translational
invariance. The weight class adds w'' e + w' e'^T + e' w'^T per point,
with the Becke or SSF weight derivatives in log form
dw/w = a_C - g, g = sum_D pi_D a_D
d2w/w = (a_C-g)(a_C-g)^T + B_C - sum_D pi_D [(a_D-g)(a_D-g)^T + B_D]
(pi_D = P_D/Z, a_D = d ln P_D), finite as P_C -> 0. LKO throws.
- include_weight_derivatives = false: the basis class alone (fixed grid
and weights), the analogue of the gradient's Hellmann-Feynman option.
The basis class sums generated per-function rows over the shells of
each atom, contracts the two row sets as an outer product, and adds the
Pulay and same-atom terms. The Pulay term is exactly bilinear in the
displaced rows, alpha(u)^T W(g) beta(v), so it is contracted with GEMMs.
The per-point kernels (host/gauxc_hess_kernel.hpp) and their call sites
(host/gauxc_hess_call_*.inc) are generated by xckernel and should be
regenerated, not edited:
python -m xckernel.emitters.gauxcwriter --emit-dir src/xc_integrator/local_work_driver/host
Call-site arguments are bound by name from each kernel's signature:
GauXC's names (vgamma, ...) sort differently from Libxc's (vsigma, ...),
and a hand-written meta-GGA call site had mis-bound five of seven
arguments. The generator also proves symbolically that the assembly
recipe equals the unfactorised Hessian, and generates the confocal
coordinate mu_DE with its derivatives and the Becke/SSF cell functions
with t = s'/s, u = s''/s from the factored ln s (stable as mu -> 1).
Validation, benzene/cc-pVDZ, LDA, PBE, TPSS and LAK, against central
differences (Richardson) of eval_exc_grad with weight derivatives,
displacing atom + basis and rebuilding the grid: diagonal and
off-diagonal blocks agree to ~1e-12 (Becke) and ~1e-9 (SSF) on the PySCF0
grid; on UltraFine Becke agrees to 8e-12 and SSF to 2e-7, where the
finite-difference reference is itself asymmetric by the same amount.
H is symmetric to 3e-16 and obeys the translational sum rule to 3e-15.
The basis class alone agrees with finite differences over the basis
function origins at the truncation level of the reference.
Not included: UKS; Laplacian-dependent meta-GGAs (they need fourth
collocation derivatives). The Becke weight term costs O(N^3) per grid
point; SSF skips inactive atom pairs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0135evJ9zgNL1y8U6T9bQ3UT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GauXC has nuclear gradients of the XC energy but no Hessian. This adds
eval_exc_hess(P, settings): the full 3N x 3N second derivative ofE_xc at fixed density matrix, RKS, for LDA, GGA and (tau-dependent)
meta-GGA functionals, on the host replicated integrator.
What is included
IntegratorSettingsEXC_HESSmirrorsIntegratorSettingsEXC_GRAD:include_weight_derivatives = true(default): all three ways E_xcdepends on the nuclei -- the basis functions ride their atoms, the grid
points ride their parent atoms, and the partition weights change.
Each task is accumulated in coordinates excluding its parent atom C
(the task energy depends on R_A - R_C only), and C's rows and columns
are restored by translational invariance. The weight class adds
w'' e + w' e'^T + e' w'^T per point, with Becke or SSF weight
derivatives in log form, which stay finite as the parent partition
function goes to zero.
include_weight_derivatives = false: the basis class alone (fixedgrid, fixed weights), the analogue of the gradient's Hellmann-Feynman
option.
The Pulay term is contracted with GEMMs (it is exactly bilinear in the
displaced basis rows), so its cost is BLAS-3 rather than
O(9 nbe^2 npts) scalar kernel calls.
Generated code
The per-point kernels (
host/gauxc_hess_kernel.hpp) and their callsites (
host/gauxc_hess_call_*.inc) are generated by xckernel from thesymbolic nuclear Hessian, and should be regenerated rather than edited:
Call-site arguments are bound by name from each kernel's own signature,
because GauXC's names (
vgamma, ...) sort differently from Libxc's(
vsigma, ...), and a hand-written meta-GGA call site had silentlymis-bound five of seven arguments. The generator also proves, symbolically,
that the assembly recipe used here (per-atom rows contracted as an outer
product, plus the Pulay and same-atom terms) equals the unfactorised
Hessian.
Validation
Benzene / cc-pVDZ; LDA (SVWN), PBE, TPSS, LAK.
eval_exc_gradwith weight derivatives, displacing atom + basis andrebuilding the grid: diagonal and off-diagonal blocks agree to ~1e-12
with Becke weights and ~1e-9 with SSF (PySCF0 grid). On UltraFine,
Becke agrees to 8e-12. SSF agrees to 2e-7 there, which is the noise
floor of the reference itself: its finite-difference Hessian is
asymmetric by the same amount.
sum_B H[(A,x),(B,y)] = 0 to 3e-15.
function origins: agreement at the FD truncation level for all four
functionals.
Limitations
so no device stubs are needed).
collocation derivatives.
atom pair contributes); SSF skips inactive pairs and is much cheaper.
🤖 Generated with Claude Code
https://claude.ai/code/session_0135evJ9zgNL1y8U6T9bQ3UT