Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ jobs:
cmake --build build -j8
cmake --install build

- name: rVV10 host contract
run: |
source toolchain/install/setup
ctest --test-dir build --output-on-failure --no-tests=error -R RVV10_LIBVDWXC_CONTRACT

- name: Report compiler cache
if: always()
run: |
Expand Down
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ option(USE_SW "Enable SW Architecture" OFF)

option(ENABLE_ABACUS_LIBM "Build libmath from source to speed up" OFF)
option(ENABLE_LIBXC "Enable using the LibXC package" OFF)
option(ENABLE_LIBVDWXC "Enable libvdwxc-backed nonlocal XC" OFF)
option(ENABLE_FLOAT_FFTW "Enable using single-precision FFTW library." OFF)

option(ENABLE_LCAO "Enable LCAO algorithm" ON)
Expand Down Expand Up @@ -618,6 +619,17 @@ if(ENABLE_LIBXC)
endif()
endif()

if(ENABLE_LIBVDWXC)
if(NOT ENABLE_LIBXC)
message(FATAL_ERROR
"ENABLE_LIBVDWXC currently requires ENABLE_LIBXC=ON because the first "
"rVV10 interface uses Libxc for the semilocal RPW86+PBE part.")
endif()
# The config target supplies headers and transitive FFT dependencies.
# rVV10 currently requires the development revision documented in install.md.
find_package(libvdwxc CONFIG REQUIRED)
endif()

if(DEFINED DeePMD_DIR)
find_package(DeePMD REQUIRED)
endif()
Expand Down
11 changes: 11 additions & 0 deletions cmake/CollectBuildInfoVars.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ else()
set(ABACUS_DFTD4_VERSION "no")
endif()

if(ENABLE_LIBVDWXC AND libvdwxc_VERSION)
set(ABACUS_LIBVDWXC_VERSION "yes (v${libvdwxc_VERSION})")
elseif(ENABLE_LIBVDWXC)
set(ABACUS_LIBVDWXC_VERSION "yes (version unknown)")
else()
set(ABACUS_LIBVDWXC_VERSION "no")
endif()

# Accelerators
if(USE_CUDA AND CUDAToolkit_VERSION)
set(ABACUS_CUDA_VERSION "yes (v${CUDAToolkit_VERSION})")
Expand Down Expand Up @@ -382,6 +390,7 @@ list(APPEND CMAKE_OPTIONS_LIST " USE_ROCM=${USE_ROCM}")
list(APPEND CMAKE_OPTIONS_LIST " ENABLE_LCAO=${ENABLE_LCAO}")
list(APPEND CMAKE_OPTIONS_LIST " ENABLE_ELPA=${ENABLE_ELPA}")
list(APPEND CMAKE_OPTIONS_LIST " ENABLE_LIBXC=${ENABLE_LIBXC}")
list(APPEND CMAKE_OPTIONS_LIST " ENABLE_LIBVDWXC=${ENABLE_LIBVDWXC}")
list(APPEND CMAKE_OPTIONS_LIST " ENABLE_MLALGO=${ENABLE_MLALGO}")
list(APPEND CMAKE_OPTIONS_LIST " ENABLE_ASAN=${ENABLE_ASAN}")
list(APPEND CMAKE_OPTIONS_LIST " BUILD_TESTING=${BUILD_TESTING}")
Expand All @@ -396,6 +405,7 @@ list(APPEND CMAKE_FIND_PACKAGES_LIST " CUDA Found=${CUDA_FOUND}")
list(APPEND CMAKE_FIND_PACKAGES_LIST " ROCm Found=${ROCM_FOUND}")
list(APPEND CMAKE_FIND_PACKAGES_LIST " ELPA Found=${ELPA_FOUND}")
list(APPEND CMAKE_FIND_PACKAGES_LIST " Libxc Found=${Libxc_FOUND}")
list(APPEND CMAKE_FIND_PACKAGES_LIST " libvdwxc Found=${libvdwxc_FOUND}")
list(APPEND CMAKE_FIND_PACKAGES_LIST " PEXSI Found=${PEXSI_FOUND}")
list(APPEND CMAKE_FIND_PACKAGES_LIST " LibRI Found=${LIBRI_FOUND}")
foreach(package_line ${CMAKE_FIND_PACKAGES_LIST})
Expand Down Expand Up @@ -439,6 +449,7 @@ message(" Torch = ${ABACUS_LIBTORCH_VERSION}")
message(" DeePMD = ${ABACUS_DEEPMD_VERSION}")
message(" NEP = ${ABACUS_NEP_VERSION}")
message(" Features : Libxc = ${ABACUS_LIBXC_VERSION}")
message(" libvdwxc = ${ABACUS_LIBVDWXC_VERSION}")
message(" LibRI = ${ABACUS_LIBRI_VERSION}")
message(" DFT-D4 = ${ABACUS_DFTD4_VERSION}")
message(" JSON = ${ABACUS_JSON_VERSION}")
Expand Down
8 changes: 8 additions & 0 deletions docs/CITATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,11 @@ The following references are required to be cited when using ABACUS. Specificall
Eike Caldeweyher, Jan-Michael Mewes, Sebastian Ehlert, and Stefan Grimme. "Extension and evaluation of the D4 London-dispersion model for periodic systems." Physical Chemistry Chemical Physics 22, 8499-8512 (2020). DOI: 10.1039/D0CP00502A.

