目录
Mohan Chen

Refactor: DFT+U 10th refactor — HamiltLCAO operator-chain factory, force/stress free-function extraction, and nonlocal/InfoNonlocal modernization (#7961)

  • refactor(hamilt): remove GlobalV/PARAM deps from HamiltLCAO

Snapshot inp.nspin/inp.vl_in_h as members at construction so getHR_vector/updateHk/refresh no longer read global PARAM, and pass the EXX restart flag into the constructor as load_exx_flag instead of reading GlobalC::restart. Drop the now-unused global_variable.h include. Call sites in esolver_ks_lcao/esolver_double_xc/lcao_others compute the flag with the original logic, so behavior is unchanged.

Verified: make -j 30 in build_max_para_test builds with zero errors.

  • refactor(hamilt): drop unused default arg in updateSk

All call sites pass hk_type explicitly, so the default argument was dead weight. Removing it aligns with the no-default-arguments rule without changing any caller or behavior.

Verified: make -j 30 in build_max_para_test builds with zero errors.

  • refactor(hamilt): cache OperatorLCAO downcast in HamiltLCAO

updateHk and refresh repeated the same dynamic_cast<OperatorLCAO*> four times; cache the result in a private ops_lcao_ member filled on first use via getOperatorLCAO(). Also spell out the matrix() local type explicitly instead of auto.

Verified: make -j 30 in build_max_para_test builds with zero errors.

  • refactor(hamilt): split HamiltLCAO constructor operator-chain branches

Move the gamma-only and multi-k operator-chain construction out of the ~300-line constructor into private init_gamma_operators() / init_multik_operators(), cutting constructor cyclomatic complexity from 35 to 12. The TDDFT velocity-gauge block (TDEkinetic/TDNonlocal) stays guarded by std::is_same<TK, complex> inside init_multik_operators so the double instantiation dead-branch-eliminates it – those operators have no double instantiation, and hoisting them into a standalone function would produce undefined references.

Verified: make -j 30 in build_max_para_test builds and links with zero errors.

  • refactor(hamilt): dedupe DFTU/DeePKS operator construction

The DFT+U and DeePKS operator blocks were byte-identical in the gamma and multi-k branches. Extract them into private add_dftu_op() and add_deepks_op() helpers so each is defined once, removing ~60 lines of duplication and slightly lowering init_multik_operators complexity. Both operators have double and complex instantiations, so the helpers are safe for every HamiltLCAO specialization.

Verified: make -j 30 in build_max_para_test builds and links with zero errors.

  • refactor(hamilt): tidy HamiltLCAO misc cleanups
  • drop trailing return; at end of the constructor
  • make the TDDFT nonlocal term conditional up front instead of new-then-maybe-delete, removing a new/delete pair
  • remove trailing spaces on the include guard
  • drop redundant virtual on updateHk (override already implies it)
  • unify destructor to plain delete ops/hR/sR (delete nullptr is safe)
  • remove dead member const int istep = 0 (never read; the ctor parameter shadows it and is forwarded to OperatorEXX)

All changes are behavior-preserving cleanups; no allocation ownership path changes, so no memory leaks introduced.

Verified: make -j 30 in build_max_para_test builds and links with zero errors.

  • refactor(hamilt): prune unused includes and order by call chain

Drop six unused headers verified by grep + full build:

  • source_io/module_parameter/parameter.h (no PARAM usage)
  • source_hamilt/module_xc/xc_functional.h (no XC_Functional usage)
  • source_hsolver/hsolver_lcao.h and diago_elpa.h (no solver symbols)
  • module_operator_lcao/meta_lcao.h (no Meta node constructed)
  • module_operator_lcao/op_exx_lcao.h duplicate (already under __EXX)

Keep dspin_lcao.h: DeltaSpin is declared there (class name does not match the file name, so it survived an initial over-pruning caught by the build). Reorder the remaining includes to follow the constructor call chain: infra -> dftu base/setup -> electronic state -> operators (overlap -> kinetic -> nonlocal -> veff -> dftu -> dspin -> tddft).

Verified: make -j 30 in build_max_para_test builds and links with zero errors.

  • refactor(hamilt): extract LCAO operator-chain construction to factory

HamiltLCAO carried a construction-time factory responsibility (building the overlap/kinetic/nonlocal/veff/DFTU/DeePKS/TDDFT/spin-constrain operator chain) that is independent of the object’s runtime state. Move that logic out of the class into this-free factory functions, matching the explicit-parameter style used elsewhere (KListIO, dftu_pw).

New hamilt_lcao_factory.{h,cpp} in namespace hamilt:

  • LcaoOpsBundle<TK,TR>: the only two construction products – the chain head (ops) and the DeePKS V_delta(R) handle. hR/sR/hsk stay allocated by the caller and are passed in as inputs, keeping ownership clear.
  • build_gamma_ops / build_multik_ops: free functions with explicit parameters; add_dftu_op / add_deepks_op move to an anonymous namespace as internal helpers that append onto the chain head by reference.

HamiltLCAO constructor now calls the factory and assigns bundle.ops / bundle.v_delta_R; the four private builder method declarations are removed from the header, and the now-unused operator-node includes are pruned from hamilt_lcao.cpp.

Explicit instantiation (3 TK/TR combos x 2 functions) keeps the complex-only TDEkinetic/TDNonlocal guard inside build_multik_ops so the double instantiation still dead-branch-eliminates those references.

Verified: make -j 30 in build_max_para_test builds and links with zero errors after both the split and the include pruning.

  • refactor(hamilt): guard dft_plus_u with explicit branches and WARNING_QUIT

add_dftu_op previously used if (==2) … else …, which silently routed every non-2 value (including invalid ones) into the first-zeta NAO DFTU implementation. Per input semantics (dft_plus_u: 0 = off, 1 = radius-adjustable, 2 = first-zeta NAO), make the branches explicit:

== 1 -> DFTU (radius-adjustable, default new method, listed first) == 2 -> OperatorDFTU (first-zeta NAO, old method kept for testing) else -> ModuleBase::WARNING_QUIT on any out-of-range value

add_dftu_op is only reachable when dft_plus_u != 0, so the else branch turns previously-silent misclassification into a clear abort. Adds the source_base/global_function.h include for ModuleBase::WARNING_QUIT.

Verified: make -j 30 in build_max_para_test builds and links with zero errors; valid inputs (1/2) keep identical behavior.

  • refactor(hamilt): manage HamiltLCAO::hsk with std::unique_ptr

hsk is exclusively owned by HamiltLCAO (allocated in the SCF constructor, freed in the destructor, only read elsewhere), so hold it in a std::unique_ptr instead of a raw pointer. Pass .get() to the operator-chain constructors and factories, and drop the manual delete.

C++11 baseline: use reset(new …) instead of std::make_unique.

Verified: builds with make -j 30.

  • refactor(hamilt): manage HamiltLCAO hR/sR with std::unique_ptr

hR and sR are exclusively owned by HamiltLCAO (allocated in the constructors, freed in the destructor, only read elsewhere; no caller rebinds or deletes them). Hold them in std::unique_ptr and drop the manual deletes.

This requires getHR()/getSR() to return HContainer* by value instead of HContainer*&, since a unique_ptr member cannot expose a reference to its stored pointer. No call site relies on the reference (verified: nothing assigns to or rebinds through getHR()/getSR()), so the change is behavior-compatible.

C++11 baseline: use reset(new …) instead of std::make_unique.

Verified: builds with make -j 30.

  • fix makefile

  • remove useless TAC

  • refactor(dftu): rename DFTU operator classes for clarity

Rename DFTU<OperatorLCAO<TK,TR>> to DFTU_onsite and OperatorDFTU<OperatorLCAO<TK,TR>> to DFTU_firstzeta to better reflect the two DFT+U projection methods (radius-adjustable on-site vs first-zeta NAO) and to match the naming style of other LCAO operators (Overlap, Nonlocal, etc.).

  • refactor(dftu): replace GlobalFunc::ZEROS with std::fill

Remove the ModuleBase::GlobalFunc::ZEROS dependency in module_dftu by using std::fill on the raw buffers, consistent with the preference for std::fill/std::copy over ZEROS/COPYARRAY. T(0) covers both the double and std::complex instantiations of cal_pot_onsite/cal_pot_uterm.

  • refactor(dftu): drop __DEBUG guard around input asserts

Keep the nspin/null-pointer and nlm-size asserts active in all builds; they validate cheap invariants, not expensive debug-only checks.

  • fix(hamilt): allocate hR in HamiltLCAO vacuum constructor

The vacuum constructor documented “only HR and SR will be initialed as empty HContainer” but only allocated sR, passing an unallocated hR to the Overlap node. With raw pointers this was an uninitialized-value UB; with unique_ptr it is a null pointer that would segfault if any caller invokes init(). Allocate hR alongside sR to match the documented contract. hsk stays null because the vacuum path has no k-space matrix and never calls init().

No numerical change: the sole caller (esolver_gets) only invokes contributeHR(), which writes SR and never reads hR/hsk.

  • refactor(lcao): replace ForceStressArrays raw pointers with std::vector (steps 1-3)

Step 1: eliminate DSloc_R* aliasing in cal_dS by writing DHloc_fixedR_* directly in single_derivative (‘S’ branch), guarded by write_dsloc_r.

Step 2: convert 12 gamma-only stress members (DSloc_11..33, DHloc_fixed_11..33) from double* to std::vector.

Step 3: convert 7 multi-k stress members (DH_r, stvnl11..33) from double* to std::vector; replace OpenMP ZEROS lambda with resize(n, 0.0); update nullptr checks to .empty().

  • refactor(lcao): convert DSloc_x/y/z and DHloc_fixed_x/y/z to std::vector (step 4)

Replace 6 gamma-only force members from double* to std::vector. Update all call sites to use .data() for set_force and cal_pulay_fs, and nullptr checks to .empty() in check_folded_arrays.

  • refactor(lcao): convert DHloc_fixedR_x/y/z to std::vector (step 5)

Replace 3 multi-k force members from double* to std::vector. Resize with zero-init replaces new + ZEROS + OpenMP lambda in force_lcao_k.cpp and spar_dh.cpp. Remove all corresponding delete[]. Build verified in build_max_para_test.

  • refactor(lcao): convert DSloc_Rx/Ry/Rz to std::vector (step 6)

Replace 3 multi-k force members from double* to std::vector. Update write_dsloc_r guard from nullptr to .empty() in single_derivative. Update check_folded_arrays nullptr checks. Build verified in build_max_para_test.

  • refactor(lcao): replace InfoNonlocal raw pointers with std::vector

Convert all raw new/delete arrays in InfoNonlocal and its local temporaries to std::vector, eliminating manual memory management:

  • InfoNonlocal::Beta: Numerical_Nonlocal* -> std::vector
  • InfoNonlocal::nproj: int* -> std::vector
  • Set_NonLocal/Read_NonLocal local arrays -> std::vector
  • setupNonlocal(): use resize/assign instead of delete[]+new[]
  • Update all call sites to use .data() for raw-pointer interfaces
  • Align setup_nonlocal.h style (4-space indent, unified comments)

Files updated:

  • source/source_lcao/setup_nonlocal.h/.cpp
  • source/source_lcao/lcao_init_basis.cpp
  • source/source_esolver/esolver_lr_lcao_tddft.cpp
  • source/source_lcao/module_operator_lcao/test/test_{t_nl_cd,nonlocal}.cpp
  • source/source_lcao/module_rt/test/snap_psb_half_tddft_test.cpp
  • source/source_lcao/module_operator_lcao/test/tmp_mocks.cpp
  • refactor(lcao): eliminate GlobalV/PARAM dependencies in InfoNonlocal

Pass my_rank, log stream, and out_element_info as explicit parameters instead of reading GlobalV::MY_RANK, GlobalV::ofs_running, and PARAM.inp.out_element_info directly. This aligns with ABACUS governance rule 1 (no cross-layer control through globals).

Changes:

  • Set_NonLocal: add my_rank parameter, use it for plot() calls
  • Read_NonLocal: add out_element_info and log parameters
  • setupNonlocal: add my_rank parameter, forward to callees
  • Remove parameter.h include (no longer needed)
  • Update LCAONonlocalInfo::setupNonlocal wrapper signature
  • Update all call sites to pass GlobalV::MY_RANK explicitly
  • Update snap_psb_half_tddft_test.cpp Set_NonLocal calls with my_rank=0

Verified: make -j 30 in build_std_gpu passes. Quality score: setup_nonlocal.cpp 54 -> 68 (global_dependency eliminated).

  • refactor(lcao): extract functions to reduce cyclomatic complexity

Extract 5 helper functions from Set_NonLocal and Read_NonLocal:

  • build_soc_coefficients: SOC coefficient matrix construction (from Set_NonLocal)
  • build_beta_r: radial projector truncation and copy (from Set_NonLocal)
  • read_header: parse
    section (from Read_NonLocal)
  • read_dij: parse section (from Read_NonLocal)
  • read_projector: parse one block (from Read_NonLocal)

Also remove dead code: coefficient_D_in and coefficient_D_nc_in in Read_NonLocal were written but never read.

Cyclomatic complexity:

  • Set_NonLocal: 19 -> eliminated (main body now <10)
  • Read_NonLocal: 24 -> eliminated (main body now <10)
  • build_soc_coefficients: 14 (extracted, can be further split)

Verified: make -j 30 in build_std_gpu passes. Quality score: setup_nonlocal.cpp 68 -> 85.

  • refactor(lcao): encapsulate InfoNonlocal member variables

Convert 4 public member variables to private and add const getters/setters:

  • Beta -> get_Beta(), get_Beta(it), get_Beta_data(), resize_Beta()
  • nproj -> get_nproj(), get_nproj(it), assign_nproj()
  • nprojmax -> get_nprojmax(), set_nprojmax()
  • rcutmax_Beta -> get_rcutmax_Beta(), set_rcutmax_Beta()

Update all external call sites to use getters/setters instead of direct member access. LCAONonlocalInfo now uses the new interface.

Verified: make -j 30 in build_std_gpu passes. Quality score: setup_nonlocal.h 85 -> 87, lcao_nonlocal_info.h 96.

  • refactor(lcao): remove Read_NonLocal dead code and helpers

Remove Read_NonLocal, read_header, read_dij, and read_projector which were unreachable because readin_nonlocal was hardcoded to false. This eliminates ~300 lines of dead code including all NONLOCAL file parsing logic.

Also remove the readin_nonlocal branch from setupNonlocal, keeping only the Set_NonLocal path.

Verified: make -j 30 in build_std_gpu passes. Quality score: setup_nonlocal.cpp 85 -> 90, setup_nonlocal.h 87 -> 92.

  • fix(lcao): add get_nproj_ref for non-const lvalue reference

Set_NonLocal takes int& n_projectors which requires a modifiable lvalue. get_nproj(it) returns int by value which cannot bind. Add get_nproj_ref(it) that returns int& for this use case.

Update snap_psb_half_tddft_test.cpp to use get_nproj_ref(0) in both Set_NonLocal call sites.

Verified: make -j 30 in build_std_gpu passes.

  • fix(tddft): construct Nonlocal for hR pair insertion in velocity gauge

Nonlocal::initialize_HR inserts atom pairs into hR using a cutoff that includes the nonlocal pseudopotential radius, which may be larger than the orbital cutoff used by EKinetic/Veff. TDEkinetic and TDNonlocal both build hR_tmp by iterating over hR’s pairs, so skipping Nonlocal’s construction in TDDFT velocity gauge mode left hR with missing pairs, producing an incomplete hR_tmp and incorrect Hamiltonian.

Restore the original pattern: always construct Nonlocal when vnl_in_h is set, then conditionally add it to the operator chain (or delete it).

  • fix(lcao): forbid copying Numerical_Nonlocal and avoid vector reallocation

InfoNonlocal::Beta was changed from a raw array to std::vector in the recent refactor. Since Numerical_Nonlocal owns a raw Proj buffer but defines no copy semantics, Beta.resize() reallocating would shallow-copy elements, leaving dangling Proj pointers and causing SEGFAULTs in all module_deepks unit tests (and any run with ntype > 1).

Fix without introducing copy/move semantics:

  • Explicitly delete Numerical_Nonlocal copy constructor and copy assignment, so any accidental copy now fails at compile time.
  • Replace Beta wholesale via move-assigning a fresh vector instead of resize(), so elements are constructed in place and never relocated.
  • Drop the Beta.resize(1) preallocation in InfoNonlocal’s constructor (also in the operator_lcao test mock) to keep the invariant.

Verification: static analysis only; build and test run not performed.

  • fix(test): allocate Beta before direct Set_NonLocal calls in tddft test

snap_psb_half_tddft_test calls InfoNonlocal::Set_NonLocal directly without setupNonlocal(), which is the only path that used to size the Beta array. After the raw array was replaced by std::vector and the resize(1) preallocation was removed, Beta was empty and Beta[it] was out of bounds, causing SEGFAULT in MODULE_LCAO_tddft_snap_psibeta_half_test.

Add resize_Beta(1) next to the existing assign_nproj(1, 0) in both fixture SetUp() functions.

Verification: static analysis only; build and test run not performed.

  • refactor(lcao): split Record_adj::for_2d and deduplicate adjacency check

Extract the copy-pasted direct-cutoff / beta-bridge adjacency test into a single file-local is_adjacent helper shared by both passes, and split the ~230-line for_2d (cyclomatic complexity 31) into count_adjacent, allocate_info, and fill_info orchestrated by a thin for_2d wrapper. Public members and the int*** info layout are unchanged so downstream consumers need no modifications.

Code quality score for record_adj.cpp: 59 -> 84.

  • refactor(lcao): pass npol explicitly to Record_adj::for_2d

Remove Record_adj’s reads of PARAM.globalv.npol, PARAM.inp.out_level and GlobalV::ofs_running. npol is now an explicit argument of for_2d / count_adjacent (no default argument per governance), and the ParaV.nnr log is emitted by the three callers instead. Add a public const getAdjacentInfo() observer on Grid_Driver to expose adj_info read-only.

Code quality score for record_adj.cpp: 84 -> 96 (global_dependency gone).

  • refactor(lcao): flatten Record_adj info storage into a single vector

Replace the manually managed int*** info (and the raw int* na_each / iat2ca) with containers. Adjacent records are stored flat in one std::vector<std::array<int,5>> with an info_offset prefix-sum table, exposed read-only through get_info(iat, cb). This removes all raw new/delete, the info_modified flag, and the nested-vector pointer chasing, and keeps each atom’s records contiguous for the OpenMP fill loop. na_each / iat2ca become std::vector. Update the three consumers (density_matrix_io, td_current_io, pulay_fs_temp) and the dm_r_init test to the new layout.

Code quality score for record_adj.cpp: 96 -> 100 (raw_new_keyword gone).

  • refactor(lcao): use injected inp_->out_level at for_2d call sites

The ParaV.nnr log moved out of Record_adj in the previous commit read PARAM.inp.out_level at each caller, which raised the PR-level global dependency budget. All three callers already hold an injected INPUT pointer (this->inp_), so read out_level from it instead of PARAM.inp, removing three PARAM.inp references.

  • refactor(lcao): remove dead Force_Stress_LCAO::integral_part

The two integral_part specializations were the only callers of Force_LCAO::ftable, and integral_part itself has no callers since the operator-based force/stress path took over. Remove the dead entry point first so the ftable implementations can be deleted next.

Verified: make -j 30 in build_max_para_test passes (100% Built target abacus_max_para).

  • refactor(lcao): delete dead force_lcao_gamma.cpp and force_lcao_k.cpp

After removing Force_Stress_LCAO::integral_part (the only caller of Force_LCAO::ftable), the allocate/ftable/finish_ftable specializations in these two files have no remaining callers. Delete the files and drop them from CMakeLists.txt and Makefile.Objects. The active force/stress path uses operator-based cal_force_stress plus PulayForceStress::cal_pulay_fs directly.

Verified: make -j 30 in build_max_para_test passes (100% Built target abacus_max_para).

  • refactor(lcao): drop dead Force_LCAO method declarations

With ftable/allocate/finish_ftable deleted, their declarations plus the never-defined average_force/cal_fedm/cal_ftvnl_dphi/cal_fvl_dphi declarations are dead. Force_LCAO now only carries the actively used cal_edm and its ParaV/pot members. Remove the declarations and the includes (matrix.h, two_center_bundle.h, force_stress_arrays.h, setup_deepks.h) that only served them.

Verified: make -j 30 in build_max_para_test passes (100% Built target abacus_max_para).

  • refactor(lcao): drop dead DSloc_*/DHloc_fixed_* stress arrays

The DSloc_11/12/13/22/23/33 and DHloc_fixed_11/12/13/22/23/33 arrays were only written by the gamma-only cal_stress branch of single_derivative via set_stress, and never read anywhere. The active LCAO stress path computes the overlap/kinetic/nonlocal contribution through the operator-based cal_force_stress instead. Remove the 12 arrays from ForceStressArrays, the set_stress call site, and the now unused set_stress declaration/implementation. single_derivative keeps its cal_stress parameter because the multi-k branch still uses it to fill DH_r and stvnl*.

Verified: make -j 30 in build_max_para_test passes (100% Built target abacus_max_para).

  • fix(lcao): add missing TwoCenterBundle include for CUDA build

Forward-declare TwoCenterBundle in force_stress_lcao.h and explicitly include two_center_bundle.h in force_stress_lcao.cpp to fix CUDA compilation where the indirect include chain is broken.

  • refactor(lcao): rename misplaced .hpp headers to .h

lcao_hs_arrays.hpp is a pure declaration header and the two pulay_fs_*.hpp files hold template implementations; none of them are .hpp implementation headers in the prohibited sense. Rename them to .h and update the 11 include sites so the hpp_implementation rule no longer flags them.

Quality score: lcao_hs_arrays 34->84, pulay_fs_temp 23->73, pulay_fs_gint 46->96.

  • refactor(lcao): pass gamma_only_local/nspin/npol into sparse_format

sparse_format::cal_dH/cal_dS/cal_dSTN_R/destroy_dH_R_sparse read PARAM.globalv.gamma_only_local, PARAM.inp.nspin and PARAM.globalv.npol directly. Pass them as explicit arguments so the functions no longer depend on global INPUT state, in line with the rule that cross-layer control through PARAM should not grow.

The remaining PARAM.globalv.nlocal in cal_dH is kept because the caller has no local value for it; threading it further would only move the global read, not remove it.

Quality score: spar_dh.cpp 58->77.

  • refactor(lcao): pack single_overlap/single_derivative args into ST_env/ST_elem

single_overlap and single_derivative each took 29 parameters, mixing three kinds of state: the read-only build environment (basis, parallel layout, unit cell, spin config), the per-element inputs (operator type, orbital and angular-momentum indices, displacement) and the outputs.

Pack them into two aggregate types in LCAO_domain:

  • ST_env: everything fixed for one build_ST_new call, built once before the omp region. This also removes the PARAM.globalv.gamma_only_local reads inside both functions.
  • ST_elem: the per-matrix-element inputs, built once per inner-loop iteration and shared by both call sites.

Dead parameters tau1/tau2 (only dtau was used) are dropped. Local index variables are lowercased (t1/l1/n1/i1, mm1/mm2 for the magnetic quantum number to avoid clashing with the m1/m2 indices).

The functions stay in lcao_set_st.cpp so they remain inlinable at their hot inner-loop call sites; the parameter unpacking is POD and optimises away. Quality score: lcao_domain.h 36->82.

  • refactor(lcao): split single_deriv S/T branches into helpers

single_deriv (renamed from single_derivative) had cyclomatic complexity 24, all of it in the multi-k branch that dispatches on operator type (S/T) x nspin (1/2/4) x spin index is. Extract the per-element writes into two static free functions, set_deriv_s and set_deriv_t, kept in this translation unit so they stay inlinable at the hot inner-loop call site. The main function now only computes the spin index and dispatches.

The nspin==4 S-branch “write olm or write zero” blocks were two symmetric if/else arms; collapse them to is==0 ? olm[i] : 0.0.

Also fix WARNING_QUIT labels that named LCAO_domain::build_ST_new from inside set_deriv_s/set_deriv_t/single_overlap/single_deriv; they now name the function actually raising them so the log points at the right place.

Quality score: lcao_set_st.cpp 45 -> 59.

  • refactor(lcao): extract per-element nonlocal accumulators

Split the energy/force accumulation of one <psi|beta><beta|psi> matrix element out of build_Nonlocal_mu_new into three static helpers (accum_nlm_energy/accum_nlm_force_soc/accum_nlm_force). Bundle the call-invariant inputs into NL_env and the per-element indices into NL_elem so the helpers take explicit arguments instead of reaching into the enclosing loop, and drop the four nlm_cur*_e/f pointer aliases. Lowers the function cyclomatic complexity from 60 to 40.

  • refactor(lcao): extract build_psi_beta from build_Nonlocal_mu_new

Move the <psi|beta> (and <d psi|beta>) generation loop into a static build_psi_beta helper, keeping its OpenMP-parallel iat loop inside the helper and passing nlm_tot/nlm_tot1 out by reference. The main function now only drives Step 2, lowering build_Nonlocal_mu_new cyclomatic complexity from 40 to 29.

  • refactor(lcao): extract Step2 inner orbital loop into accum_nlm_block

Move the (j, k) orbital loop that dispatches to the energy/force accumulators out of build_Nonlocal_mu_new into a static accum_nlm_block helper, packing the per-neighbour inputs (atoms, orbital offsets, iat slot and the two <psi|beta> block keys) into a file-local NL_pair struct. Also normalise the remaining K&R brace placement in this file. Lowers build_Nonlocal_mu_new cyclomatic complexity from 29 to 21.

  • refactor(lcao): extract force/stress assembly into helpers

Move the 32 local force/stress part matrices in getForceStress into LCAOForceParts/LCAOStressParts containers, and extract the force assembly+print and stress assembly+print blocks into assemble_and_print_force / assemble_and_print_stress.

  • refactor(lcao): extract per-term force/stress calculators from getForceStress

Split the body of getForceStress into focused helpers: cal_operator_fs (kinetic/overlap/nonlocal/rt-TDDFT/local-Pulay/DeltaSpin), cal_deepks_fs, cal_vdw_and_fields_fs (vdW, E-field, rt-TDDFT E-field, gate, implicit solvation), cal_dftu_fs and cal_exx_fs. The main function now only orchestrates, dropping its cyclomatic complexity below the report threshold. No behavior change.

  • fix(lcao): pass two_center_bundle into cal_dftu_fs and drop const in cal_operator_fs

cal_dftu_fs reads two_center_bundle.overlap_orb_onsite, and cal_foverlap_rt inside cal_operator_fs takes a non-const UnitCell&. Fix the extracted helper signatures so the file compiles.

  • refactor(lcao): move PW stress and force symmetrization to free functions

Extract calStressPwPart and forceSymmetry from the Force_Stress_LCAO class template into free functions LCAO_domain::cal_stress_pw and LCAO_domain::symmetrize_force in the new force_stress_pw.h/.cpp. Neither depends on the electronic template type T, so they no longer need to be instantiated per T.

calForcePwPart stays a member: Forces::cal_force_* are protected and only accessible through the existing friend declaration on Force_Stress_LCAO.

  • refactor(lcao): move per-term force/stress calculators to free functions

Extract cal_deepks_fs, cal_exx_fs, cal_vdw_fields_fs and cal_dftu_fs from the Force_Stress_LCAO class template into free functions in the new force_stress_terms.h/.cpp under LCAO_domain. cal_vdw_fields_fs does not depend on the electronic template type T and is a plain function; the other three are function templates with explicit instantiation for double and std::complex.

cal_deepks_fs now takes Parallel_Orbitals& explicitly instead of reaching Force_LCAO::ParaV, removing its dependence on the Force_LCAO member.

  • refactor(lcao): move force/stress assembly to free functions

Extract assemble_and_print_force and assemble_and_print_stress from the Force_Stress_LCAO template class into LCAO_domain free functions assemble_print_force / assemble_print_stress in the new force_stress_assemble.{h,cpp}. The force threshold is passed in as an explicit argument instead of reading the private static member, and the new translation unit carries its own explicit instantiations.

  • refactor(lcao): split force/stress assembly helpers to cut complexity

Extract the per-component accumulation (sum_force_terms / sum_stress_terms) and the test-only printers (print_force_parts / print_force_invalid_table) out of assemble_print_force and assemble_print_stress into file-local helpers. This drops the two assemble functions’ cyclomatic complexity from 34/16 to 12/11 and lifts force_stress_assemble.cpp above the quality gate.

  • refactor(lcao): split vdw/external-field terms and tidy term helpers

Extract copy_vdw_terms and cal_external_field_forces out of cal_vdw_fields_fs to remove its cyclomatic-complexity deduction, give the DFT+U adjacent-atom list an explicit std::vector type instead of auto, and rewrap two over-length explicit-instantiation lines. force_stress_terms.cpp now passes the quality gate.

  • style(lcao): replace auto with explicit DMK vector types, rewrap long line

Give the two assign_dmk_ptr specializations an explicit std::vector<std::vector<…>>& type for the DMK vector instead of auto, and rewrap one over-length cal_force_stress call. (An attempted split of cal_operator_fs’s per-spin branches was reverted: the extra helper parameters cost more on the quality gate than the cyclomatic-complexity deduction they removed.)

  • refactor(lcao): drop unused assign_dmk_ptr param, dedupe include/comments
  • Remove the unused gamma_only_local parameter from assign_dmk_ptr and its call site in force_stress_terms.cpp (the specializations select the DMK pointer purely from the template type).
  • Drop the duplicate parameter.h include in force_stress_lcao.cpp.
  • Reword the nspin=4 branch comments so they are distinct from the nspin=1/2 branch instead of duplicated boilerplate.

Verified: make -j 30 abacus_max_para in build_max_para_test passes. code_quality_score.py force_stress_lcao.cpp: 29 -> 33 (duplicate_doc_block deduction removed).

  • refactor(lcao): pass INPUT scalars via FSCalcConfig, drop PARAM reads

getForceStress and its two helpers used to read the global PARAM object for nspin/nbands/t_in_h/sc_mag_switch/device. Introduce a small FSCalcConfig aggregate and pass those five values in explicitly from the two esolver call sites (both already hold this->inp_). This removes the last PARAM reads from force_stress_lcao.cpp and bundles the scalars into one reference argument.

Verified: make -j 30 abacus_max_para in build_max_para_test passes. code_quality_score.py force_stress_lcao.cpp: 29 -> 60 (global_dependency deduction removed; file now passes the >=60 bar).

  • fix bug

  • fix bug

  • fix(lcao): guard ForceStressArrays writes in build_ST_new derivative path

Add defensive empty checks before writing DHloc_fixedR_*, DH_r and stvnl* arrays in set_deriv_s/set_deriv_t, and validate required buffers at build_ST_new entry when calc_deri=true in multi-k mode.

This prevents potential out-of-bounds access if a future caller passes unallocated ForceStressArrays members, and makes the caller contract explicit.

  • refactor(force): share PW/LCAO force finalize and move PW-part stress into module_pwdft
  • Add ModuleBase::remove_net_force (mathzone.h) as a free function and ModuleSymmetry::symmetrize_force_cartesian, replacing the duplicated inline net-force zeroing and Cartesian->direct->symmetrize->Cartesian code in force_pw.cpp and force_stress_assemble.cpp. Both take lattice vectors from the Symmetry object so no UnitCell dependency is added.
  • Move LCAO_domain::cal_stress_pw into Stress_Func::stress_pw_terms so the PW-basis stress assembly lives in module_pwdft.
  • Delete force_stress_pw.h/cpp and update CMakeLists.txt/Makefile.Objects.
  • fix(force): update symmetrize_force_cartesian call to new signature

The call site in force_pw.cpp still passed (ucell, p_symm, force); update to (p_symm, this->nat, force) to match the new signature that takes lattice vectors from the Symmetry object.

  • fix(force): pass current lattice vectors to symmetrize_force_cartesian

Symmetry::a1/a2/a3 are overwritten by lattice_type() with the symmetry-optimized lattice during the analysis, so they no longer match the current cell. Using them for the Cartesian<->direct conversion symmetrized forces in the wrong basis and broke PW force results (008_PW_UPF201_USPP_NaCl, 805_PW_LT_*, etc.). Take the lattice vectors as explicit arguments so callers pass ucell.a1/a2/a3, restoring the pre-refactor behavior.

  • refactor(lcao): rename force_lcao.h to edm.h and Force_LCAO to CalEDM

The header force_lcao.h no longer declares any force-related interface; its only remaining content is the private cal_edm method implemented in edm.cpp. Rename the file to edm.h and the class to CalEDM so names match the actual responsibility, and rename the Force_Stress_LCAO member from flk to edm_cal for clarity.

Verified: cmake –build build_max_para_test –target hamilt_lcao -j 16 (rebuilt edm.cpp, force_stress_lcao.cpp, force_stress_terms.cpp) passed.

  • refactor(lcao): extract DeePKS force/stress writers to drop assemble templates

Setup_DeePKS::write_forces/write_stress do not depend on the electronic type TK; move them to DeePKS_domain free functions taking dpks_out_type explicitly. assemble_print_force/stress then lose their only T-dependent argument and become plain functions, removing the explicit instantiations.

Verified: build_max_para_test (ENABLE_MLALGO=ON) make abacus_max_para passes; ./abacus_max_para –version -> v3.11.0-beta9; agent governance check has no blockers (PARAM net_delta=0, migration-neutral).

  • fix some small issues

Co-authored-by: abacus_fixer mohanchen@pku.eud.cn

3小时前8136次提交

About ABACUS

ABACUS (Atomic-orbital Based Ab-initio Computation at UStc) is an open-source package based on density functional theory (DFT). The package utilizes both plane wave and numerical atomic basis sets with the usage of pseudopotentials to describe the interactions between nuclear ions and valence electrons. ABACUS supports LDA, GGA, meta-GGA, and hybrid functionals. Apart from single-point calculations, the package allows geometry optimizations and ab-initio molecular dynamics with various ensembles. The package also provides a variety of advanced functionalities for simulating materials, including the DFT+U, VdW corrections, and implicit solvation model, etc. In addition, ABACUS strives to provide a general infrastructure to facilitate the developments and applications of novel machine-learning-assisted DFT methods (DeePKS, DP-GEN, DeepH, DeePTB etc.) in molecular and material simulations.

Online Documentation

For detailed documentation, please refer to our documentation website.

See our Github Pages for more tutorials and developer guides.

关于
433.9 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号