Honour the range-separation omega in GPU libxc functionals (#815) - #923
Merged
Merged
Conversation
The omega declared in xc_code, or set as mf.omega, reached the exact exchange but never the semilocal functional, which stayed at libxc's default. Set it as pyscf's LIBXC_xc_func_set_params does, key the functional cache on omega, forward omega through eval_xc_eff and the CPU fallback, and keep it in to_cpu.
sunqm
approved these changes
Sep 25, 2026
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.
Problem
The omega of a range-separated functional reaches the exact exchange but never the semilocal part, which stays at libxc's built-in default. Both ways of setting omega are affected:
xc_code, e.g.LR_HF(0.3)+ITYH,LYP. The string is parsed correctly, but omega is never given to libxc, so ITYH runs at its default of 0.2. No override is needed to hit this.mf.omega. The override is applied to the exact exchange only.In both cases the two halves of the exchange are range-separated at different omegas, and nothing warns. Only omegas that differ from libxc's default are affected.
Measured on an A100 with gpu4pyscf 1.8.1, against pyscf on the CPU:
LR_HF(0.3)+ITYH,LYP, omega declared in the string: max pointwise exc / vxc error (test_libxcdensity)ni.omega = 0.1: max pointwise exc / vxc error (same density)mf.omega = 0.175: RKS SCF energy (water/def2-TZVPP)Fix
The same semantics as
pyscf.dft.libxc.XCFunctionalCacheandLIBXC_xc_func_set_params: an override takes precedence over the omega declared inxc_code, and zero leaves libxc's default in place.libxc.XCfun(xc, spin, omega=0): when omega is nonzero, set_omegaon the functional and on eachfunc_auxthat exposes it. The name is looked up withxc_func_info_get_ext_params_name, because the bundled libxc does not exportxc_func_find_ext_params_name.numint._init_xcfuns(xc_code, spin, omega=None): resolves omega as above. Omega is part of the cache key, so functionals with different omegas are separate cached objects.NumInt._init_xcfunsandNumInt2C._init_xcfunspassself.omega. The PBC and multigrid classes reuseNumInt._init_xcfuns.eval_xc_effpasses omega to_init_xcfunsand to the CPU fallback.NumInt.eval_xc_effnow forwards itsomega=argument, which it previously dropped.to_cpu()onNumInt,NumInt2Cand the PBCKNumInt/NumIntkeepsomega.Tests
test_libxc.py, GPU vs CPU exc/vxc at the existing 1e-10 bound:xc_codewith no override (RKS and UKS);to_cpu()keeping omega.test_rks.py: an LC_WPBE SCF withmf.omega = 0.175againstmf.to_cpu(), to 1e-6 Ha.On an A100, with the patch applied to v1.8.1:
test_libxc,test_rks,test_numintandtest_numint2cshow no regressions;test_numint::test_sparse_indexfails with and without the patch: its exact-float fingerprint differs in the 14th digit.NumInt2Cand the PBC paths get the same code change but are not exercised by these tests.Note: LC_WPBE vxc at its default omega
The libxc override test uses LRC_WPBEH rather than LC_WPBE because, independently of this change, LC_WPBE's GPU vxc differs from pyscf by about 2e-9 at its default omega of 0.4. That is above
test_libxc's 1e-10 bound. LRC_WPBEH, CAM_B3LYP and ITYH agree to about 1e-15. This may be worth a separate look.Fixes #815