Nikolay V. Tkachenko, Linus B. Dittmer, Rebecca Tomann, and Martin Head-Gordon. "Smooth D4S model." The Journal of Physical Chemistry Letters 15, 10629-10637 (2024). DOI: 10.1021/acs.jpclett.4c02653.

- **If the libvdwxc-backed rVV10 nonlocal correction is used:**

O. A. Vydrov and T. Van Voorhis. "Nonlocal van der Waals density functional: The simpler the better." The Journal of Chemical Physics 133, 244103 (2010). DOI: 10.1063/1.3521275.

P. Sabatini, T. Gorni, and S. de Gironcoli. "Nonlocal van der Waals density functional made simple and efficient." Physical Review B 87, 041108(R) (2013). DOI: 10.1103/PhysRevB.87.041108.

Cite the exact [libvdwxc](https://gitlab.com/libvdwxc/libvdwxc) revision used for the calculation, because the rVV10 CMake interface is version-dependent during development.
38 changes: 38 additions & 0 deletions docs/advanced/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,44 @@ vdw_d4_model d4 # or d4s for the smooth D4S model

If `vdw_d4_xc` is set to `default`, ABACUS will infer the functional name from `dft_functional` or pseudopotential metadata and pass it to the DFT-D4 library. The `vdw_d4_model` keyword selects the dispersion model inside the DFT-D4 library; the default is `d4`, while `d4s` enables the smooth D4S model.

## Build with libvdwxc-backed rVV10 support

The first rVV10 integration uses the external [libvdwxc](https://gitlab.com/libvdwxc/libvdwxc) library for the nonlocal kernel. The current rVV10 API is under review in Draft MR !32, so this option is intended for development and reproducible integration testing rather than a stable release build.

Build and install the pinned libvdwxc development branch first (MR !32,
`rvv10-cmake`, commit
`94410ebdf3dc9615a40f40c3a5b59dbe20a433d2`), then pass its CMake prefix to
ABACUS together with Libxc. This revision fixes Hermitian symmetry on stored
FFT boundary planes in oblique cells. With GCC 11.2.1, its eight library tests
pass using either FFTW 3.3.11 or the MKL 2022.2.1 compatibility backend.
The ABACUS adapter is tested with standalone FFTW for both programs; the
library's MKL tests alone do not validate an MKL-based ABACUS build. Do not
mix the two FFT providers in one process. To use the validated serial
configuration, leave `MKLROOT`/`MKL_ROOT` unset and select OpenBLAS/LAPACK plus
FFTW through ABACUS's existing dependency options:

```bash
cmake -B build-libvdwxc -DBUILD_TESTING=ON \
-DENABLE_MPI=OFF -DENABLE_LCAO=OFF \
-DENABLE_LIBXC=ON -DENABLE_LIBVDWXC=ON \
-DCMAKE_PREFIX_PATH="/path/to/libvdwxc-prefix;/path/to/libxc-prefix" \
-DFFTW3_DIR=/path/to/fftw-prefix \
-DBLA_VENDOR=OpenBLAS \
-DBLAS_DIR=/path/to/openblas-prefix \
-DLAPACK_DIR=/path/to/openblas-prefix
```

Enable the correction with `xc_nonlocal rvv10` and explicitly select
`dft_functional GGA_X_RPW86+GGA_C_PBE`; this first parameterization uses
`rvv10_b 6.3` and `rvv10_c 0.0093`.

The first adapter supports CPU double-precision, full-complex PW, one process,
`nspin=1`, a single density grid, a right-handed cell and norm-conserving
pseudopotentials for SCF energy/potential evaluation. Other spin/layout modes,
forces, stress, relaxation and pairwise D2/D3/D4 combinations are rejected.
The legacy Makefile does not build this backend. See `tests/rvv10/README.md`
for the numerical tests and host/backend accounting.

## Build with JSON support

ABACUS uses [nlohmann-json](https://github.com/nlohmann/json) for optional JSON output. To build ABACUS with JSON support, pass `-DENABLE_JSON=ON` to CMake.
Expand Down
7 changes: 7 additions & 0 deletions generate_build_info.sh
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ if [ "${USE_CUDA}" == "ON" ]; then
fi
fi

# 6b. libvdwxc
#
# The legacy Makefile does not compile the adapter, even if an environment
# variable requests it. Report the compiled feature, not a discovered library.
LIBVDWXC_VERSION="no"

# 7. ROCm/HIP
ROCM_VERSION="no"
if [ "${USE_ROCM}" == "ON" ]; then
Expand Down Expand Up @@ -279,6 +285,7 @@ sed \
-e "s#@ABACUS_OPENMP_VERSION@#$OPENMP_VERSION#g" \
-e "s#@ABACUS_MKL_SUPPORT@#$MKL_SUPPORT#g" \
-e "s#@ABACUS_LIBXC_VERSION@#$LIBXC_VERSION#g" \
-e "s#@ABACUS_LIBVDWXC_VERSION@#$LIBVDWXC_VERSION#g" \
-e "s#@ABACUS_FFTW_VERSION@#$FFTW3_VERSION#g" \
-e "s#@ABACUS_CUDA_VERSION@#$CUDA_VERSION#g" \
-e "s#@ABACUS_ROCM_VERSION@#$ROCM_VERSION#g" \
Expand Down
34 changes: 33 additions & 1 deletion source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ set(_abacus_feature_definitions
$<$<BOOL:${ENABLE_LIBRI}>:TEST_EXX_LCAO=0>
$<$<BOOL:${ENABLE_LIBRI}>:TEST_EXX_RADIAL=1>
$<$<BOOL:${ENABLE_LIBXC}>:__LIBXC>
$<$<BOOL:${ENABLE_LIBVDWXC}>:__LIBVDWXC>
$<$<BOOL:${ENABLE_DFTD4}>:__DFTD4>
$<$<BOOL:${MATH_INFO}>:GATHER_INFO>)

Expand Down Expand Up @@ -270,7 +271,8 @@ set(_abacus_feature_libs
$<$<BOOL:${ENABLE_CNPY}>:ZLIB::ZLIB>
$<$<BOOL:${ENABLE_LIBRI}>:cereal::cereal>
$<$<BOOL:${ENABLE_LIBXC}>:Libxc::xc>
$<$<BOOL:${ENABLE_PLUMED}>:PLUMED::plumed>)
$<$<BOOL:${ENABLE_PLUMED}>:PLUMED::plumed>
$<$<BOOL:${ENABLE_LIBVDWXC}>:libvdwxc::vdwxc>)
set(_abacus_feature_include_dirs)
set(_abacus_feature_compile_options)

Expand Down Expand Up @@ -392,6 +394,7 @@ foreach(_abacus_feature_target IN ITEMS
cereal::cereal
ELPA::ELPA
Libxc::xc
libvdwxc::vdwxc
dftd4::dftd4
DeePMD::deepmd_c
DeePMD::deepmd_cc
Expand Down Expand Up @@ -714,6 +717,34 @@ endif()
# base uses symbols from device (memory_op and math_ylm_op).
target_link_libraries(base PUBLIC device)

if(BUILD_TESTING)
# Register after all object-library dependencies exist; the optional adapter
# test links the existing PW, INPUT and device targets.
add_subdirectory(source_hamilt/module_vdw/test)
if(ENABLE_LIBVDWXC AND NOT ENABLE_MPI AND NOT USE_CUDA AND NOT USE_ROCM)
# Test the additive host with real Charge and UnitCell lifecycles after
# its dependencies exist, without linking the full estate/cell libraries.
AddTest(
TARGET MODULE_ESTATE_pot_nonlocal_xc_LIBVDWXC
LIBS xc_ planewave base parameter device nonlocal_xc
SOURCES
source_estate/test/test_pot_nonlocal_xc.cpp
source_estate/module_pot/pot_nonlocal_xc.cpp
source_estate/module_charge/charge.cpp
source_estate/module_charge/chg_tools.cpp
source_cell/unitcell.cpp
source_cell/atom_spec.cpp
source_cell/atom_pseudo.cpp
source_cell/pseudo.cpp
source_cell/magnetism.cpp
source_cell/sep.cpp
source_cell/sep_cell.cpp
)
target_link_libraries(MODULE_ESTATE_pot_nonlocal_xc_LIBVDWXC PRIVATE Libxc::xc libvdwxc::vdwxc)
set_tests_properties(MODULE_ESTATE_pot_nonlocal_xc_LIBVDWXC PROPERTIES ENVIRONMENT "OMP_NUM_THREADS=1")
endif()
endif()

if(ENABLE_COVERAGE)
add_coverage(driver)
endif()
Expand All @@ -738,6 +769,7 @@ target_link_libraries(
module_stodft
module_dfpt
xc_
nonlocal_xc
vdw
relax
io_advanced
Expand Down
2 changes: 2 additions & 0 deletions source/Makefile.Objects
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ OBJS_ELECSTAT=elecstate.o\
h_hartree_pw.o\
h_tddft_pw.o\
pot_xc.o\
pot_nonlocal_xc.o\
pot_ml_exx.o\
pot_ml_exx_label.o\
pot_xc_fdm.o\
Expand Down Expand Up @@ -1014,6 +1015,7 @@ OBJS_SRCPW=h_ewald_pw.o\
vsep_pw.o

OBJS_VDW=vdw.o\
nonlocal_xc.o\
vdwd2_parameters.o\
vdwd3_parameters.o\
vdwd2.o\
Expand Down
1 change: 1 addition & 0 deletions source/source_estate/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ list(APPEND objects
module_pot/h_hartree_pw.cpp
module_pot/h_tddft_pw.cpp
module_pot/pot_xc.cpp
module_pot/pot_nonlocal_xc.cpp
module_pot/pot_local.cpp
module_pot/pot_pcc.cpp
module_pot/potential_new.cpp
Expand Down
59 changes: 59 additions & 0 deletions source/source_estate/module_pot/pot_nonlocal_xc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "pot_nonlocal_xc.h"

#include "source_hamilt/module_vdw/nonlocal_xc.h"
#include "source_base/timer.h"
#include "source_base/tool_quit.h"

#include <vector>

namespace elecstate
{
PotNonlocalXC::PotNonlocalXC(const ModulePW::PW_Basis* density_basis,
double* etxc,
double* vtxc,
const std::string& method,
double b,
double c)
: etxc_(etxc), vtxc_(vtxc)
{
backend_ = vdw::make_nonlocal_xc(density_basis, method, b, c);
rho_basis_ = density_basis;
dynamic_mode = true;
fixed_mode = false;
}

PotNonlocalXC::~PotNonlocalXC() = default;

void PotNonlocalXC::cal_v_eff(const Charge* chg, const UnitCell* cell, ModuleBase::matrix& v_eff)
{
ModuleBase::TITLE("PotNonlocalXC", "cal_v_eff");
ModuleBase::timer::start("PotNonlocalXC", "cal_v_eff");
if (!chg || !cell || !rho_basis_ || chg->rhopw != rho_basis_ || chg->nspin != 1
|| chg->nrxx != rho_basis_->nrxx || !chg->rho || !chg->rho_core || v_eff.nr != chg->nspin
|| v_eff.nc != chg->nrxx)
{
ModuleBase::WARNING_QUIT("PotNonlocalXC", "the first rVV10 interface requires a consistent nspin=1 density basis");
}
std::vector<double> valence(chg->nrxx, 0.0);
for (int is = 0; is < chg->nspin; ++is)
for (int r = 0; r < chg->nrxx; ++r)
valence[r] += chg->rho[is][r];
std::vector<double> total = valence;
for (int r = 0; r < chg->nrxx; ++r)
total[r] += chg->rho_core[r];
const vdw::NonlocalXCResult nl = backend_->evaluate(*rho_basis_, total, valence);
if (nl.potential.size() != static_cast<std::size_t>(chg->nrxx))
{
ModuleBase::WARNING_QUIT("PotNonlocalXC", "nonlocal XC backend returned an invalid potential size");
}

// PotXC is registered before this component and owns the semilocal
// contribution. This component only adds the selected nonlocal correction.
*etxc_ += nl.energy;
*vtxc_ += nl.vtxc;
for (int is = 0; is < chg->nspin; ++is)
for (int r = 0; r < chg->nrxx; ++r)
v_eff(is, r) += nl.potential[r];
ModuleBase::timer::end("PotNonlocalXC", "cal_v_eff");
}
} // namespace elecstate
34 changes: 34 additions & 0 deletions source/source_estate/module_pot/pot_nonlocal_xc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef ABACUS_POT_NONLOCAL_XC_H
#define ABACUS_POT_NONLOCAL_XC_H
#include "pot_base.h"

#include <memory>
#include <string>

namespace vdw
{
class NonlocalXC;
}

namespace elecstate
{
// Independent rVV10 nonlocal correction for the CPU/PW SCF path.
class PotNonlocalXC final : public PotBase
{
public:
PotNonlocalXC(const ModulePW::PW_Basis* density_basis,
double* etxc,
double* vtxc,
const std::string& method,
double b,
double c);
~PotNonlocalXC() override;
void cal_v_eff(const Charge* chg, const UnitCell* cell, ModuleBase::matrix& v_eff) override;

private:
double* etxc_;
double* vtxc_;
std::unique_ptr<vdw::NonlocalXC> backend_;
};
} // namespace elecstate
#endif // ABACUS_POT_NONLOCAL_XC_H
30 changes: 29 additions & 1 deletion source/source_estate/module_pot/potential_new.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,36 @@ Potential::Potential(const ModulePW::PW_Basis* rho_basis_in,
double* etxc_in,
double* vtxc_in,
VSep* vsep_cell_in)
: Potential(rho_basis_in,
rho_basis_smooth_in,
ucell_in,
vloc_in,
structure_factors_in,
solvent_in,
etxc_in,
vtxc_in,
vsep_cell_in,
6.3,
0.0093,
"none")
{
}

Potential::Potential(const ModulePW::PW_Basis* rho_basis_in,
const ModulePW::PW_Basis* rho_basis_smooth_in,
const UnitCell* ucell_in,
const ModuleBase::matrix* vloc_in,
Structure_Factor* structure_factors_in,
surchem* solvent_in,
double* etxc_in,
double* vtxc_in,
VSep* vsep_cell_in,
double nonlocal_xc_b_in,
double nonlocal_xc_c_in,
const std::string& nonlocal_xc_in)
: ucell_(ucell_in), vloc_(vloc_in), structure_factors_(structure_factors_in), solvent_(solvent_in), vsep_cell(vsep_cell_in),
etxc_(etxc_in), vtxc_(vtxc_in)
etxc_(etxc_in), vtxc_(vtxc_in), nonlocal_xc_b_(nonlocal_xc_b_in), nonlocal_xc_c_(nonlocal_xc_c_in),
nonlocal_xc_(nonlocal_xc_in)
{
this->rho_basis_ = rho_basis_in;
this->rho_basis_smooth_ = rho_basis_smooth_in;
Expand Down
Loading
Loading