Repository navigation
feat(xc): add libvdwxc-backed rVV10 nonlocal XC - #8140
CleverPhysician wants to merge 32 commits into
Conversation
|
Update after the hosted checks completed:
The PR remains Draft while the maintainer confirms the staged CPU/serial/nspin=1 scope and while the QE same-density reference comparison (including gradient/divergence sign and normalization) is completed. libvdwxc MR !32 is still a Draft dependency, so I am not presenting it as a stable release. |
Could you provide the detailed information? Another side note: libvdwxc currently requires FFTW-MPI wrapper when MPI is enabled, so be careful with MKL; for now you can consider adding a |
ABACUS-PR-BOT
left a comment
There was a problem hiding this comment.
Static review of 32e12de74c07d2307a90c695dac6f8e452f592e5, independently cross-checked against the pinned libvdwxc implementation. Two geometry issues and one nonblocking timer-label cleanup are noted inline. No builds or runtime tests were run.
|
Follow-up on head
The PR remains Draft while the new head's hosted checks are queued and the QE same-density reference is discussed. |
|
Addressed the ABACUS-PR-BOT static review on head
The intern004 adapter CTest is 1/1 after these changes, and the Si CPU/PW/nspin=1 SCF remains numerically unchanged. The PR stays Draft pending the hosted checks for the new head and maintainer review. |
| if(NOT TARGET libvdwxc::vdwxc) | ||
| message(FATAL_ERROR | ||
| "ENABLE_LIBVDWXC requires the libvdwxc::vdwxc CMake target. " | ||
| "Use the libvdwxc development build that includes the rVV10 API.") | ||
| endif() |
There was a problem hiding this comment.
That shouldn't be needed as libvdwxc's CMake config will definitely have libvdwxc::vdwxc target. Previously I did this in abacus for RapidJSON due to its embarrassing release status, but with it replaced by nlohmann-json there's no longer the case. If abacus can deal with items like dftd4 and pexsi well then the same for libvdwxc (its cmake is cleaner). If you really encountered issues please report them.
There was a problem hiding this comment.
Agreed. c23f000 removes the if(NOT TARGET libvdwxc::vdwxc) check; ABACUS now relies on find_package(libvdwxc CONFIG REQUIRED) and links the exported libvdwxc::vdwxc target through _abacus_feature_libs, alongside Libxc::xc.
| get_target_property(LIBVDWXC_INCLUDE_DIRS libvdwxc::vdwxc INTERFACE_INCLUDE_DIRECTORIES) | ||
| if(NOT LIBVDWXC_INCLUDE_DIRS) | ||
| message(FATAL_ERROR "libvdwxc::vdwxc does not expose its include directory") | ||
| endif() | ||
| # Installed packages expose a concrete include path, while build-tree | ||
| # targets may expose generator expressions. Strip those expressions before | ||
| # probing so configuration gives a useful error instead of a later include | ||
| # failure. | ||
| set(_libvdwxc_include_hints) | ||
| foreach(_include_dir IN LISTS LIBVDWXC_INCLUDE_DIRS) | ||
| string(GENEX_STRIP "${_include_dir}" _include_dir_stripped) | ||
| if(IS_DIRECTORY "${_include_dir_stripped}") | ||
| list(APPEND _libvdwxc_include_hints "${_include_dir_stripped}") | ||
| endif() | ||
| endforeach() | ||
| unset(LIBVDWXC_HEADER_DIR CACHE) | ||
| find_path(LIBVDWXC_HEADER_DIR NAMES vdwxc.h HINTS ${_libvdwxc_include_hints} | ||
| NO_DEFAULT_PATH) | ||
| if(NOT LIBVDWXC_HEADER_DIR) | ||
| message(FATAL_ERROR "libvdwxc::vdwxc does not provide vdwxc.h") | ||
| endif() | ||
| file(READ "${LIBVDWXC_HEADER_DIR}/vdwxc.h" LIBVDWXC_HEADER_TEXT) | ||
| if(NOT LIBVDWXC_HEADER_TEXT MATCHES "VDWXC_RVV10" | ||
| OR NOT LIBVDWXC_HEADER_TEXT MATCHES "vdwxc_new" | ||
| OR NOT LIBVDWXC_HEADER_TEXT MATCHES "vdwxc_set_rvv10_parameters" | ||
| OR NOT LIBVDWXC_HEADER_TEXT MATCHES "vdwxc_set_unit_cell" | ||
| OR NOT LIBVDWXC_HEADER_TEXT MATCHES "vdwxc_init_serial" | ||
| OR NOT LIBVDWXC_HEADER_TEXT MATCHES "vdwxc_calculate" | ||
| OR NOT LIBVDWXC_HEADER_TEXT MATCHES "vdwxc_finalize") | ||
| message(FATAL_ERROR | ||
| "The selected libvdwxc headers do not provide the complete serial rVV10 API; " | ||
| "use the pinned development build containing MR !32.") | ||
| endif() |
There was a problem hiding this comment.
Looks like you add a lot of lines simply for detecting rVV10 API? For the time it might be okay, but we should drop it at some time in the future.
There was a problem hiding this comment.
Dropped in c23f000: CMake no longer probes include directories, calls find_path(vdwxc.h), reads the header or matches rVV10 symbols with regexes. docs/advanced/install.md points to the libvdwxc MR !32 rVV10 branch instead.
|
|
||
| ## Follow-up work | ||
|
|
||
| The next PRs can add a libvdwxc MPI/PFFT adapter, ordinary spin, GPU/LCAO |
There was a problem hiding this comment.
Just a side note: PFFT dependency might be dropped in the future. Actually I'm proposing a minimal dependency policy upstream, but anyways PFFT will be the first lucky one.
There was a problem hiding this comment.
Noted, thanks. This page was removed in c23f000; the adapter calls vdwxc_init_serial, and ABACUS does not directly discover or link PFFT.
|
Thanks for asking. I reran the unchanged libvdwxc revision Both builds used GCC 11.2.1, Release ( With
The original MKL executable reproduces exactly the same values under a clean environment with no env -i PATH=/usr/bin:/bin LANG=C LC_ALL=C OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 \
/tmp/libvdwxc-mr32-audit/build-audit/libvdwxc_rvv10_testSelecting Both configurations pass the separate CP2K-table reference comparisons in that test: energy, density/sigma derivatives, and explicit stress on a The current evidence therefore isolates the discrepancy to this MKL backend configuration. The underlying cause has not been established. Updated head This update also removes the manual CMake target/header/API checks and uses |
|
Ah OK, I can now reproduce the failure with oneMKL 2026.1.0. I will have a look into it. |
@CleverPhysician This should be fixed on libvdwxc side, please check |
|
Follow-up on
The earlier 18 successful hosted checks apply to |
|
Thanks, checked the fix at The new adapter has now also been compared against the immutable original-QE |
Replace the single combined scope check with per-setting diagnostics that name the parameter to change, drop the rvv10_b/rvv10_c checks already covered by the xc_nonlocal check, give the gamma_only reset its own message, and note the nscf restriction in the parameter description. The reader tests now create mkstemp scratch files under testing::TempDir() so concurrent runs do not share INPUT/KPT names. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Forward-declare the opaque vdwxc_data_obj handle so only the implementation and the API-parity test include <vdwxc.h>. Register the module_vdw tests from their own CMakeLists again and the serial libvdwxc host test from source_estate, remove the redundant dftd4 link of the pairwise vdW test, read the single nspin=1 density channel in PotNonlocalXC, and stop duplicating the rVV10 defaults in Potential. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The build-report contract test already runs in the "Other Unittests" step, so the workflow is now unchanged from develop. The test README keeps only how to run the tests, install.md documents the nscf restriction, and CITATIONS.md fixes the Sabatini initial. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Please answer directly to each comment. |
Resolves the CMake list re-indentation from the Prettify series, the SCCS component next to the nonlocal XC branch in potential_types.cpp and HamiltPW, and the renamed relax_method reader test.
…x the rVV10 parameters Read xc_nonlocal in Potential::get_pot_type from the Input_para it now receives, the same way the pcc, efield and sccs components do, and drop the second Potential constructor, the three stored members and the has_nonlocal_xc() query that HamiltPW no longer needs since the merge of develop switched it to input.xc_nonlocal. The current interface pairs GGA_X_RPW86+GGA_C_PBE with the published rVV10 parameters b=6.3 and C=0.0093, so they become named constants in nonlocal_xc.h instead of two INPUT parameters that accepted only one value. The reader keeps the functional and scope checks in a small helper that names the first unsupported setting; braces on every if, no auto, a named spin channel, and a unit-cell guard in the factory. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…test from module_vdw The tests/rvv10 CTest only asserted a hard-coded constant in generate_build_info.sh through a Python interpreter found at configure time; backend coverage stays with the two GoogleTest targets. The serial adapter test is now registered from module_vdw/CMakeLists.txt, leaving the MPI-only test directory as in develop, and nonlocal_xc joins the coverage targets. install.md keeps the build recipe, the libvdwxc merge request and the INPUT lines and points to `abacus -h xc_nonlocal` for the supported scope; CITATIONS.md cites libvdwxc itself. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ModuleBase::e2 for the Hartree-to-Rydberg conversion and ModuleBase::TWO_PI in the tests, named cell and finite-difference tolerances with their origin, braces on nested loops, explicit types instead of auto, one allocation for the returned potential, 2-space CMake blocks matching the Prettify series, a configure-time warning when ENABLE_LIBVDWXC meets the MKL FFTW interface, and clang-format on the new files and touched hunks. The unrelated Makefile newline and the hamilt_pw.h comment are gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
nonlocal_xc_libvdwxc.{h,cpp} become nonlocal_vdwxc.{h,cpp} (and the test
test_nonlocal_vdwxc.cpp) to keep file names within the 15-character
preference. LibvdwxcNonlocalXC::evaluate now delegates to small helpers
(serial grid and right-handed cell predicates, finite-value check,
initialized-cell check, host gradient/sigma, Ry assembly of energy,
potential and vtxc) so each unit stays readable; the numerical path is
unchanged.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…cmake-format The pre-commit job formats the whole tree, so its exit code reflects upstream formatting debt (2257 C++ and 67 CMake files at develop 8e20175); this commit only brings the lines this PR adds in line with clang-format 23.1.3 and cmake-format 0.6.13: two wrapped WARNING_QUIT calls, the xc_nonlocal field comment, the std::transform iterator arguments, and the two new test-registration blocks. No functional change; tokens verified equal before and after. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
At libvdwxc
Not in this PR: the documented build uses standalone FFTW with |
Thanks for reproducing it. |
Checked, thanks for the fix. At libvdwxc |
Done. Each inline and conversation comment from ABACUS-PR-BOT and Growl1234 now has a direct reply. Since your comment, I merged develop ( Two points need your decision:
|
|
Please give us a little more time. Discussions on the related series of PRs are already underway and should be wrapped up soon. Once the rVV10 PR is merged, a new release will come. Also, to be honest, I'm not happy with the code itself and restriction here; IMHO it makes many things unnecessarily complicated. Perhaps I could ping @askhl to help take a look at this integration attempt. |
…nctional::v_xc Replace the xc_nonlocal INPUT item and the PotXC hook by the dft_functional short name RVV10 (rPW86 exchange, PBE correlation, rVV10 with b = 6.3 and C = 0.0093), stored next to func_id like the other short names. The nonlocal term is added in the libxc branch of XC_Functional::v_xc, so the SCF potential, the NLCC force and stress terms, out_mat_h_vxc, PotXC_FDM, RDMFT and the DeePKS base functional all use the same XC potential, and no force-specific restriction is needed. The libvdwxc adapter becomes one stateless function: it creates the handle per call, as the libxc wrappers do, and collects the grid on the pool root with the Parallel_Common wrappers. It is compiled into the XC library only when ENABLE_LIBVDWXC is on, following the DFT-D4 build pattern. Stress and DFPT are rejected where those quantities are built. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
In |
|
Well, several questions:
|
|
Problem (AI-generated, correct me if I'm wrong):
|
…tributed interface rVV10 becomes vdw_method rvv10 with the parameters vdw_rvv10_b and vdw_rvv10_c, independent of dft_functional. The parameters reach the XC layer through XCFunctionalParameters, and the nonlocal term is added in all three return paths of XC_Functional::v_xc and in XC_Functional_Libxc::v_xc_meta, so it can be combined with native, libxc and meta-GGA functionals. The libvdwxc object, its FFT plans and buffers are kept between calls and rebuilt only when the grid or the pool changes. With several processes per pool, vdwxc_init_mpi is used and the fields are redistributed between the ABACUS z-plane layout and libvdwxc's FFTW-MPI slabs instead of collecting the grid on one process. Stress is computed with vdwxc_stress plus the gradient term on the ABACUS grid. DFPT and LR-TDDFT forces are rejected when INPUT is read and at run time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The DFPT runtime guard and LR_Util::check_force_vdw repeated the INPUT requirement on vdw_method, which is checked on the effective values before any calculation; both are removed, so no esolver or LR file changes. ESolver_FP copies the rVV10 settings like the other XC runtime parameters, with an explicit rvv10 switch instead of rvv10_b > 0, and the XC hooks pass these parameters to vdw::add_rvv10 instead of the adapter reading global state. The libxc hook moves to the single exit of v_xc_libxc, next to the one in v_xc_meta, so the existing return of v_xc is unchanged. The adapter test drops cases that other cases already cover and merges the distributed stress check into the distributed grid test; the new Parallel_Common::alltoallv_data gets a case in the existing 4-rank parallel_device test, which runs without libvdwxc. CMake enables C in the shared language block and warns, instead of stopping, when MKL meets an MPI libvdwxc. INPUT and docs keep the parameter values in one place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With an MPI build, vdwxc_init_mpi creates FFTW-MPI plans and libvdwxc runs them through the public fftw_execute_* symbols. When ABACUS links the FFTW interface of MKL or KML, these symbols resolve to that interface, which cannot execute FFTW-MPI plans, so CMake now stops instead of warning. The install guide builds libvdwxc as a shared library, the form that was validated, and the rebuild hint names both required options. The workspace comment is reworded, and the vdw_method comment in Input_para keeps its develop text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Updated in
For the input-validation comment, With MPI-enabled libvdwxc One correction to my earlier target reply: since |
What's changed?
This adds rVV10 nonlocal correlation through libvdwxc MR !32, selected with
vdw_method rvv10. The semilocal functional remains set bydft_functional.vdw_rvv10_bdefaults to 6.3 and must be positive;vdw_rvv10_cdefaults to 0.0093 and must be nonnegative. Both parameters requirevdw_method rvv10. Set b explicitly to 15.7 for SCAN or 11.95 for r2SCAN; it is not changed automatically when selecting a functional.v_xc_libxc,v_xc_meta, and the native and NCGGA paths ofv_xc. It uses the existing charge, gradient, potential and XC-energy bookkeeping.evdwremains zero because this is a density-functional contribution, not a pairwise dispersion term.vdwxc_init_mpi.Parallel_Common::alltoallv_dataredistributes density, sigma and derivatives between ABACUS planes and libvdwxc slabs without gathering the full grid on one process. The libvdwxc object, FFT plans and buffers are reused; a grid or pool change rebuilds the workspace. Cell and b/C values are updated on each call. Left-handed cells are inverted for libvdwxc's signed-volume convention.add_rvv10_stresscombinesvdwxc_stresswith the ABACUS gradient contribution instress_gga. Density-dependent terms use the existing XC and NLCC paths. Stress and cell relaxation are enabled; DFPT, LR-TDDFT forces and LR relaxations are rejected during INPUT validation.ENABLE_LIBVDWXCdefaults to OFF and requiresENABLE_LIBXC. CMake uses the exportedlibvdwxc::vdwxctarget. MPI builds require an MPI-enabled libvdwxc and standalone FFTW; CMake rejects the MKL/KML FFTW interfaces. Build information follows DFT-D4. The legacy Makefile does not build this feature.Installation, SCF usage and citations are updated in
docs/advanced/install.md,docs/advanced/scf/advanced.mdanddocs/CITATIONS.md. INPUT metadata includes the new parameters and help text; generated INPUT documentation is not committed. Like the othervdw_methodvalues,rvv10must be lowercase. A build without the backend gives a rebuild hint.Linked Issue
This continues the rVV10 work discussed in #8031; no separate issue was opened.
Unit Tests and/or Case Tests for my changes
The cluster runs cover the runtime changes through
7e9425c86, including an incremental rebuild and focused tests after that commit.b378fb261changes CMake checks, documentation, a hint and comments. It passed local syntax, formatting and governance checks but has not been rebuilt on the cluster.Builds used GCC 11.5, OpenMPI 4.1, Libxc 6.2.2, FFTW 3.3.10 with MPI and libvdwxc
da2d55fwith MPI enabled. Runtime tests used one OpenMP thread.Commands run:
The CLI checks passed for valid inputs and rejected the unsupported settings. CTest passed 18/18 with libvdwxc and 13/13 without it. This includes the adapter tests at 1, 2 and 4 ranks and the communication tests at 1 and 4 ranks. The LCAO selection passed 8/9:
MODULE_LR_pot_hxc_lrtdfailed because the loaded Libxc does not provide KXC for Slater exchange.Case runs used
abacus_pw_paraandabacus_basic_paraon two-atom Si, plus H2Oks-lrfromtests/08_RI/lr_tddft_pbe_gammawithcal_force 0,tests/06_SDFT/03_PW_SDFT_5D10Sand the WT-OFDFT casetests/07_OFDFT/22_OF_LibxcPBE.2e-11 eVacross 1–4 ranks, including different ABACUS/libvdwxc plane distributions. A separate nonmagnetic Si comparison ofnspin=1,2,4at two ranks agrees within5e-11 eV. The toy-cell energy agrees with earlier versions within1e-12 eV.2.6e-4 eV/angstromwithout NLCC and1.2e-4 eV/angstromwith NLCC in PW; the semilocal NLCC control gives1.4e-4 eV/angstrom. In LCAO the corresponding errors are5e-5,1.1e-3and1.4e-3 eV/angstrom.0.02 kbarin PW and0.05 kbarin LCAO. PW checks include rPW86+PBE and SCAN with b = 15.7, with and without a smooth NLCC core. Hard-NLCC residuals remain:Si.pz-n-nc.UPFgives up to1.1 kbaratecutrho120 Ry and0.4 kbarat 480 Ry. Its semilocal off-diagonal control differs by up to0.35 kbar. Absolute PW NLCC diagonal stresses also have large residuals in the semilocal controls; total-stress accuracy and the cause of those discrepancies remain unresolved.ks-lrspectrum runs. These are smoke tests, not independent force/stress checks for those solvers.Earlier fixed-density QE comparisons found energy differences up to
3.5e-13 Ryon seven synthetic densities and6e-15 Ryon graphene, with an own-energy directional residual up to1.3e-10 Ry. Pointwise potentials differed in low-q and small-gradient cases. Those results belong to the earlier implementation; this revision has not had a new independent QE comparison.OpenMP, GPU, ELPA-based LCAO solvers, USPP, rt-TDDFT and DeePKS have not been tested with rVV10. Hosted CI leaves libvdwxc disabled, so it does not test the backend-enabled path.
Core-module impact
ESolver_FP::before_all_runnerscopies three values intoXCFunctionalParameters; it adds no solver step. The XC evaluators andstress_ggacall the new functions only with__LIBVDWXC. Existing evaluator callers receive the correction, including NLCC,PotXC_FDM, RDMFT and matrix writers; the tests above do not cover every caller.ScopedTyperestores the added XC parameters.The workspace is kept for the process lifetime to avoid destruction after
MPI_Finalizeorfftw_cleanup_threads; its buffers remain allocated after SCF.source_basegains thealltoallv_datawrapper and tests. Local governance checks found no issues; quality scores fornonlocal_xc.cpp,nonlocal_xc.handtest_nonlocal_xc.cppwere 89, 98 and 86.Governance Exception
#define(AGENTS rule 20).__LIBVDWXCandABACUS_LIBVDWXC_VERSION, following DFT-D4 (CMake: Move __DFTD4 to global feature definitions #7793).build_info.h.in.ENABLE_LIBVDWXC=OFF, the default.Open points
da2d55f; the PR remains Draft pending the library release.da2d55f(ceil(nz/P)z planes). A backend/layout change would require updating this mapping.nonlocal_xc.cppis inmodule_vdwand compiled intoxc_;libvdwxc::vdwxcis linked toxc_. I can move the source tomodule_xcif that placement is preferred.