Refactor DFT+U, step 4 - #7861
Open
mohanchen wants to merge 23 commits into
Open
Conversation
added 14 commits
August 26, 2026 16:17
Group the previously interleaved public/protected sections of Plus_U_Base into a single public block followed by a single protected block. No member is moved between access levels and no signature or implementation is changed; this only consolidates the layout so that follow-up changes to access permissions are easier to review.
Move all public data members of Plus_U_Base to protected so that
external code is forced to go through accessors. This tightens
encapsulation of the U values, the DFT+U configuration flags, the
occ_mat state flag, and the occupation matrices themselves.
New public getters added for the existing external read sites:
- get_uramping() replaces dftu.uramping reads in chgmixing.cpp
- get_occ_mat_ctrl() replaces dftu.occ_mat_ctrl reads in
setup_dftu_pw.cpp and setup_dftu_lcao.cpp
- use_yukawa() replaces dftu.use_yukawa reads in dftu_output.cpp
The data member use_yukawa is renamed to use_yukawa_ so the getter
can keep the natural name; the 9 internal bare-name accesses in
dftu_base.cpp / dftu_lcao.cpp / dftu_tools.cpp / dftu_yukawa.cpp
are updated accordingly.
External write access is limited to the unit-test fixture
DFTUTest::SetUp, which writes u_current, orbital_corr and resizes
occ_mat directly. Rather than exposing setters for these one-off
test scenarios, DFTUTest is declared as a friend of Plus_U_Base.
gtest TEST_F derives DFTUTest_xxx_Test whose TestBody does not
inherit the friend declaration, so a small const helper
occ_mat_c(iat, spin, icc) is added to DFTUTest itself; the three
affected EXPECT_NEAR sites in dftu_lcao_test.cpp call it instead
of touching dftu.occ_mat directly.
Two hamilt::DFTU<OperatorLCAO<TK, TR>> methods
(cal_v_of_u in dftu_lcao_op.cpp, cal_force_stress in dftu_fs.cpp)
read this->dftu->u_current[T0]; both are switched to the existing
get_u_current(T0) accessor.
将 fold_dSR_gamma 和 folding_matrix_k 中的重复代码抽取为两个 private 成员函数,消除重复逻辑并统一行为。 新增辅助函数(声明于 dftu_lcao.h,实现于 dftu_folding.cpp): - is_adjacent_pair(): 原子对相邻性判断(直接截断 + 三体重叠桥接) - get_linear_index(): 按 ks_solver 选择行/列主序的本地矩阵索引 主函数精简效果: - fold_dSR_gamma: 113 行 -> 85 行 - folding_matrix_k: 156 行 -> 109 行 - 邻居判断逻辑副本数: 2 -> 1 - 矩阵索引逻辑副本数: 2 -> 1(且修复了 G 版写死列主序的不一致) 顺手清理: - 删除 fold_dSR_gamma 中未使用的 iat0、start0 声明(死代码) - 删除 folding_matrix_k 中冗余的 atom1 重复声明 - 删除两个函数中不再需要的 dtau/dtau1/dtau2/tau0 局部变量 - 统一了 G 版的矩阵索引判断(原本硬编码列主序,现在和 K 版一致) 公共 API 与调用点: - fold_dSR_gamma / folding_matrix_k / folding_matrix_k_new 签名不变 - 调用方 dftu_force.cpp、dftu_occup.cpp 无需修改 验证: - python3 tools/03_code_analysis/agent_governance_check.py --staged 结果: no findings - g++ -std=c++11 -fsyntax-only(针对 dftu_folding.cpp、dftu_lcao.h、 dftu_force.cpp、dftu_occup.cpp)均通过,无错误无警告 - 未做完整 CMake build 与 ctest 运行时测试,因当前环境无 build 目录 (仅有预编译的 abacus_max_para 可执行文件)
…iter param
The CPU and GPU branches of cal_occ_pw (formerly L32-110 and L113-188)
were near-verbatim duplicates, differing only in the device template
parameter of OnsiteProjector and Psi. Merge them into a single template
member function accumulate_occ_one_k<Device>, with explicit
instantiation controlling CPU always compiled and GPU only under
__CUDA/__ROCM.
Also drop the iter parameter from cal_occ_pw signature since it was
never used in the function body; update the call site in
setup_dftu_pw.cpp accordingly.
Files changed:
- source/source_pw/module_pwdft/dftu_base.h
- drop const int iter param from cal_occ_pw declaration
- add template member declaration accumulate_occ_one_k<Device>
- source/source_pw/module_pwdft/dftu_pw.cpp
- drop iter param from cal_occ_pw implementation
- replace ~80 lines of CPU/GPU duplicate code with two template calls
- add accumulate_occ_one_k template definition and explicit
instantiations at end of file
- source/source_pw/module_pwdft/setup_dftu_pw.cpp
- drop iter argument at call site
Effects:
- ~80 lines of duplicate code removed from dftu_pw.cpp
- CPU/GPU inner loops (iat/ib/m1/m2 + nspin==4 Pauli block assembly)
now maintained in a single template implementation
- psi::Psi visibility confirmed transitively via onsite_proj.h
Pending verification (build delegated to user):
- make module_pwdft incremental build
- DFT+U ctest (e.g. MODULE_DFTU label)
- GPU build path (__CUDA/__ROCM) explicit instantiation
…tions
The five private member functions of Plus_U defined in dftu_folding.cpp
(is_adjacent_pair, get_linear_index, fold_dSR_gamma, folding_matrix_k,
folding_matrix_k_new) were pure folding helpers that only read data
members without relying on class invariants. Extract them into free
functions declared in the new dftu_folding.h, removing them from the
Plus_U class API in dftu_lcao.h.
The free functions live in namespace dftu_folding and take the data they
need (orb_cutoff, ks_solver, npol, gamma_only_local, nspin) as direct
parameters instead of receiving a Plus_U reference. Since all callers
are Plus_U member functions, they read this->member directly and pass
the values in, so no getters or friendship are required. The function
names drop the dftu_ prefix since the namespace already qualifies them
(call sites read dftu_folding::folding_matrix_k(...)). No Plus_U members
are deleted: three of the five (npol, gamma_only_local, nspin) are still
read by other Plus_U member functions, and the other two (orb_cutoff_,
ks_solver) are kept to avoid PARAM coupling or cascading signature
changes through the public API.
Also rename the include guard of dftu_lcao.h from DFTU_H to DFTU_LCAO_H
to match the filename (consistent with the new dftu_folding.h guard
DFTU_FOLDING_H); confirmed no other translation unit references DFTU_H.
Files changed:
- source/source_lao/module_dftu/dftu_folding.h (NEW)
- declare 5 free function prototypes under __LCAO, wrapped in
namespace dftu_folding
- source/source_lao/module_dftu/dftu_folding.cpp
- rewrite 5 member functions as free functions in namespace
dftu_folding, taking data params
- member access (this->orb_cutoff_ etc.) replaced by parameters
- internal calls use unqualified names within the namespace
- source/source_lao/module_dftu/dftu_lcao.h
- remove the 5 private member function declarations
- rename include guard DFTU_H -> DFTU_LCAO_H
- member variables and public API unchanged
- source/source_lao/module_dftu/dftu_force.cpp
- include dftu_folding.h; update 3 call sites in
cal_force_k / cal_stress_k / cal_stress_gamma to
dftu_folding::folding_matrix_k / dftu_folding::fold_dSR_gamma
- source/source_lao/module_dftu/dftu_occup.cpp
- include dftu_folding.h; update 1 call site in cal_occup_m_k to
dftu_folding::folding_matrix_k_new
Effects:
- Plus_U class fully decoupled from folding details; dftu_lcao.h no
longer mentions any folding function
- No getters, no friend declarations, no member-variable deletion
- TITLE/timer labels ("Plus_U", "fold_dSR_gamma" etc.) intentionally
preserved to keep profiling tooling stable
Verification (partial, full build delegated to user):
- cmake --build build_std_para --target dftu -> [100%] Built target dftu
- full abacus build and DFTU ctest pending
The nspin==4 VU+energy calculation was split into two loops: - block 0 (is=0, charge channel) with diag_coeff on the diagonal - blocks 1-3 (is=1..3, spin channels sigma_x/y/z) with zero diagonal These two loops have identical structure and only differ in the diagonal coefficient. Merge them into a single is=0..3 loop with diag = (is == 0) ? diag_coeff : 0.0 Also add an English comment explaining the Pauli-block layout: VU is stored as 4 contiguous blocks per atom, where is=0 is the charge channel (Hubbard U contributes diag_coeff*delta on the diagonal) and is=1,2,3 are spin channels (sigma_x/y/z, no U diagonal term). The occupation matrix occ_mat[...][0][0].c packs all 4 blocks contiguously. Physics unchanged: - Hubbard U acts only on the charge channel (is=0), so diag_coeff is still applied only there; spin channels remain with zero diagonal. - energy_u accumulation formula is identical for all 4 blocks. Effect: ~25 lines -> ~12 lines (plus comment), removing the artificial block-0 vs block-1-3 symmetry breaking. Verification: - semantic equivalence checked by inspection (start=0 + diag_coeff for is=0 matches the original block-0 loop; start=is*size + 0.0 for is=1..3 matches the original block-1-3 loop) - existing test VUPotNspin4_PauliTransform (dftu_pw_test.cpp) covers the Pauli->spin transform that follows this loop - full build and ctest delegated to user
cal_occ_pw was doing three conceptually distinct jobs: (1) accumulate
occ_mat from psi, (2) reduce occ_mat across k-pools and sync to
uom_array, (3) compute effective potential VU and DFT+U energy. The
function name only reflects job (1), and the mixing step plus VU/energy
computation were tangled together at the end.
Extract job (3) into a protected member function
compute_eff_pot_and_energy(cell). This isolates the VU+energy
calculation (which reads occ_mat and writes eff_pot_pw / energy_u) from
the occupation-matrix accumulation and reduction logic.
The new function assumes occ_mat has already been reduced across
k-pools (documented in its doxygen comment), matching the current
calling order in cal_occ_pw.
Also add a doxygen comment block on the new function documenting:
- preconditions (occ_mat accumulated and reduced)
- outputs (eff_pot_pw layout for nspin=1/2/4, energy_u formula)
Files changed:
- source/source_pw/module_pwdft/dftu_base.h
- add protected member declaration compute_eff_pot_and_energy(cell)
- source/source_pw/module_pwdft/dftu_pw.cpp
- replace ~95 lines of VU+energy code in cal_occ_pw with a single call
- add compute_eff_pot_and_energy definition containing the moved code
- add doxygen comment on the new function
Effects:
- cal_occ_pw body shrinks from ~175 lines to ~80 lines (orchestration)
- VU+energy logic is now a self-contained unit that can be tested and
evolved independently
- no behavior change: same code, same order, just moved
Verification:
- make module_pwdft incremental build passed (verified by user)
- DFT+U ctest not yet run (delegated to user)
…l_occ_pw
cal_occ_pw's middle section (formerly L42-L91) did two distinct jobs in
a single per-atom loop:
(1) reduce occ_mat across k-pools (MPI AllReduce)
(2) copy occ_mat to uom_array for mixing (plain data shuffle)
These have different natures (parallel communication vs local copy)
and interleaving them in one loop body made both harder to read. Split
them into two protected member functions so each is self-contained.
The new functions:
- reduce_occ_mat(cell): sums per-pool occ_mat contributions across pools.
nspin-aware: nspin=1 reduces one channel, nspin=2 reduces two, nspin=4
reduces all 4 Pauli blocks in one shot.
- sync_occ_to_uom(cell): flattens occ_mat into uom_array for mixing.
nspin=2 uses the split layout [all_up | all_dn]. The uom_array.size()==0
guard is hoisted to an early return at the function entry (equivalent
to the previous in-loop check, but clearer).
Behavior unchanged: same code, same order
(reduce -> sync -> mixing -> compute_eff_pot_and_energy).
Note: GlobalV::NPROC_IN_POOL is still referenced inside reduce_occ_mat.
Isolating it there is a step toward removing the global dependency, but
the actual de-globalization is deferred to a separate governance PR.
Files changed:
- source/source_pw/module_pwdft/dftu_base.h
- add protected declarations for reduce_occ_mat / sync_occ_to_uom
- source/source_pw/module_pwdft/dftu_pw.cpp
- replace ~50 lines in cal_occ_pw with two calls
- add reduce_occ_mat / sync_occ_to_uom definitions (code moved as-is)
- add doxygen comments documenting nspin layout per function
Effects:
- cal_occ_pw body now ~30 lines of pure orchestration
- reduce and copy logic each isolated, nspin-aware layout documented
- existing test MultiAtomSplitLayout_Nspin2 (dftu_pw_test.cpp) covers
the nspin=2 split layout used by sync_occ_to_uom
Verification:
- make module_pwdft incremental build passed (verified by user)
- DFT+U ctest not yet run (delegated to user)
Step 4a of the dftu_pw decoupling plan. Create a new header dftu_pw.h
declaring free functions in namespace dftu_pw, so the DFT+U PW kernels
can be unit-tested directly without going through Plus_U_Base.
First function: pauli_to_spin_basis(vu, m_size). This performs the
Pauli-to-spin-basis transform on VU for nspin==4, previously inlined
in compute_eff_pot_and_energy. The function is pure (no access to
Plus_U_Base members): it takes a raw std::complex<double>* pointer to
the per-atom VU block and m_size.
Files changed:
- source/source_pw/module_pwdft/dftu_pw.h (new)
- declare namespace dftu_pw
- declare pauli_to_spin_basis with doxygen comment documenting the
4 Pauli blocks layout and the transform formula
- source/source_pw/module_pwdft/dftu_pw.cpp
- include dftu_pw.h
- replace ~18 lines of inlined Pauli transform in
compute_eff_pot_and_energy with a single call
dftu_pw::pauli_to_spin_basis(vu_iat, m_size)
- add namespace dftu_pw block at end of file with the function
definition (code moved as-is from the inlined version)
Effects:
- compute_eff_pot_and_energy nspin==4 branch shrinks by ~17 lines
- pauli_to_spin_basis is now independently testable
- no behavior change: same transform, same memory layout
Verification:
- make module_pwdft incremental build passed (verified by user)
- existing test VUPotNspin4_PauliTransform (dftu_pw_test.cpp) covers
the transform; step 4d will rewire it to call the real function
…unctions
Step 4b of the dftu_pw decoupling plan. Extract the VU+energy per-atom
loops from compute_eff_pot_and_energy into two free functions in
namespace dftu_pw:
- compute_vu_spinor: nspin==4 case, writes 4 Pauli blocks of VU and
returns the energy_u increment; internally calls pauli_to_spin_basis
to convert VU to spin basis in-place (same order as before).
- compute_vu_scalar: nspin==1/2 case, writes one spin channel's VU
and returns the energy_u increment.
Both functions are pure: they take raw pointers (vu, occ) and scalars
(u_value, diag_coeff, weight_eu, m_size), no access to Plus_U_Base
members. compute_eff_pot_and_energy now computes per-atom offsets
(vu_iat, occ pointer, u_value) and delegates the inner loop.
Files changed:
- source/source_pw/module_pwdft/dftu_pw.h
- declare compute_vu_spinor / compute_vu_scalar with doxygen
comments documenting pointer semantics and return value
- source/source_pw/module_pwdft/dftu_pw.cpp
- replace ~40 lines of inlined VU+energy loops in
compute_eff_pot_and_energy with 1 (nspin==4) or 1-2 (nspin==1/2)
calls to the free functions; energy_u accumulates the return values
- add compute_vu_spinor / compute_vu_scalar definitions in the
namespace dftu_pw block (code moved as-is from the inlined version)
Effects:
- compute_eff_pot_and_energy per-atom body shrinks from ~55 lines to
~20 lines of orchestration
- VU+energy kernels now independently testable
- no behavior change: same formula, same order (pauli_to_spin_basis
still called after the 4 Pauli blocks are filled, inside compute_vu_spinor)
Verification:
- make module_pwdft incremental build passed (verified by user)
- existing tests VUPotNspin1_DiagonalLocale, VUPotNspin2_TwoSpinChannels,
VUPotNspin4_PauliTransform (dftu_pw_test.cpp) cover the same formulas;
step 4d will rewire them to call the real functions
…r free functions
Step 4c of the dftu_pw decoupling plan. Extract the per-atom-per-kpoint
occ_mat accumulation loops from accumulate_occ_one_k into two free
functions in namespace dftu_pw:
- accumulate_occ_spinor: nspin==4 case, accumulates 4 Pauli blocks from
becp into occ_mat (npol=2 spinor layout).
- accumulate_occ_scalar: nspin==1/2 case, accumulates one spin channel
from becp into occ_mat.
Both functions are pure: they take raw pointers (occ_mat_out, becp) and
scalars describing the per-atom/per-kpoint offsets, no access to
Plus_U_Base members. accumulate_occ_one_k now computes these offsets
and delegates the inner ib/m1/m2 loop.
Files changed:
- source/source_pw/module_pwdft/dftu_pw.h
- add #include "source_base/matrix.h" (for ModuleBase::matrix wg param)
- declare accumulate_occ_spinor / accumulate_occ_scalar with doxygen
comments documenting pointer semantics and parameter meanings
- source/source_pw/module_pwdft/dftu_pw.cpp
- replace ~45 lines of inlined accumulation loops in
accumulate_occ_one_k with 1 call per branch (nspin==4 / nspin!=4)
- add accumulate_occ_spinor / accumulate_occ_scalar definitions in
the namespace dftu_pw block (code moved as-is)
- use std::conj explicitly (no 'using namespace std')
- drop unused 'is' parameter from accumulate_occ_scalar: the caller
selects the spin channel by passing the corresponding occ_mat
pointer (occ_mat[...][is].c); the function itself does not need is
Effects:
- accumulate_occ_one_k per-atom body shrinks from ~50 lines to ~15 lines
of orchestration
- occ accumulation kernels now independently testable
- no behavior change: same becp indices, same Pauli-block packing,
same weight handling
Verification:
- make module_pwdft incremental build passed (verified by user)
- existing tests LocaleAccumNspin12, LocaleAccumNspin4_PauliComponents
(dftu_pw_test.cpp) cover the same formulas via arithmetic
reimplementation; step 4d will rewire them to call the real functions
…pw.cpp
Step 4d-prerequisite of the dftu_pw decoupling plan. Enforce the
"header-implementation pairing" rule: the free-function declarations in
dftu_pw.h had their implementations stuffed at the bottom of dftu_pw.cpp
(alongside Plus_U_Base member functions), which is not a proper .h/.cpp
pair.
File structure after this commit:
- dftu_tools_pw.h (renamed from dftu_pw.h)
- declare 5 free functions in namespace dftu_pw
- include guard DFTU_TOOLS_PW_H
- dftu_tools_pw.cpp (new file)
- implement the 5 free functions (pauli_to_spin_basis,
compute_vu_spinor, compute_vu_scalar, accumulate_occ_spinor,
accumulate_occ_scalar); depends only on <complex> and matrix.h
- dftu_cal_occ_pw.cpp (renamed from dftu_pw.cpp via git mv)
- Plus_U_Base member functions only (cal_occ_pw, accumulate_occ_one_k,
reduce_occ_mat, sync_occ_to_uom, compute_eff_pot_and_energy)
- includes dftu_tools_pw.h to call the free functions
namespace stays dftu_pw (not renamed) to avoid churning all call sites;
only filenames change.
Files changed:
- source/source_pw/module_pwdft/dftu_tools_pw.h (git mv from dftu_pw.h)
- update include guard to DFTU_TOOLS_PW_H
- source/source_pw/module_pwdft/dftu_tools_pw.cpp (new)
- body moved verbatim from the former dftu_pw.cpp namespace block
- source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp (git mv from dftu_pw.cpp)
- drop the namespace dftu_pw block (moved to dftu_tools_pw.cpp)
- include "source_pw/module_pwdft/dftu_tools_pw.h" instead of dftu_pw.h
- source/source_pw/module_pwdft/CMakeLists.txt
- replace dftu_pw.cpp with dftu_tools_pw.cpp + dftu_cal_occ_pw.cpp
- source/Makefile.Objects
- replace dftu_pw.o with dftu_tools_pw.o + dftu_cal_occ_pw.o
- source/source_pw/module_pwdft/dftu_base.cpp
- update the pointer comment to reflect new filenames
Effects:
- header/implementation properly paired for the free functions
- dftu_tools_pw.cpp has minimal dependencies, can be linked into
unit tests without pulling in onsite_proj.h / parallel_reduce.h
- main implementation file (dftu_cal_occ_pw.cpp) retains its git history
via git mv (rename similarity ~63%, above the 50% threshold)
Verification:
- make module_pwdft incremental build passed (verified by user)
- step 4d proper (rewire tests to call real functions) follows next
Step 4d of the dftu_pw decoupling plan. The 7 tests in dftu_pw_test.cpp
previously used arithmetic re-implementations of the VU/energy/occ
formulas, meaning they could not catch bugs in the real dftu_pw
implementations (test and production code were two independent copies).
Now that the free functions live in dftu_tools_pw.{h,cpp} with minimal
dependencies (only <complex> and matrix.h), the tests can link against
the real implementations directly.
Tests rewired:
- VUPotNspin1_DiagonalLocale -> compute_vu_scalar
- VUPotNspin2_TwoSpinChannels -> compute_vu_scalar (twice, up/down)
- VUPotNspin4_PauliTransform -> pauli_to_spin_basis (in-place)
- EnergyNspin12_DiagonalLocale -> compute_vu_scalar (check return value)
- EnergyNspin4_WithOffDiagonal -> compute_vu_spinor (check return value)
- LocaleAccumNspin12 -> accumulate_occ_scalar
- LocaleAccumNspin4_PauliComponents -> accumulate_occ_spinor
Tests kept as arithmetic (out of dftu_tools_pw scope):
- EnergyWeightsAllNspin, BecpIndexNspin12vs4 (pure constants/arithmetic)
- MultiAtomSplitLayout_Nspin2 (Plus_U_Base member layout)
- OnsitePsOpKernel_Nspin2_Npol1 (onsite_op.cpp kernel)
Files changed:
- source/source_lcao/module_dftu/test/dftu_pw_test.cpp
- add includes: <vector>, source_base/matrix.h,
source_pw/module_pwdft/dftu_tools_pw.h
- replace inlined arithmetic loops with calls to the real free
functions; expected values unchanged
- VUPotNspin4_PauliTransform: m_size 3 -> 1 (the test only fills a
single (m1,m2) pair; m_size=1 matches the data layout)
- EnergyNspin4_WithOffDiagonal: pass diag_coeff=1.0 (the nspin==4
value used in cal_occ_pw)
- source/source_lcao/module_dftu/test/CMakeLists.txt
- add ../../../source_pw/module_pwdft/dftu_tools_pw.cpp to
dftu_pw_test SOURCES so the real implementations are linked
Effects:
- tests now exercise the same code path as cal_occ_pw
- arithmetic re-implementations removed (~80 lines of duplicated logic)
- any future change to the free functions is automatically covered
Verification:
- make dftu_pw_test build passed (verified by user)
- ctest -R dftu_pw_test passed (verified by user)
…TU_LCAO namespace Extract the 5 force/stress member functions of Plus_U from dftu_force.cpp into free functions declared in a new dftu_force.h header, mirroring the existing dftu_folding pattern. The top-level force_stress takes a Plus_U& parameter because it still calls Plus_U::cal_VU_pot_mat_real/complex (defined in dftu_tools.cpp); the four inner functions (cal_force_k, cal_stress_k, cal_force_gamma, cal_stress_gamma) are fully decoupled and take their dependencies (npol, nlocal, ks_solver, orb_cutoff, iatlnmipol2iwt, orbital_corr) as explicit parameters, so they are unit-testable without a Plus_U instance. Consolidate the two module-local namespaces dftu_force and dftu_folding into a single namespace DFTU_LCAO. The project-wide hamilt:: namespace (used by dftu_lcao_op.h/cpp, dftu_fs.cpp, dftu_lcao_op_legacy.h/cpp for operator classes inheriting from hamilt::OperatorLCAO<T>) is left untouched to avoid breaking the ABACUS hamilt operator framework. All callers updated: dftu_force:: and dftu_folding:: prefixes are replaced by DFTU_LCAO:: in dftu_force.cpp, dftu_occup.cpp, and force_stress_lcao.cpp; TITLE/timer/WARNING_QUIT identifier strings in dftu_force.cpp are renamed accordingly. Plus_U_Base gains two public read-only accessors (get_iatlnmipol2iwt, get_orbital_corr_vec) so the free functions can receive the lookup table and orbital_corr vector as parameters. Plus_U gains 8 public getters (get_paraV, get_npol, get_nlocal, get_ks_solver, get_orb_cutoff, is_gamma_only_local, is_cal_force, is_cal_stress) and cal_VU_pot_mat_real/complex are promoted from private to public so the free function force_stress can call them via the Plus_U& parameter. get_onebody_eff_pot remains private. Verification performed: - cmake --build build_max_para_test -j 4: clean build, no errors, no warnings - ./build_max_para_test/abacus_max_para --version: ABACUS version v3.11.0-beta8 - OMP_NUM_THREADS=1 ctest --test-dir build_max_para_test -R '^dftu_(pw_test|core_test|operator_test|lcao_test)$': 4/4 pass - python3 tools/03_code_analysis/agent_governance_check.py --staged: only warnings (header deps, test evidence, doc sync), all Exception allowed: yes, no blockers - 17_DS_DFTU: 45/50 sub-cases pass; the 5 PW Double-Spin failures are pre-existing baseline (verified via git stash + rerun with identical deviations), unrelated to this refactor - dft_plus_u==2 + force/stress path remains disabled per the existing comment in force_stress_lcao.cpp:429-454; not end-to-end tested.
mohanchen
force-pushed
the
2026-08-25-U3
branch
from
August 26, 2026 08:20
a1dbccf to
144c795
Compare
added 9 commits
August 26, 2026 16:49
Remove unused #include directives across 12 files in source/source_lcao/module_dftu/. Each removal was verified by symbol-usage grep against the file body (excluding the include lines themselves) and by compiling the dftu + hamilt_lcao CMake targets. Removed includes per file: - dftu_lcao.cpp: parameter.h, constants.h, global_function.h, inverse_matrix.h, memory_recorder.h, magnetism.h, charge.h and unused <cstdint>/<cmath>/<cstdio>/<cstring>/<fstream>/<iomanip>/ <iostream>/<sstream>; add focused matrix.h (for ModuleBase::matrix::operator() via occ_mat), tool_quit.h, tool_title.h - dftu_folding.cpp: parameter.h, hcontainer.h, hcontainer_funcs.h - dftu_force.cpp: parameter.h, constants.h, inverse_matrix.h, elecstate_lcao.h, magnetism.h, charge.h, <cmath>, <fstream>, <iomanip>, <iostream>, <sstream>, <stdio.h>, <string.h> - dftu_hamilt.cpp: parameter.h - dftu_lcao_op.cpp: hcontainer_funcs.h, <unordered_set> - dftu_lcao_op_legacy.cpp: dftu_lcao.h (already provided by its own .h) - dftu_occup.cpp: parameter.h - dftu_tools.cpp: timer.h (no direct ModuleBase::timer use), parameter.h - dftu_yukawa.cpp: parameter.h, <complex>, <fstream>, <iomanip>, <iostream>, <sstream>, <cstdio>, <cstring> - dftu_lcao.h: charge_mixing.h (still provided transitively via dftu_base.h), force_stress_arrays.h (not directly used here) - dftu_lcao_op.h: density_matrix.h (not directly used here) - dftu_lcao_op_legacy.h: timer.h (not directly used here) Note: scalapack_connector.h was kept in dftu_force.cpp / dftu_hamilt.cpp / dftu_occup.cpp -- these files call ScalapackConnector::gemm. Verification: OMP_NUM_THREADS=1 make -C build_std_para dftu hamilt_lcao => EXIT=0, no errors, no warnings. Full abacus build deferred to user; external modules that include dftu_lcao.h and use Charge_Mixing (chgmixing.cpp, esolver_ks.cpp/h) should still resolve via dftu_lcao.h -> dftu_base.h -> charge_mixing.h.
…_LCAO
Rename for consistency with the DFTU_LCAO free-function convention
established in dftu_force.h, and to disambiguate from the KS effective
potential V_eff:
* Plus_U::cal_eff_pot_mat_{complex,real} -> DFTU_LCAO::pot_uterm_{complex,real}
Extracted from member functions to free functions taking Plus_U&.
Internal this->paraV / this->nlocal replaced with dftu.get_paraV()
/ dftu.get_nlocal(); this->cal_VU_pot_mat_* replaced with
dftu.pot_onsite_*.
* Plus_U::cal_VU_pot_mat_{complex,real} -> Plus_U::pot_onsite_{complex,real}
Member, renamed only. The on-site Hubbard potential V_{mm'}.
* Plus_U::cal_occup_m_{k,gamma} -> Plus_U::cal_occ_mat_{k,gamma}
Member, renamed only.
* dftu_cal_occup_m -> DFTU_LCAO::cal_occ_mat
Moved into namespace DFTU_LCAO and renamed.
R-space variants Plus_U::cal_eff_pot_mat_R_double and
Plus_U::cal_eff_pot_mat_R_complex_double are intentionally left
untouched; they bind to the sparse R-space Hamiltonian path in
spar_u.cpp (force/stress) and will be addressed in a follow-up.
Timer and TITLE strings inside dftu_hamilt.cpp updated to match the
new function names for runtime log consistency.
No behavior change; pure rename + structural relocation.
Test directory source/source_lcao/module_dftu/test/ has no
references to any renamed function, so no test update is required.
Verification:
- rg confirms zero leftover references to the old names across the
whole codebase, except the intentionally-preserved R-space variants.
- python3 tools/03_code_analysis/agent_governance_check.py --staged
passes with only 2 PR-level WARNINGs (test/docs sync reminder),
both addressed by this message.
…u_hamilt.h / dftu_occup.h
Previously dftu_lcao.h bundled the DFTU_LCAO namespace free-function
declarations together at the bottom of the Plus_U class header. Split
them into two focused headers mirroring dftu_force.h convention:
* dftu_hamilt.h: DFTU_LCAO::pot_uterm_complex / pot_uterm_real
(implemented in dftu_hamilt.cpp)
* dftu_occup.h: DFTU_LCAO::cal_occ_mat template
(specialized in dftu_lcao.cpp, delegates to Plus_U::cal_occ_mat_{k,
gamma} in dftu_occup.cpp)
dftu_lcao.h no longer auto-includes the two new headers; each .cpp
that actually needs them includes the relevant one explicitly:
* dftu_hamilt.cpp -> dftu_hamilt.h (defines pot_uterm_*)
* dftu_lcao_op_legacy.cpp -> dftu_hamilt.h (calls pot_uterm_*)
* dftu_lcao.cpp -> dftu_occup.h (specializes cal_occ_mat)
* setup_dftu_lcao.cpp -> dftu_occup.h (calls cal_occ_mat)
Both new headers are self-contained: they forward-declare
'class Plus_U;' instead of including dftu_lcao.h, so there is no
include cycle.
Plus_U member function declarations (cal_eff_pot_mat_R_*,
cal_occ_mat_{k,gamma}, pot_onsite_*, etc.) remain in dftu_lcao.h
because C++ does not support partial classes.
Verification:
- rg confirms the two new headers are only included by the four .cpp
files listed above, with no remaining references via dftu_lcao.h.
- python3 tools/03_code_analysis/agent_governance_check.py --staged
passes with only PR-level WARNINGs (test/docs sync reminder), all
addressed by this message.
- The 'Confirm the declaration requires this include' reviewer note
applies to the four added includes; all four are required because
each .cpp either defines or calls the declared function and needs
the full signature, not a forward declaration.
…ee functions
The two pot_uterm_{complex,real} functions were extracted into the
DFTU_LCAO namespace in a previous commit, but their ModuleBase::TITLE
and timer::start/end calls still used 'Plus_U' as the owner string.
This made the runtime log misleading: the entries appeared to come
from a Plus_U member function while they are actually DFTU_LCAO
namespace free functions.
Update the first TITLE/timer argument from 'Plus_U' to 'DFTU_LCAO'
for all 6 calls in dftu_hamilt.cpp so the log owner matches the
actual namespace hosting the function.
Plus_U member functions in dftu_tools.cpp (pot_onsite_*),
dftu_occup.cpp (cal_occ_mat_*), and dftu_lcao.cpp keep 'Plus_U'
as their TITLE/timer owner, since those are still class members.
OperatorDFTU::contributeHk in dftu_lcao_op_legacy.cpp keeps
'OperatorDFTU' as the owner, since it is a hamilt::OperatorDFTU
member, not a Plus_U member nor a DFTU_LCAO free function.
Verification:
- rg confirms 6 TITLE/timer calls in dftu_hamilt.cpp now use
'DFTU_LCAO' as owner.
- python3 tools/03_code_analysis/agent_governance_check.py --staged
passes with no findings.
…cross LCAO and PW bases
The codebase mixed variable naming conventions for the same physical
quantities: uppercase 'VU' (LCAO base) and lowercase 'vu' (PW base)
for the Hubbard on-site potential, 'eff_pot' for the LCAO-basis
U-term effective potential, and 'eff_pot_pw' for the PW counterpart.
This commit unifies them to 'pot_onsite' and 'pot_uterm[_pw]',
matching the function-name conventions introduced earlier.
Variable renames:
* VU / vu -> pot_onsite (Hubbard on-site potential V_{mm'})
* eff_pot -> pot_uterm (LCAO-basis U-term effective potential)
* eff_pot_pw -> pot_uterm_pw (PW-basis U-term effective potential,
Plus_U_Base member plus accessor names get_eff_pot_pw_* / get_size_eff_pot_pw_*
get_pot_uterm_pw_* / get_size_pot_uterm_pw_*)
* eff_pot_pw_index -> pot_uterm_pw_index
* VU_tmp / vu_tmp -> pot_onsite_tmp
* vu_iat / vu_iat1 -> pot_onsite_iat / pot_onsite_iat1
* vu_ptr / vu_size / vu_host / vu_device -> pot_onsite_*
* vu_begin_iat -> pot_onsite_begin_iat
* rho_VU -> rho_pot_onsite
* dm_VU_dSm -> dm_pot_onsite_dSm
Function renames (per user request 'names containing vu should also be renamed'):
* transfer_vu -> transfer_pot_onsite
* cal_v_of_u -> cal_pot_onsite
* compute_vu_spinor -> compute_pot_onsite_spinor
* compute_vu_scalar -> compute_pot_onsite_scalar
* cal_vu (test helper) -> cal_pot_onsite
* local static 'compute_vu' in dftu_core_test -> compute_pot_onsite
Test fixture renames:
* VUPotentialTest -> PotOnsitePotentialTest
* VUPot* test names -> PotOnsitePot*
* OffDiagonalVU -> OffDiagonalPotOnsite
Scope (38 files):
* LCAO base: source/source_lcao/module_dftu/ (dftu_hamilt.{h,cpp},
dftu_tools.cpp, dftu_force.cpp, dftu_fs.cpp, dftu_lcao.{h,cpp},
dftu_lcao_op.{h,cpp}, dftu_lcao_op_legacy.cpp, test/dftu_*_test.cpp)
* PW base: source/source_pw/module_pwdft/ (dftu_base.{h,cpp},
dftu_cal_occ_pw.cpp, dftu_tools_pw.{h,cpp}, op_pw_proj.cpp,
onsite_proj.cpp, onsite_proj_tools.{h,cpp},
kernels/{onsite,force,stress}_op.{h,cpp},
kernels/cuda/{onsite,force,stress}_op.cu,
kernels/rocm/{onsite,force,stress}_op.hip.cu,
kernels/test/onsite_op_test.cpp)
* Cross-module callers: source/source_estate/module_charge/chgmixing.cpp
and charge_mixing.cpp (eff_pot_pw -> pot_uterm_pw),
source/source_esolver/esolver_ks_lcao.cpp (comment).
Out of scope (intentionally untouched):
* Non-DFTU files that happen to contain 'vu' as LAPACK/FORTRAN parameter
names (lapack_connector.h, scalapack_connector.h, gather_math_lib_info.cpp,
td_current_io_comm.cpp, base/module_container/*, etc.) -- these 'vu'
strings are LAPACK interface parameters, not Hubbard potential, and
renaming them would be incorrect.
* Plus_U_Base member 'uom_array' / 'uom_save' (occupation-related,
different physical quantity, not renamed here).
Verification:
* rg '\bVU\b|\bvu\b|\beff_pot\b|cal_v_of_u|transfer_vu|compute_vu|eff_pot_pw'
over source/source_lcao/module_dftu/, source/source_pw/module_pwdft/,
chgmixing.cpp, charge_mixing.cpp, esolver_ks_lcao.cpp returns no matches.
* python3 tools/03_code_analysis/agent_governance_check.py --staged passes
with only PR-level WARNINGs (test/docs sync reminder).
Test/Doc plan:
* Tests: pure rename, no semantic change; existing tests in
source/source_lcao/module_dftu/test/ and
source/source_pw/module_pwdft/kernels/test/ updated in lock-step.
* Docs: no INPUT parameter or user-facing behavior change; no
documentation update required.
…missed in previous commit The previous rename commit (3ac7790) used rg with word-boundary patterns, which missed identifiers like 'vu_device', 'vu_begin_iat', 'vu_begin_iat0', 'vu_begin', 'vu_in' -- because underscore is a word character, so '\bvu\b' does not match 'vu' followed by '_'. Compile failure: op_pw_proj.cpp:47: error: 'class hamilt::OnsiteProj<...>' has no member named 'pot_onsite_device' op_pw_proj.cpp:263: error: ... has no member named 'pot_onsite_device' This was because the member declaration in op_pw_proj.h:75 was still 'vu_device' while op_pw_proj.cpp called this->pot_onsite_device. Files fixed (loose-pattern search 'vu' as substring): * source/source_pw/module_pwdft/op_pw_proj.h: - vu_begin_iat -> pot_onsite_begin_iat (member) - vu_device -> pot_onsite_device (member) * source/source_pw/module_pwdft/op_pw_proj.cpp: - vu_begin_iat, vu_begin_iat0, vu_begin -> pot_onsite_* * source/source_lcao/module_dftu/dftu_fs.cpp: - vu_in -> pot_onsite_in (function parameter, 14 occurrences) Verification: - rg 'vu' (substring, no word boundary) over DFTU scope returns no matches. - python3 tools/03_code_analysis/agent_governance_check.py --staged passes with no findings.
… names Commit 5ac6ca7 claimed 'R-space versions cal_eff_pot_mat_R_* kept as-is for follow-up' in its message, but actually renamed the function definitions in dftu_hamilt.cpp to cal_pot_uterm_mat_R_*. The member declarations in dftu_lcao.h were not renamed, causing header/implementation mismatch: dftu_hamilt.cpp:127: error: no declaration matches 'void Plus_U::cal_pot_uterm_mat_R_double(int, double*, double*, int)' dftu_hamilt.cpp:157: error: no declaration matches 'void Plus_U::cal_pot_uterm_mat_R_complex_double(...)' Restore the original names cal_eff_pot_mat_R_double and cal_eff_pot_mat_mat_R_complex_double in dftu_hamilt.cpp so they match the declarations in dftu_lcao.h:80,82 and the call sites in spar_u.cpp:76,195. The R-space functions will be renamed in a follow-up commit that also updates spar_u.cpp and the header in lock-step. Verification: - rg 'cal_pot_uterm_mat_R' returns no matches (no stale callers). - rg 'cal_eff_pot_mat_R' shows consistent use across dftu_lcao.h (declarations), dftu_hamilt.cpp (definitions), spar_u.cpp (call sites).
… docs
The DFTU tests and input parameter docs used 'locale' as a variable
and annotation name for the occupation matrix. This is confusing
because 'locale' is also a C++ standard library concept
(std::locale, localization). The actual physical quantity is the
occupation matrix n_{mm'}, so rename to 'occ_mat' for clarity and
consistency with the existing Plus_U_Base member 'occ_mat' and
'get_occ_mat()' accessor.
Renames (variable scope limited to tests + comments):
* dftu_pw_test.cpp: locale_c / locale_up / locale_dn -> occ_mat_c /
occ_mat_up / occ_mat_dn (flattened occupation matrix passed to
compute_pot_onsite_scalar); comments updated.
* dftu_core_test.cpp: function parameters locale_up / locale_dn ->
occ_mat_up / occ_mat_dn (Matrix2D per-atom occupation matrices).
* dftu_lcao_op.cpp:192 comment 'Reads locale ...' -> 'Reads occ_mat ...'
* input_parameter.h:115 annotation 'mix locale' -> 'mix occ_mat'
(parameter name 'mixing_dftu' unchanged, no INPUT behavior change).
* read_inp_estruc.cpp:760 annotation 'mix locale' -> 'mix occ_mat'
Out of scope (intentionally untouched):
* Plus_U_Base::occ_mat member -- already named 'occ_mat', no change.
* Non-DFTU 'locale' occurrences (input_parameter.h is touched only for
the DFT+U annotation line).
Verification:
- rg '\blocale\b' over DFTU scope + module_parameter returns no matches.
- python3 tools/03_code_analysis/agent_governance_check.py --staged
passes with no findings.
Test/Doc plan:
* Tests: pure rename of test-local variables and comments; no
semantic change; existing tests in dftu_pw_test.cpp and
dftu_core_test.cpp updated in lock-step.
* Docs: no INPUT parameter name change (still 'mixing_dftu'); only
the annotation string is reworded for clarity. parameters.yaml
and input-main.md do not mention 'locale' so no update required
there.
- dftu_base.h: drop klist.h (UnitCell from unitcell.h, matrix via charge_mixing.h) - dftu_base.cpp: drop <cmath>/<complex>/<iomanip> (no usage) - dftu_output.cpp: drop <cstring>/<sstream> (no usage); replace parameter.h with global_variable.h (GlobalV source, PARAM unused) - dftu_cal_occ_pw.cpp: replace parameter.h with global_variable.h (GlobalV source, PARAM unused)
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.
Refactor DFT+U, step 4