Repository navigation
update to the newest version 2026-09-14 - #379
Merged
Merged
Conversation
* fix: align module hs sparse output with threshold * fix: stabilize module hs sparse output controls * test: fix module hs regression test builds
…ay (#7536) The HContainer copy constructor was unconditionally zeroing out the data_array when wrapping existing memory. This caused getHR_vector() to erase both spin channels' HR data for nspin=2, resulting in all-zero HR output when out_mat_hs2 is enabled. Fix: only zero memory when data_array is nullptr (fresh allocation); preserve existing data when wrapping external memory. Also add integration test scf_out_hsr_spin2 (nspin=2 + out_mat_hs2) and update catch_properties.sh to compare hrs2_nao.csr for nspin=2.
) * fix: correct Pauli-to-spinor Hamiltonian conversion for nspin=4 Fix two bugs in LCAO non-collinear Hamiltonian construction: 1. Wrong sign in off-diagonal elements: H_{up,down} = B_x + i*B_y (wrong) should be B_x - i*B_y (correct), and vice versa for H_{down,up}. Fixed by correcting clx_j coefficients in merge_hr_part_to_hR(). 2. Missing complex conjugate in lower triangle fill: H(-R) used transpose instead of conjugate transpose, breaking Hermiticity for complex matrices. Fixed by using std::conj() when filling lower triangle. These errors caused the non-collinear Hamiltonian to be the complex conjugate of the correct result, leading to incorrect spin textures in nspin=4 calculations. The PW code path was not affected. Add test case and verification script to validate: - H(R=0) Hermiticity: max|H - H^dagger| < 1e-10 - Off-diagonal phase: Im(H_{up,down}) < 0 for m||+y direction See tests/03_NAO_multik/verify_hamiltonian_convention/TEST_DESIGN.md for details. * fix: correct Pauli-to-spinor conversion in DFT+U and DeltaSpin for nspin=4 Fix three critical bugs in non-collinear (nspin=4) LCAO calculations: 1. DFT+U transfer_vu (dftu_lcao.cpp): Fix sign error in Pauli-to-spinor conversion. The off-diagonal elements had wrong imaginary part sign: - Before: V_{up,down} = 0.5*(V_x + i*V_y) (wrong) - After: V_{up,down} = 0.5*(V_x - i*V_y) (correct, from sigma_y) 2. DFT+U force/stress (dftu_force_stress.hpp): Convert VU from Pauli basis to spinor basis before force calculation. The old code incorrectly mixed Pauli-basis VU with spinor-basis DM. 3. DeltaSpin force/stress (dspin_force_stress.hpp): Convert lambda from Pauli basis to spinor basis. The constraint force F = lambda·dM/dR requires proper Pauli-to-spinor conversion: - lambda_spinor = (lambda_z, lambda_x, lambda_x, -lambda_z) for (uu, ud, du, dd) components. These fixes ensure consistent Pauli-to-spinor conversion across all modules: - H construction (gint_common.cpp): already fixed - DFT+U Hamiltonian: fixed in this commit - DFT+U force/stress: fixed in this commit - DeltaSpin force/stress: fixed in this commit Verified by scf_u_spin4 test (nspin=4 + DFT+U): SCF converges correctly. * chore: remove .py and .md test files from PR * fix: correct DFT+U force for nspin=4 - DM is stored in Pauli basis, not spinor basis Two bugs fixed in dftu_force_stress.hpp: 1. Removed incorrect VU Pauli-to-spinor conversion: DM for nspin=4 is stored in Pauli basis (rho_0, rho_x, rho_y, rho_z) per func_xyz_to_updown(), so VU must also stay in Pauli basis for the force trace formula F = -Tr(VU * dDM/dR). 2. Removed force *= 2.0 for nspin=4: Pauli basis already includes all spin channels, unlike nspin=1 where the factor of 2 accounts for spin degeneracy. Updated scf_u_spin4 result.ref accordingly. * fix: remove force*=2.0 for nspin=4 in DeltaSpin - Pauli basis already covers all spin channels * fix: add missing blacs_context to ELPA Constructor 1 for nspin=4 support Constructor 1 of ELPA_Solver was missing elpa_set_integer("blacs_context", ...) while Constructor 2 (otherParameter) already had it. Without blacs_context, ELPA's internal MPI operations (e.g. MPI_Bcast in complex Cholesky and invert_triangular) can fail with INVALID DATATYPE when using complex eigensolves. Also update scf_angle_spin4 result.ref with corrected reference energy. * fix: correct rho_y sign in spinor-to-Pauli DM conversion (func_xyz_to_updown) For Pauli decomposition: rho = rho_0*I + rho_x*sigma_x + rho_y*sigma_y + rho_z*sigma_z sigma_y = [[0,-i],[i,0]], so rho_updown = rho_x + i*rho_y, rho_downup = rho_x - i*rho_y Thus rho_y = Im(rho_updown - rho_downup) = tmp[1].imag() - tmp[2].imag]. Previously the real version had -tmp[1].imag()+tmp[2].imag() = -2*rho_y (wrong sign), and the complex version had i*(tmp[1].imag()-tmp[2].imag()) = 2i*rho_y (wrong formula). This broke rotational invariance: mag along y gave wrong energy (~4 eV deviation vs x/z). * test: update scf_angle_spin4 and scf_u_spin4 result.ref after DM rho_y fix * chore: revert density_matrix.cpp rho_y fix (wrong branch) and remove verify_hamiltonian_convention test dir - Revert density_matrix.cpp func_xyz_to_updown rho_y sign fix from commit 52ee608 (belongs on a separate DM-fix branch) - Remove tests/03_NAO_multik/verify_hamiltonian_convention/ (debug helper) - Update result.ref for scf_angle_spin4 and scf_u_spin4 to match current code (Pauli-to-spinor + ELPA fixes only) * fix: restore density_matrix.cpp rho_y sign fix (paired with gint_common clx_j fix) The gint_common.cpp fix corrects Pauli→spinor (H construction) and the density_matrix.cpp fix corrects spinor→Pauli (DM Fourier transform). Both must use the same σ_y convention for self-consistency. Also update result.ref files for both test cases. * fix: correct DFT+U force/stress reference values and clean up empty nspin=4 block Both VU (from cal_v_of_u) and DMR are stored in Pauli basis for nspin=4, so the Pauli-to-spinor conversion in force/stress calculation is NOT needed. The previous result.ref for scf_u_spin4 (totalforceref=6.562) was incorrect because it was generated with code that mixed Pauli-basis VU with incorrectly converted values. The correct force is 11.33, consistent with the physical Pauli-basis trace Tr(VU * dDM/dR). Changes: - Remove empty if(nspin==4) block in dftu_force_stress.hpp (no conversion needed) - Update scf_u_spin4/result.ref: totalforceref 6.562 -> 11.332 (correct value) - Update scf_angle_spin4/result.ref: energy/stress to match computed values - Add scf_angle_spin4/threshold: relax energy threshold to 1e-5 eV for non-collinear calculation numerical reproducibility - Update scf_out_dos_spin4/result.ref: force/stress to match computed values
…on and add unit test (#7539) * Refactor: Share RT-TDDFT projector snap integration * Docs: Comment RT-TDDFT projector snap integration
* Toolchain: Rely on installed CMake config file for Cereal and RapidJSON * Remove FindLibxc.cmake * CMake: Use interface target for feature dependencies * Add "-Werror=dev" in CMake for "Test" workflow * Follow-up CMake cleanups * Document CMAKE_PREFIX_PATH and remove hints for LibXC_DIR * Fix Libxc version issue and remove fatals that do not make sense * Follow up to #7521 * CI: Build ABACUS with Ninja generator * Sync abacus_disable_feature_definitions settings * Guard every "apt" system package installation under "sudo"
Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
* Test: Refactor DeePKS unit tests * Test: Address DeePKS unit test review comments
* refactor(cell): remove unused cross-module includes in read_atoms.cpp
Drop two dead includes that create needless reverse dependencies from
source_cell onto higher layers:
- source_estate/read_orb.h (elecstate::read_orb_file not used here;
the real user is read_atoms_helper.cpp)
- source_basis/module_ao/ORB_read.h (ORB / LCAO_Orbitals not used here)
Verified by compiling the `cell` target with ENABLE_LCAO=ON so the
former `#ifdef __LCAO` block was actually exercised.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor: remove dead cross-module includes on reverse-dependency edges
Static scan + per-target compile verification identified 9 unused
includes that create reverse/lateral dependency edges between modules.
Removing them weakens the coupling without any behavior change:
io -> md input_conv.cpp (md_func.h)
estate -> lcao elecstate_energy_terms.cpp, elecstate_print.cpp
(module_deepks/LCAO_deepks.h)
lcao -> pw rdmft_tools.cpp (structure_factor.h),
wavefunc_in_pw.cpp (soc.h)
lcao -> io FORCE_gamma.cpp, FORCE_k.cpp (module_hs/write_HS.h)
pw -> io forces_cc.cpp, forces_scc.cpp (module_output/output_log.h)
Verified by building io_basic, elecstate, rdmft, hamilt_lcao and
module_pwdft (ENABLE_LCAO=ON) after removal; all link targets compile.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(esolver): remove 29 dead io includes (esolver -> io hygiene)
Remove unused source_io includes across the esolver drivers. These are
on the allowed esolver->io direction, so this is include hygiene rather
than decoupling, but it trims 29 needless includes.
Verified three ways:
1. `make esolver` (ENABLE_LCAO=ON) recompiles all 21 TUs, 0 errors.
2. Feature-guarded headers checked explicitly since __RAPIDJSON,
__EXX/__LIBRI and __MLALGO are OFF in this build: the json
(init_info.h/output_info.h) and restart_exx_csr.h symbols are
unused in their consumers (Json::add_output_scf_mag in
esolver_ks.cpp comes from output_info.h, which is kept).
3. Whole-file precise-symbol sweep (incl. all #ifdef blocks) finds
no specific symbol of any removed header in its consumer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor: remove 2 more dead cross-module includes
Two dead includes missed by the first reverse-edge pass:
estate -> lcao elecstate_energy_terms.cpp
(module_deltaspin/spin_constrain.h; SpinConstrain
is not referenced anywhere in the file)
esolver -> io esolver_double_xc.cpp
(module_hs/write_HS.h; only a comment mentions
ModuleIO::write_hsk(), no actual call)
Verified: no header symbol appears anywhere in the consumer (guards
included), and `make elecstate` / `make esolver` build cleanly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: update interfaces with ATAT * feat: update path to PP&ORB * feat: re-run the examples use pp&orb in tests/ * feat: update the validation of .orb/.upf extensions * feat: update the validation of .orb/.upf extensions --------- Co-authored-by: Zanthoxylum <chenshengjun@localhost.localdomain>
* Support NPZ output for LCAO HSR matrices * Write NPZ outputs under OUT directory * Run NPZ integration tests only with CNPY --------- Co-authored-by: nscc-gz_pinchen_1 <nscc-gz_pinchen_1@users.noreply.github.com>
* Add FindKML.cmake and resolve FFTW3 issue * FindKML: Add compiler check * Detect fftwf only if ENABLE_FLOAT_FFTW
* checkpoint: skeleton gpu file before full implementation * feat: GPU-accelerated WT KEDF multi_kernel convolution Add GPU backend for KEDF_WT::multi_kernel() using cuFFT via PW_Basis _gpu interface. Key changes: - kedf_wt_gpu.cu: single CUDA kernel (kedf_wt_recip_multiply) for G-space element-wise kernel multiplication, plus multi_kernel_gpu() method that pipelines real2recip → kernel multiply → recip2real entirely on GPU. Persistent buffers allocated via memory_op. - kedf_wt.h: GPU method declarations and buffer members under #ifdef __CUDA guard (zero overhead when CUDA disabled). - kedf_wt.cpp: GPU dispatch at top of multi_kernel() — when pw_rho->device == "gpu", delegates to multi_kernel_gpu(). - source/CMakeLists.txt: add kedf_wt_gpu.cu to USE_CUDA block. Design follows existing ABACUS GPU patterns (memory_op for device memory, thrust::complex in kernels, CHECK_CUDA_SYNC for safety). * fix: move cufft.h include to file scope, fix memory_op type mismatch - kedf_wt.h: #include <cufft.h> was erroneously inside the class body (both in destructor and private section). This caused the cuFFT header extern "C" block to appear inside a C++ class definition, triggering "linkage specification is not allowed" and all cuFFT types undeclared. Moved the include to file scope, guarded by #ifdef __CUDA. - kedf_wt_gpu.cu: d_result_ is double* but resmem_zd_op/delmem_zd_op are typed std::complex<double>*. Changed to resmem_dd_op/delmem_dd_op (nrxx*2 doubles = nrxx complex doubles). * test: add GPU WT KEDF test case (31_OF_KE_WT_GPU) - Add test directory with INPUT (device=gpu), STRU, KPT, result.ref - Test identical to 09_OF_KE_WT but exercises GPU code path - Add CASES_GPU.txt for GPU test discovery - GPU results should match CPU reference within tolerance * refactor: move kedf_wt_gpu.cu to kernels/cuda/ for module consistency Per reviewer request (sunliang98): keep GPU kernel files organized under kernels/cuda/ subdirectory, consistent with other ABACUS modules. * fix: use full include path for kedf_wt.h in moved GPU kernel file After moving kedf_wt_gpu.cu to kernels/cuda/, the bare include #include "kedf_wt.h" no longer resolves since the header is now in the parent directory. Use full module path consistent with other CUDA kernel files (e.g., module_pwdft/kernels/cuda/*.cu). * perf: optimize WT KEDF GPU kernels — double2 + grid-stride + GPU rho^exponent Replace thrust::complex<double> with native double2 (cufftDoubleComplex) to eliminate AoS memory layout overhead (50% bandwidth waste from unused imag component). Add grid-stride loops for flexible occupancy. Move rho^exponent (std::pow) from CPU to GPU, eliminating one H→D transfer per SCF iteration. Kernel changes: - kedf_wt_rho_power (new): GPU-side pow() replaces CPU loop - kedf_wt_recip_multiply: double2 replaces thrust::complex, grid-stride - kedf_wt_real_to_complex: double2 + grid-stride - kedf_wt_complex_to_real_norm: double2 + grid-stride Benchmark (RTX 4060 Laptop, 96^3 grid): ~3.3x end-to-end speedup vs thrust::complex baseline. Kernel-only section: ~76% faster. See wt_kernel_opt/ standalone benchmark for full comparison. Thread coarsening (4x) was tested but showed regression on Ada Lovelace (SM 8.9) — fewer active warps reduced latency hiding for memory-bound kernels. Left for future architecture-specific tuning. * docs: update of_kinetic parameter to note WT GPU acceleration support * fix: pass nspin as parameter to avoid PARAM link error in CUDA unit multi_kernel_gpu in kedf_wt_gpu.cu referenced PARAM.inp.nspin, but the global PARAM symbol is not available during CUDA link in non-OFDFT test targets (dftu_core_test, dftu_operator_test). Pass nspin as a function parameter from the caller in kedf_wt.cpp. * docs: clarify GPU acceleration is enabled via device=gpu for WT KEDF * docs: remove incorrect GPU note from ext-wt KEDF ext-WT KEDF is a separate CPU-only implementation in kedf_extwt.cpp and is not modified by this PR; only WT KEDF has a GPU kernel. Drop the GPU acceleration note from the ext-wt line. --------- Co-authored-by: Liang Sun <50293369+sunliang98@users.noreply.github.com> Co-authored-by: Mohan Chen <mohanchen@pku.edu.cn>
* Normalize CRLF line endings to LF * Normalize whitespace in legacy text files * Update SIAB author reference * Add agent governance checks * Document agent governance review fixes * fix: tighten agent governance diff scope * remove useless plan file * fix: preserve LiRh integration input bytes * test: normalize LiRh integration input * test: report integration fatal deviations * test: disable force stress in LiRh symmetry case * test: refresh LiRh symmetry reference * fix: address copilot governance review * docs: refine agent governance * docs: strengthen governance PR follow-up --------- Co-authored-by: QuantumMisaka <QuantumMisaka@users.noreply.github.com>
* fix(tools): correct syntax error in RT-TDDFT projection tool Line 9 contained the invalid expression `fdir suffix + s_dir`, which made projection.py unparseable. Use `fdir + s_dir` to match the working example copy. Closes #7541 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(tools): repair empty else branch in generate_orbital_mixstru.sh `bash -n` failed on the empty `else` branch before `fi`. Add a `:` no-op so the example script is syntactically valid. Closes #7542 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(nao): reject one-past angular momentum index in TwoCenterTable index_map_ is allocated with final dimension length bra.lmax()+ket.lmax()+1, so valid indices are 0..dim_size(6)-1. The bounds check used `l <= dim_size(6)`, allowing a one-past read. Use `l < dim_size(6)` to match the neighboring dimension checks. Closes #7552 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(container): copy innermost dimension when slicing 3D tensors Each 3D row is placed at offset_out advancing by size[2], so the contiguous copy length must also be size[2]. The copy used size[1], corrupting non-cubic slices where size[1] != size[2]. Closes #7551 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(esolver): delete OFDFT KEDF_Manager with scalar delete kedf_manager_ is allocated with scalar `new KEDF_Manager()`, but the reinitialization path in before_all_runners() freed it with `delete[]`, which is undefined behavior. Use scalar `delete` to match the allocation. Closes #7548 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ci): use consistent SuperLU_DIST32_ROOT variable in path exports LD_LIBRARY_PATH, PKG_CONFIG_PATH and CPATH referenced the misspelled SUPERLU32_DIST_ROOT while CMAKE_PREFIX_PATH used SUPERLU_DIST32_ROOT (the name defined in Dockerfile.intel). Align the path exports to SUPERLU_DIST32_ROOT so SuperLU_DIST is not silently omitted. Closes #7572 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(io): read LATTICE_PARAMETER blocks consistently in STRU parsers The Multiwfn and pyabacus STRU parsers checked for a LATTICE_PARAMETER block but then read blocks['LATTICE_PARAMETERS'] with an extra S, and treated the list of lines as a string. Read blocks['LATTICE_PARAMETER'][0].split() to match the neighboring LATTICE_CONSTANT idiom, so STRU files using LATTICE_PARAMETER parse instead of raising KeyError. The identical fix for the ASE AbacusLite parser is intentionally left out of this PR and will be handled separately. Refs #7555 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* Normalize CRLF line endings to LF * Normalize whitespace in legacy text files * Update SIAB author reference * Add agent governance checks * Document agent governance review fixes * fix: tighten agent governance diff scope * remove useless plan file * fix: preserve LiRh integration input bytes * test: normalize LiRh integration input * test: report integration fatal deviations * test: disable force stress in LiRh symmetry case * test: refresh LiRh symmetry reference * fix: address copilot governance review * docs: refine agent governance * docs: strengthen governance PR follow-up * update agent governance check --------- Co-authored-by: QuantumMisaka <QuantumMisaka@users.noreply.github.com> Co-authored-by: QuantumMisaka <ff6757442@gmail.com> Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v4...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* CMake: Centralize target linkage in source/CMakeLists.txt
This refactors the CMake layout so that the top-level CMakeLists.txt is limited
to project configuration: options, feature resolution, platform/compiler setup,
and package discovery.
Target construction and linkage are centralized in source/CMakeLists.txt, which
now owns:
- the common linear-algebra dependency interface;
- optional external feature dependencies;
- the final external link closure;
- the ABACUS executable and its ordered internal target linkage;
- unit-test setup and registration of the top-level integration tests.
The final link closure is kept in one explicit location. Its order is part of
the build contract, especially for static or mixed static/shared builds:
1. internal ABACUS targets, from higher-level consumers to lower-level
providers;
2. optional external feature libraries;
3. numerical backends and their MPI, OpenMP, compiler-runtime, and system
dependencies.
Dependencies are therefore no longer accumulated through the legacy
`${math_libs}` path or scattered between the root CMakeLists.txt, test
directories, and setup modules. The old global OpenMP flag/link-option handling
is also removed in favour of imported targets and their usage requirements.
The top-level integration-test directory is registered only after the final
executable and its path are available. No integration-test cases are changed.
This is a structural cleanup only. It does not redesign dependency discovery or
change the current provider-selection logic for MKL, cuSOLVERMp, PEXSI, ELPA,
FFTW, ScaLAPACK, KML, or GPU dependencies, part of which need to be revised
seperately .
* Fix: Some testing target are exposed unconditionally
* Fix: Tests are built unconditionally
* Do not pass all targets to tests
* Fix: Link PEXSI properly
* Fix: Missing Torch libraries in DeePKS test
* Link Torch separately after the main dependency closure
* Add missing GTest dependency for DeePKS test support
Shared DeePKS test helpers include GoogleTest headers.
* Link DeePMD to the ESolver_DP unittest
* Resolve typo/mistake
* Attempt: Address PEXSI testing failure
* Move dependency discovery files to cmake/modules
* feat: enforce global dependency budget * docs: document global dependency budget * ci: surface governance warnings on PRs --------- Co-authored-by: QuantumMisaka <QuantumMisaka@users.noreply.github.com>
* fix: harden abacuslite ASE interface * fix: accept boolean abacuslite property keywords * fix: clarify abacuslite keyword comparison
* initial version of writing H and dH terms (except exx) * correct 1-electron terms: T, Vl, Vnl * fix pot register * Gint_drho * add EXX H&dH, dH (H-F term) of Veff Hartree, and refactor * add dm_container_to_Ds and exx nscf-from-dm workflow; minor refactor OperatorEXX * fix parallel segfaults and kinetic sign * XC H-F term (FD) * enable value-adding HContainers, total dH and atom-specified output; enable nspin=2 * dH test cases * exclude cal_exx_dHs with __EXX_DEV flag, waiting for LibRI PR merged * small fixes * change scf_in_dmr ref due to not renormalizing charge at init_chg==dm * fix conflict #7462 #7475 #7478 * Revert reference change by adding option dm_no_renormalize to init_chg This reverts commit ed14d9f. * fix pyabacus CI
* Test: Add <phi|r_a|p_{l,m}> snap_psibeta checks
* Style: Format cal_r_overlap_R
* INIT MGGA VELOCITY * Test * Revert "Test" This reverts commit bed1ff6. * Fix times 2 * Fix(pw): address meta-gga velocity review comments * Feature(pw): add meta-gga velocity conductivity switch * Docs(pw): clarify meta-gga velocity correction * Fix(pw): guard meta-gga velocity data * Style(pw): use ASCII in velocity comments
* Relax PR metadata governance severity * Simplify PR template metadata requirements * Restore concise PR checklist * Restore Reminder-style PR checklist
…lcao) (#7612) bcast_cell.cpp included source_lcao/module_ri/serialization_cereal.h only to call ModuleBase::bcast_data_cereal on three ABFS file-name lists, all of which are plain std::vector<std::string>. This created a reverse dependency from source_cell (L1) on source_lcao (L5). Replace the cereal-based broadcast with a small local bcast_string_vector helper built on Parallel_Common::bcast_int/bcast_string, mirroring how ucell.orbital_fn is already broadcast a few lines above. Behaviour is unchanged (broadcast from rank 0 to all ranks); the direct source_cell -> source_lcao include edge is removed. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
version.h is a leaf header (a single VERSION macro) with no dependencies, but it lived in source_main (the top-level entry layer). This forced source_io to include upward into source_main (edge source_io -> source_main), a reverse dependency that violates the intended module layering. Move it to source_base (L0 infrastructure), which every module may depend on, and update the 6 include sites. No behavior change; header-only, so no CMake changes are needed (resolved via the existing source/ include root). This cuts the source_io -> source_main reverse edge. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* add mpi in neighbor_search * fix neighbor search build without mpi * make neighbor search initialization cxx11 compatible * add distributed neighbor decomposition * add mpi in neighbor_search2 * Add neighbor list shared type definitions * fix compile bug * Optimize MPI ghost atom exchange * Resolve Makefile object conflict markers * Guard MPI domain decomposition in serial builds * Align neighbor search Makefile objects * Link neighbor MPI benchmark external deps * Guard benchmark external deps target * Always build neighbor domain decomposition source * Link neighbor MPI benchmark math deps explicitly * fix cmakelists --------- Co-authored-by: Fei Yang <2501213217@stu.pku.edu.cn>
* Fix .gitattributes * Apply auto-happened CRLF change
…larized calculations (#7589) * Fix docs for mixing_beta & mixing_beta_mag to suggest parameters for scf hard to converge. * Add mixing_beta tuning strategy as advices by QuantumMisaka into docs * Update input-main
…ache (#7935) * ci: route CPU tests to ACK/ECI runners with overlay2 and cross-pod ccache Updated GitHub Actions workflow to include push trigger for develop branch, improved caching for compiler, and consolidated test execution steps. * Refactor GitHub Actions workflow for tests Removed unused permissions and workflow_dispatch trigger. Updated various commands for better performance and consistency.
…nclude (#7920) * Refactor: move MatrixBlock to source_base, drop dead hamilt include MatrixBlock only records a matrix memory layout -- data pointer, local row/column counts and the BLACS descriptor -- so it carries no physics and does not belong to the Hamiltonian module. Move the definition to source_base/matrix_block.h as ModuleBase::MatrixBlock and leave a `using` alias in source_hamilt/matrixblock.h, so the ~30 existing hamilt::MatrixBlock spellings outside source_hsolver keep compiling unchanged. With that, three source_hsolver files stop reaching into source_hamilt altogether: - diago_bpcg.h included source_hamilt/hamilt.h without using a single symbol from it; DiagoBPCG::diag() has taken HPsiFunc/SPsiFunc closures for a while. - diago_cusolver.h only needed the matrix descriptor, not the whole Hamiltonian interface. psi.h is now included explicitly, it used to arrive through hamilt.h. - diago_scalapack.cpp likewise only needed the descriptor. The source_hsolver files that still need hamilt::Hamilt now spell the type ModuleBase::MatrixBlock and include source_base/matrix_block.h directly, so dropping their source_hamilt/hamilt.h include later is a pure signature change with no name churn. source_hsolver -> source_hamilt includes: 16 files / 17 lines -> 13 files / 13 lines. No behavior change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor(hsolver): drop two dead includes, mark matrixblock.h as a shim Follow-up review fixes on top of the MatrixBlock move: - parallel_k2d.h swapped one include for another, but the header itself never names MatrixBlock -- only parallel_k2d.cpp does. Drop it from the header and include source_base/matrix_block.h in the .cpp instead, so the header's dependency set actually shrinks rather than shifts. - diago_cusolver.h includes source_basis/module_ao/parallel_orbitals.h, but Parallel_Orbitals appears in neither the header nor the .cpp. Same class of dead include as the source_hamilt/hamilt.h one already removed from diago_bpcg.h. - source_hamilt/matrixblock.h is now a one-line alias kept only for the historical spelling. Say so with a TODO, so it has a stated end state instead of quietly becoming permanent. No behavior change; no type or signature is touched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NxDLsUHq81NAbsh2rpCwKB --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Revert "Refactor: move version.h from source_main to source_base (#7611)" This reverts commit 8e5d457. * Adapt relax_driver.cpp include to the restored source_main/version.h path PR #7752 added this include after #7611, so the revert alone would leave a dangling reference to source_base/version.h.
* Fix DeltaSpin gradient decay scaling * Remove redundant DeltaSpin band updates --------- Co-authored-by: TaoXia <taoxia@mail.ustc.edu.cn>
…o test access hacks it caused (#7940) * dftu_pw_test: use the case value directly instead of driving global PARAM The test parked its loop variable in the global Parameter singleton and read it straight back: PARAM.input.nspin = c.nspin; switch (PARAM.inp.nspin) { ... } const double diag_coeff = PARAM.inp.nspin == 4 ? 1.0 : 0.5; It wrote the private half (`PARAM.input`) and read the public one (`PARAM.inp`), so PARAM was serving as a scratch local -- and writing the private half is the whole reason this file carried `#define private public`. Nothing else reads it: the test's only production dependency, source_pw/module_pwdft/dftu_base_tools.cpp, contains zero PARAM references. `c.nspin` is already in scope, so use it directly. The macro and the parameter.h include it guarded are removed with it. No production code changes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * module_dftu: pass nspin and onsite_radius explicitly instead of reading PARAM The DFTU LCAO operator read two INPUT values straight out of the global Parameter singleton -- `PARAM.inp.nspin` in the constructor and `PARAM.inp.onsite_radius` in `initialize_HR()`. That is why dftu_lcao_test.cpp had to write `PARAM.input`, which is private, which is why it carried `#define private public`. Thread them through instead. `initialize_HR()` is private and called only from the constructor, so it simply takes `onsite_radius` as an argument; the constructor takes both and assigns the member. `dftu_nao_op.cpp` now has zero PARAM references and no longer includes parameter.h. All five call sites are updated explicitly -- no default arguments were added: - hamilt_lcao.cpp, gamma-only and multi-k branches; - force_stress_lcao.cpp, the `tmpu` force/stress instance; - the two cases in dftu_lcao_test.cpp, which now pass the values they already set locally. These first three are the composition roots for LCAO operators, the same role relax_nsync.cpp plays in #7921: the global reads concentrate there and the leaf operator stays clean. The test's expectations are unchanged. Both cases already set nspin explicitly (1 and 2) and onsite_radius in SetUp (1.0), so nothing was relying on the Input_para defaults -- the regression that cost #7921 five suites. The fixture member `onsite_radius_test = 1.0` carries the value SetUp used to write into PARAM. `#define private public` in dftu_lcao_test.cpp is removed with the reason for it. Nothing in this commit adds an `#undef private`, and no file whose macro survives is touched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: exclude empty atoms from DFT-D2 * fix: exclude empty atoms from DFT-D3 * fix: exclude empty atoms from DFT-D4 * test: cover empty atoms in DFT-D corrections
* remove kpar parameter in dft+U * refactor(dftu): rename orbital_corr to l_channel for clarity - Rename member variable `orbital_corr` to `l_channel` in Plus_U_Base - Rename member variable `orbital_corr_` to `l_channel_` in YukawaScreening and OccMatMixer - Rename accessor `get_orbital_corr(int)` to `get_l_channel(int)` - Rename accessor `get_orbital_corr_vec()` to `get_l_channel_vec()` - Rename predicate `has_correlated_orbital(int)` to `has_l_channel(int)` - Rename local variable `orbital_corr_tmp` to `l_channel_tmp` in onsite_proj_tools_force.cpp - Update all call sites across PW, LCAO, IO, and test modules The new name `l_channel` directly indicates the angular momentum quantum number `l` of the channel receiving the +U correction, avoiding confusion with "correlated orbital" (many-body physics concept) and the ambiguous abbreviation `corr`. * refactor(dftu): extract cal_occ_pw from Plus_U_Base to free function Move Plus_U_Base::cal_occ_pw to DFTU_BASE::cal_occ_pw in dftu_base_occ.cpp, with all dependencies passed explicitly as parameters. This decouples the PW occupation-matrix calculation from the Plus_U_Base class, making it directly unit-testable. Changes: - dftu_base_tools.h: declare DFTU_BASE::cal_occ_pw with 15 params - dftu_base_occ.cpp: implement as free function, remove member version - dftu_base.h: remove cal_occ_pw declaration, add public accessors (get_nspin, get_device, get_u_current_vec, get_pot_uterm_pw_index, get_pot_uterm_pw, energy_ref) needed by callers - setup_dftu_pw.cpp: call DFTU_BASE::cal_occ_pw via accessors - dftu_base.cpp: update comment to reflect free-function status * refactor(dftu): remove Plus_U_Base::nspin member variable Remove the mutable nspin member from Plus_U_Base to avoid hidden workflow state. The value is now passed explicitly: - init_base keeps its nspin parameter (needed for layout setup) - get_pot_uterm_pw_spin / get_size_pot_uterm_pw_spin take nspin as a function argument - Call sites pass PARAM.inp.nspin at the PW operator boundaries where signatures are fixed by the framework Also add missing parameter.h include to onsite_proj_force_stress.cpp. * refactor(dftu): rename cal_type to UForm enum with explicit formalism semantics Replace the opaque int cal_type (always 3, never written) in Plus_U_Base with a type-safe enum class UForm that explicitly names the DFT+U formalism and double-counting scheme: - lich_fll = 1: Lichtenstein rotationally invariant + FLL DC - lich_amf = 2: Lichtenstein rotationally invariant + AMF DC - dud_fll = 3: Dudarev simplified + FLL DC (default, implemented) Changes: - dftu_base.h: add UForm enum, replace member and getter - dftu_nao_pots.cpp: switch dispatch to enum cases - dftu_nao_pots.h: update doc comment - dftu_core_test.cpp: update comments The enum preserves the existing placeholder values for future implementation of the Lichtenstein formalism paths. Also rename the per-atom DFT+U effective-potential buffer from pot_uterm_pw/pot_uterm_pw_index to uterm_mat/uterm_mat_index and the related accessors (get_uterm_mat*, get_size_uterm_mat*). The old name suggested a basis-expanded potential; it is actually the small (2l+1)^2 projector coefficient matrix, analogous to the nonlocal-pseudopotential D_ij coefficients, and is basis-independent despite living in the PW/LCAO-shared base class. * docs: sync parameters.yaml with C++ source for l_channel Update docs/parameters.yaml to use l_channel instead of orbital_corr, matching the parameter name change in the C++ source (commit eabfabc). * refactor(io): pass Input_para explicitly to ctrl_output_fp Remove PARAM.inp dependency from ModuleIO::ctrl_output_fp by adding a const Input_para& parameter, and update the single call site in ESolver_FP::after_scf to forward *this->inp_. * refactor(dftu): rename occ_mat state accessors to ready/stale semantics Rename the DFT+U occupation-matrix state accessors to shorter, clearer names: - is_occ_mat_initialized() -> is_occmat_ready() - mark_occ_mat_initialized() -> set_occmat_ready() - mark_occ_mat_dirty() -> set_occmat_stale() - member occ_mat_initialized -> occmat_ready_ Also unify the base-class internal write paths to use set_occmat_ready() instead of direct member assignment, and update all call sites and comments across PW, LCAO, and DFPT modules. * refactor: split dftu_pw into dftu_pw_tools (pure functions) + dftu_pw (orchestration) - dftu_pw_tools.h/cpp: 7 pure functions in namespace pw, unit-testable - dftu_pw.h/cpp: cal_occ_pw + accumulate_occ_one_k in namespace DFTU_BASE - test_dftu_pw_tools.cpp: tests for pure functions, links only dftu_pw_tools.cpp - Update CMakeLists.txt accordingly * test: remove #define private public hack from test_dftu_pw_tools.cpp - Replace PARAM.inp.nspin with local variable c.nspin in EnergyWeightsAllNspin - Remove unnecessary parameter.h include * fix bug in Makefile * refactor(dftu): demote pot_onsite/get_onsite_pot params to Plus_U_Base The three DFTU_LCAO free functions in dftu_nao_pots only use base-class accessors (occmat, get_l_channel, get_form, yukawa, get_u_current), so their dftu parameter can take Plus_U_Base& instead of the LCAO-derived Plus_U&. Callers still pass Plus_U, which upconverts implicitly, so this compiles standalone. This is step A1 of decoupling PW DFT+U from the LCAO-derived type. * refactor(dftu): demote pot_uterm_* params to Plus_U_Base The four pot_uterm free functions only use the base-class is_occmat_ready() plus the already-demoted pot_onsite_* helpers, so their dftu parameter can take Plus_U_Base&. Callers pass Plus_U, which upconverts implicitly. Step A2 of decoupling PW DFT+U from Plus_U. * refactor(dftu): demote cal_energy_correction param to Plus_U_Base cal_energy_correction only uses base-class accessors (is_occmat_ready, occmat, get_l_channel, use_yukawa, yukawa, get_u_current, set_energy) plus the already-demoted get_onsite_pot, so its dftu parameter can take Plus_U_Base&. set_energy is mutable so the reference stays non-const. Step A3 of decoupling PW DFT+U from Plus_U. * refactor(dftu): demote cal_occ_mat_* params to Plus_U_Base cal_occ_mat, cal_occ_mat_k and cal_occ_mat_gamma only use base-class accessors (occmat, get_l_channel_vec, has_occ_mixer, occ_mixer, is_occmat_ready, set_occmat_ready), so their dftu parameter can take Plus_U_Base&. Step A4 of decoupling PW DFT+U from Plus_U. * refactor(dftu): demote force_stress to Plus_U_Base via orb_cutoff param force_stress only used Plus_U for get_orb_cutoff(); all other state goes through base-class accessors (pot_onsite_*, get_l_channel_vec, occmat). The per-type orbital cutoff is LCAO-specific (PW uses onsite_radius), so pass it explicitly as a new orb_cutoff parameter instead of moving it to the base class. The internal cal_force_k/cal_stress_k/cal_stress_gamma already take orb_cutoff as a parameter. Caller passes orb.cutoffs(). Step A5 (B-beta) of decoupling PW DFT+U from Plus_U. * refactor(dftu): demote spar_u cal_HR_dftu* params to Plus_U_Base cal_HR_dftu and cal_HR_dftu_soc only forward dftu to the already-demoted pot_uterm_HR_real/complex, so their parameter can take Plus_U_Base&. Step B1 of decoupling PW DFT+U from Plus_U. * refactor(dftu): hold Plus_U_Base* in DFTU/OperatorDFTU operators Both operator class templates now store and accept Plus_U_Base* instead of the LCAO-derived Plus_U*. OperatorDFTU only uses base-class interfaces (pot_uterm_*), so it demotes cleanly. DFTU still needs the LCAO-only get_dmr() for the density matrix, so the five get_dmr() call sites use a static_cast<Plus_U*> back to the derived type; the cast in cal_fs_nao_r is hoisted to a single local at function entry. This confines the base-to-derived cast to the operators' DM access, so upstream callers (HamiltLCAO, getForceStress) can pass base-class pointers. Step B (operators) of decoupling PW DFT+U from Plus_U. * refactor(dftu): demote HamiltLCAO p_dftu param to Plus_U_Base The HamiltLCAO constructor only forwards p_dftu to the DFTU/OperatorDFTU operator constructors, which now accept Plus_U_Base*. Demote the parameter and switch the forward declaration from Plus_U to Plus_U_Base. Callers pass &this->dftu (a Plus_U) which upcasts implicitly. * refactor(dftu): demote getForceStress dftu param to Plus_U_Base getForceStress only forwards dftu to the already-demoted force_stress and passes &dftu to the DFTU operator constructor (now Plus_U_Base*), so its parameter can take Plus_U_Base& with no cast needed. * refactor(dftu): demote output_mat_sparse p_dftu param to Plus_U_Base The p_dftu parameter is unused inside output_mat_sparse (only forwarded between the two overloads), so demote it to Plus_U_Base* across both declarations, both definitions, and the four explicit instantiations. * refactor(dftu): sink ctrl_scf_lcao dftu param to Plus_U_Base Change the ctrl_scf_lcao template and its three explicit specializations to take Plus_U_Base& instead of Plus_U&. The dftu argument is only forwarded (to output_mat_sparse, already on Plus_U_Base*), so no cast is needed. Switch the header include from dftu_nao.h to dftu_base.h. Verified: make -j 30 in build_max_para_test builds abacus_max_para. * refactor(dftu): sink LCAO_domain::set_pot dftu param to Plus_U_Base set_pot only needs the LCAO-specific init(ucell, ..., &orb), which lives on the derived Plus_U. Take Plus_U_Base& at the interface and cast to Plus_U& at the single init call site, matching the existing set_dmr pattern. The header now forward-declares Plus_U_Base instead of including dftu_nao.h; the .cpp includes dftu_nao.h for the cast. Verified: make -j 30 in build_max_para_test builds abacus_max_para. * refactor(dftu): make Plus_U_Base destructor virtual Plus_U adds members (orb_cutoff_, dm_in_dftu_*) that require proper destruction. The upcoming esolver change holds the object through a Plus_U_Base* and deletes it in the base-class destructor, which is undefined behavior without a virtual destructor. Make it virtual now as a standalone, separately-compilable step. Verified: make -j 30 in build_max_para_test builds abacus_max_para. * Refactor: change ESolver_KS dftu member to base-class pointer Replace the value member `Plus_U dftu` with a base-class pointer `Plus_U_Base* dftu_` in ESolver_KS, so that the PW/LCAO layering no longer requires the base class to know the LCAO-derived Plus_U type. - esolver_ks.h: member -> Plus_U_Base* dftu_ = nullptr; include dftu_base.h instead of dftu_nao.h. - esolver_ks.cpp: delete dftu_ in ~ESolver_KS (virtual dtor on Plus_U_Base makes this safe); update u_converged() call. - esolver_ks_pw.cpp: allocate `new Plus_U_Base()` in ctor (PW basis). - esolver_ks_lcao.cpp: allocate `new Plus_U()` in ctor (LCAO basis); include dftu_nao.h for the derived type. - Adapt all call sites to the pointer/reference forms expected by the already-base-classified helpers (Hamilt*, setup_pot, chgmixing, ctrl_scf_lcao, init/finish_dftu_lcao void* API, force/stress/dfpt). Derived classes (TDDFT, DoubleXC, DFPT_PW, lcao_others) inherit the already-constructed dftu_ via the ESolver_KS_PW / ESolver_KS_LCAO constructors, so each object is allocated exactly once. Build: make -j 30 in build_max_para_test, abacus_max_para links OK. * Build: compile module_dftu sources only under ENABLE_LCAO All sources in source_lcao/module_dftu implement the LCAO-specific Plus_U derived class and the DFTU_LCAO operators; the PW DFT+U implementation lives in source_pw/module_pwdft/dftu_base.* and is compiled unconditionally. Move the seven previously-unconditional sources (dftu_nao, dftu_nao_fs_k, dftu_nao_folding, dftu_nao_pots, dftu_nao_occ, dftu_nao_energy, dftu_hamilt) into the existing if(ENABLE_LCAO) block, following the module_rt precedent. Because the dftu OBJECT library now has no sources when LCAO is off, wrap add_library/add_coverage/test in if(ENABLE_LCAO) and move the `dftu` entry in the final link list from the unconditional block into the if(ENABLE_LCAO) block in source/CMakeLists.txt, mirroring how `tddft` is handled. Verification: - LCAO build (build_max_para_test): cmake reconfigure + make -j 30, abacus_max_para links OK. - PW-only build: cmake -DENABLE_LCAO=OFF -DBUILD_TESTING=OFF, make -j 30 abacus_pw_para links OK with no dftu target. * Refactor: drop now-redundant #ifdef __LCAO in module_dftu sources These seven .cpp files are now compiled only when ENABLE_LCAO is on (see the previous CMakeLists change), so the #ifdef __LCAO guards inside them are always true and can be removed. Only the preprocessor lines are deleted; all function bodies are unchanged, and the pre-existing #ifdef __MPI blocks (ScalapackConnector calls) are kept intact. The header files keep their #ifdef __LCAO guards: dftu_nao.h is still included by PW-compiled code (esolver_ks.h) and must let Plus_U degrade to an empty shell when LCAO is off. Verification: - LCAO build (build_max_para_test): make -j 30 abacus_max_para links OK. - PW-only build (ENABLE_LCAO=OFF): abacus_pw_para links OK. Note: code_quality_score flags dftu_nao_fs_k.cpp (6) and dftu_nao_occ.cpp (49) for pre-existing debt (file length, parameter count, cyclomatic complexity) untouched by this change. * Refactor: drop redundant #ifdef __LCAO in module_dftu headers These six headers are only included from LCAO-only translation units (verified: no source_pw/ references), and the whole dftu module is now compiled only under ENABLE_LCAO. The __LCAO guard inside them is dead in both build flavors, so remove it; only preprocessor lines are dropped, declarations are unchanged. dftu_nao.h keeps its guards because the PW-shared esolver_ks.h still includes it. Verified: abacus_max_para links (ENABLE_LCAO=ON) and abacus_pw_para links (ENABLE_LCAO=OFF). The unrelated MODULE_IO_numerical_basis_test fails to link under ENABLE_LCAO=OFF because its CMakeLists links numerical_atomic_orbitals/orb outside if(ENABLE_LCAO) -- a pre-existing issue independent of this change. * Build: guard MODULE_IO_numerical_basis_test behind ENABLE_LCAO This test links the LCAO-only libraries numerical_atomic_orbitals and orb and compiles source_lcao/center2orb.cpp, so it cannot build under ENABLE_LCAO=OFF. Wrap its AddTest in if(ENABLE_LCAO), matching the neighboring MODULE_IO_to_qo_test. Verified: ENABLE_LCAO=OFF full build completes (abacus_pw_para links) and the test still builds under ENABLE_LCAO=ON. * fix(dftu): restore INPUT parameter name orbital_corr and fix LCAO dftu_ null pointer The rename commit eabfabc changed the INPUT parameter from orbital_corr to l_channel, but test cases (scf_u_spin2, scf_u_spin2_old, scf_u_yukawa) still use the old name. Restore the INPUT parameter name to orbital_corr while keeping the internal C++ member variable as l_channel. Additionally, the refactor to base-class pointer (156a5d8) left ESolver_KS_LCAO without initializing dftu_ (unlike PW path which news Plus_U_Base), causing a segfault on DFT+U LCAO calculations. Add the missing allocation in the ESolver_KS_LCAO constructor. Verified: scf_u_spin2 passes with exit code 0, SCF converges, final energy -11033.13 eV. * fix(esolver): manage dftu_ via std::unique_ptr to prevent memory leak ESolver_KS::dftu_ was allocated with new in both ESolver_KS_PW and ESolver_KS_LCAO constructors but never deleted in ~ESolver_KS, contradicting the member comment and commit 156a5d8. Convert dftu_ to std::unique_ptr<Plus_U_Base> so ownership is explicit and the object is released automatically on destruction. Call sites that pass raw pointers to downstream functions use .get(); C++11 baseline requires reset(new ...) instead of std::make_unique. * fix(esolver): add .get() for unique_ptr dftu_ in init_dftu_lcao call Merge from develop reverted the raw pointer back to unique_ptr member in init_dftu_lcao call site, causing compile error on void* parameter. * fix --------- Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
`synchronize_memory()` and `cast_memory()` select a compile-time specialization from a pair of runtime `AbacusDevice_t` values, but joined their branch conditions with `||`. The first branch therefore matched whenever *either* side was the CPU, so a CPU->GPU or GPU->CPU transfer was served by the CPU-to-CPU specialization, i.e. a plain host `memcpy`/cast on a device pointer. GPU->GPU could likewise match an earlier mixed-device branch. The four combinations are mutually exclusive and must be tested with `&&`. The GPU branches are now compiled only when a GPU backend is enabled, which matches the guard on the `*_op` GPU specializations in memory_op.h, and an unsupported device combination fails loudly instead of falling through silently. Both wrappers are declared in memory_op.h but were defined in the .cpp with no explicit instantiation, so they could not be linked from another translation unit and had no call sites -- which is why the defect was latent. Add the instantiations (for `cast_memory`, only the type pairs that `cast_memory_op` provides for all four device combinations) and unit tests that pin the dispatch: CPU-to-CPU everywhere, and all four pairs under __UT_USE_CUDA/__UT_USE_ROCM. No documentation change: this is an internal dispatch fix with no INPUT, output or user-visible behaviour change. Fixes #7553 Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Added push trigger for develop branch and enhanced compiler cache management. Co-authored-by: Mohan Chen <mohanchen@pku.edu.cn>
* Fix undefined basis variable in interface workflow (#7571) The "Create mock data & patch script" step referenced `basis` inside the Python heredoc without defining it: the matrix key `basis` was never exported to the step environment, so the step failed with "NameError: name 'basis' is not defined" before any mock data was generated. Pass matrix.basis through the BASIS environment variable and read it in the heredoc, matching the existing SCRIPT/PREFIX pattern. * Add Upstream Repository section to AGENTS.md Document the upstream repo/issues/PR links and two workflow facts: upstream PRs are opened from personal fork branches, and workflow_dispatch-only workflows cannot be verified by PR CI. * Fix remaining blockers in interface workflow dryrun jobs The previous fix for the undefined basis variable was only the first blocker; the workflow still failed on all three matrix jobs. Correct the advance matrix entry to point at example_advanced.py, and emit the mock wannier90.nnkp k-point list inside begin/end kpoints markers so parse_nnkp can read it. Verified locally by simulating all three matrix jobs (basic/pw/ advanced): each prints the DRY RUN COMPLETE banner and passes the generated-file validation checks. This workflow is workflow_dispatch only, so a manual dispatch run is still required for CI verification. --------- Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn> Co-authored-by: Xiaoyang Zhang <tsfxwbbzxy@163.com>
…nian (#7948) DiagoScalapack, DiagoElpa, DiagoElpaNative, DiagoLapack, DiagoPexsi and DiagoCusolverMP each took a hamilt::Hamilt<T>* and used it for exactly one thing: `phm_in->matrix(h_mat, s_mat)` on the first line of diag(). Hoist that call into the caller and take the two matrix blocks instead, which is what DiagoCusolver::diag() and every diag_pool() already did. Parallel_K2D::distribute_hsk interleaves updateHk() and matrix() inside a collective loop, so it cannot simply hoist. It now takes an HskFunc callback and HSolverLCAO supplies the closure; the loop structure and the sequence of collective calls are unchanged. HSolverLCAO::hamiltSolvePsiK fetches H(k)/S(k) once instead of once per solver branch. HamiltLCAO::matrix() is a pure accessor (OperatorLCAO:: matrixHk only fills the blocks from pointers it already holds) and updateHk(ik) still runs before it, so the hoist is behaviour-neutral. The four LCAO test files defined a `HamiltTEST : public hamilt::Hamilt<T>` whose only job was handing back H and S; they are now plain matrix suppliers with no source_hamilt dependency. The matd/matcd typedefs existed only for the deleted temporaries and are removed. source_hsolver -> source_hamilt includes: 13 files / 13 lines -> 6 files / 6 lines. No behaviour change. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…in four tests (#7949) `magnetism_test`, `atom_pseudo_test`, `pseudo_nc_test` and `read_pp_test` each switched off access control for their whole translation unit in order to call a handful of private *methods* -- the format readers and helpers the tests exist to exercise. No private data member is involved, and none of these files touches PARAM, so the macro had exactly one cause. Replace it with an explicit `friend class <fixture>;` on the class under test, following the existing precedent in source_pw/module_pwdft/dftu_base.h (`friend class DFTUTest;`) and parameter.h (`friend class TestParameters;`). This is the fix AGENTS.md rule 10 names, and it narrows a whole-TU override -- which also reinterprets access control inside every standard library header the TU pulls in -- down to one named, reviewable grant per fixture. Friendship is not inherited, and a TEST_F body lives in a class derived from the fixture, so each fixture gains thin forwarding wrappers and the TEST_F bodies call those. dftu_lcao_test.cpp already documents and uses this arrangement. - Magnetism: friend MagnetismTest, 1 wrapper (judge_parallel), 2 call sites. - Pseudopot_upf: friend AtomPseudoTest / NCPPTest / ReadPPTest; 1 + 3 + 8 wrappers for read_pseudo_upf{,201,_vwr,_blps}, set_pseudo_type, setqfnew, trim, trimend, complete_default_{h,atom}; 36 call sites in total. Public members and public methods the tests already used -- Pseudopot_upf's complete_default, init_pseudo_reader, average_p, set_upf_q, set_empty_element, print_pseudo_upf and its public data, and Magnetism's tot_mag/abs_mag/start_mag -- are untouched and still accessed directly. No test expectation changed: every wrapper forwards its arguments unmodified and returns what the private method returns. Macro occurrences in these four files go 4 -> 0; no `#undef private` is introduced anywhere, and no file whose macro survives is touched. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…no production change (#7952) `orb_nonlocal_test.cpp` and `orb_read_test.cpp` switched off access control for their whole translation unit to reach members of `Numerical_Nonlocal` and `LCAO_Orbitals` that mostly already have public getters. Neither file touches PARAM, and neither needs anything added to a production header: the macro is removed by using the accessors that exist, plus one fixture built through the public API instead of by assignment. Three distinct cases, and the second is the interesting one: 1. The member is used as a plain value. Read it through its getter -- `lcao_.kmesh` -> `lcao_.get_kmesh()` (4 sites), and the five assertions in `SetTypeInfo` now read `nn.getLabel()`, `getType()`, `getLmax()`, `get_rcut_max()`, `get_nproj()`. Those already compared against the fixture's inputs, so they stay real checks. 2. The assertion *is* `EXPECT_EQ(obj.get_x(), obj.x)`. Substituting the getter would turn it into `EXPECT_EQ(get_x(), get_x())` -- it cannot fail, and the test would be silently gutted. These are re-anchored to the value the object was given instead, which is what `orb_nonlocal_test` already did on one line (`EXPECT_EQ(nn.get_rcut_max(), rcut_max_)`); the rest now match it. In `LCAO_Orbitals::Getters`, seven of the twelve assertions covered private members. `ntype` and `lmax` are passed straight into `Read_Orbitals`, so they anchor to `ntype_` / `lmax_`. The other four are derived, and the production formula is deliberately *not* restated in the test -- a test that recomputes what it is checking passes even when the formula is wrong. They are asserted as the concrete values this fixture implies, each with its provenance: `kmesh` 1113 = int(sqrt(123)/0.01) + 4, `nchimax` 2 (H is 2s1p, O is 2s2p1d), `lmax_d`/`nchimax_d` 2 from jle.orb, `rcutmax_Phi` 8 au (H 8 au, O 7 au). Measured against the built test to confirm, and kmesh cross-checked by hand against Read_Orbitals. 3. The test *wrote* a private member to build a fixture: `nnl[i].rcut = 1.0` in `NumericalNonlocalTest::SetUp`. `Numerical_Nonlocal_Lm` derives rcut from the last point of its radial mesh, so each projector is now built through the public `set_NL_proj()` with a minimal three-point mesh whose endpoint is the wanted rcut. That removes the write and additionally exercises `set_NL_proj`, which no assertion in this file reached before. `ecutwfc`, `dk`, `dR`, `Rmax` and `dr_uniform` are public members of `LCAO_Orbitals` and never needed the macro; the four that compare against a fixture input are anchored to it for consistency, and `dr_uniform` is left alone. Macro occurrences in these two files go 2 -> 0. No `#undef private` is added, and no file whose macro survives is touched. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…etters plus one friend (#7953) `orb_atomic_lm_test.cpp` reached into 17 private members of `Numerical_Orbital_Lm` and called four of its private methods. Sixteen of those members already have public accessors, so the macro comes off mostly by using them: 138 sites now read through `get_psi()`, `getNr()`, `getRcut()` and the rest. No PARAM is involved. Two things needed more than a substitution: - `psir` was the only array in the class without the vector accessor its siblings all have. `Numerical_Orbital_Lm` exposes a systematic trio per array -- `getX()` returning a pointer, `getX(i)` returning an element, `get_x()` returning the vector -- and psir had only the first two, so `.psir.size()` and `.psir.empty()` had no public route. Added the missing `get_psir()`, completing the pattern rather than inventing an accessor for the test. - `cal_kradial`, `cal_kradial_sbpool`, `cal_rradial_sbpool` and `plot` are private and are what four of the tests exist to exercise. These get `friend class NumericalOrbitalLmTest;`, next to the `friend class Numerical_Orbital;` the class already carries, plus four forwarding wrappers on the fixture -- a TEST_F body lives in a derived class and does not inherit friendship. The substitution is uniform because the accessors return the member itself: `get_psi()` yields `const std::vector<double>&`, so `.psi[i]`, `.psi.size()`, `.psi.empty()` and bare `.psi` all keep working through it, and the scalar getters return const references. Every site was rewritten mechanically and then checked: no private member of the class is named in any TEST_F body any more. No test expectation changed. Macro occurrences in this file go 1 -> 0; no `#undef private` is added and no other file is touched. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(hsolver): honor Hermitian upper triangle in genelpa * fix(deltaspin): align lambda operator with Pauli moments * Fix second generalized ELPA transform * Fix generalized ELPA fallback transform * Update HSE symmetry regression reference --------- Co-authored-by: TaoXia <taoxia@mail.ustc.edu.cn> Co-authored-by: Mohan Chen <mohanchen@pku.edu.cn>
* refactor: LR I/O functionality * Add test case 58_KP_LR_BSE fix `out_struc` to handle `lat0` correctly * feat(BSE): add bse_q_approx_mode=3 to truncate W matrix elements by |k1-k2| Keep only (k1,k2) pairs with minimum-image |q| <= bse_q_approx_threshold in the q2kpair map; dropped pairs' W matrix elements are never computed and are strictly zero. transform_k_2dlocal tolerates missing (k1,k2) entries in the MPI counting/send loops and the non-MPI gather. q keys are aggregated in an eps-fuzzy local map (1e-6) before moving into LR_lri.q2kpair (exact std::less), avoiding ~1-ulp float key fragmentation that inflated the q-loop ~40x.
* refactor(relax): extract socket driver helpers into socket_driver_utils Move constants, structs, and helper functions from socket_driver.cpp's anonymous namespace into a dedicated socket_driver_utils module. This reduces socket_driver.cpp from 876 to 507 lines and improves its code quality score from 47 to 61. Update CMakeLists.txt and test/CMakeLists.txt to include the new source file in both the library and the socket_driver_test target. * refactor(relax): split socket_driver main loop into per-message handlers Extract the five i-PI message branches (STATUS/INIT/POSDATA/GETFORCE/EXIT) from socket_driver.cpp into a dedicated socket_driver_handlers module. The main loop now only dispatches headers, reducing the socket_driver function's cyclomatic complexity from 50 to about 10 and raising its code quality score from 61 to 100. Introduce DriverContext to bundle shared mutable state (ESolver, UnitCell, Input_para, driver state, published frame, etc.) so each handler receives at most three parameters. Update CMakeLists.txt and test/CMakeLists.txt to include the new source file. * refactor(relax): extract socket frame math helpers into socket_frame_utils Move Jacobi SVD and matrix utility functions from socket_frame.cpp's anonymous namespace into a dedicated socket_frame_utils module. This reduces socket_frame.cpp from 426 to 278 lines, making the remaining validation logic easier to decompose in follow-up changes. Update CMakeLists.txt and test/CMakeLists.txt to include the new source file in the library and both socket test targets. * refactor(relax): decompose validate_ipi_cell into focused validation stages Split the validate_ipi_cell function into nine private helpers in an anonymous namespace: entry validation, tolerance validation, scale computation, determinant computation, SVD, condition number, inverse computation, and consistency check. The public function now reads as a linear pipeline, reducing its cyclomatic complexity from 27 to about 5 and raising socket_frame.cpp's code quality score from 72 to 89. Also change MATRIX_DIMENSION from an extern const to a constexpr in socket_frame_utils.h so it can be used as an array bound in the helper signatures. * refactor(relax): split make_ipi_virial into validation and computation helpers Decompose make_ipi_virial into three private helpers in an anonymous namespace: validate_virial_inputs, check_stress_symmetry, and compute_symmetric_virial. The public function now reads as a short pipeline, reducing its cyclomatic complexity from 16 to about 4 and raising socket_frame.cpp's code quality score from 89 to 95. * style(relax): rename socket constants to kCamelCase and fix long lines Rename all UPPER_CASE constants in the socket driver, frame, and IPI modules to kCamelCase per project style. Also split two long WARNING_QUIT/WARNING message strings in socket_driver_handlers.cpp. The remaining uppercase_constant deductions are from system macros (e.g., MPI_COMM_WORLD) and include guards in headers, which are not addressed by this change. * refactor(relax): use Parallel_Reduce and Parallel_Common wrappers in socket driver Replace direct MPI_Allreduce calls with Parallel_Reduce::reduce_min and reduce_max, and replace MPI_Bcast with Parallel_Common::bcast_int for int32 values. Add explicit instantiation of reduce_max<int> in parallel_reduce.cpp. Note: socket_driver_test currently fails in this build because the test binary links against an MPI-enabled base library but does not initialize MPI; this is a pre-existing test environment limitation. * fix(build): add new socket source files to Makefile.Objects Add socket_frame_utils.o, socket_driver_utils.o, and socket_driver_handlers.o to OBJS_RELAXATION so the Makefile build can link the new translation units introduced by the socket refactoring. * test(relax): run socket_driver_test under MPI and remove redundant MPI guards - Add custom main with MPI_Init/MPI_Finalize to socket_driver_test.cpp - Link MPI::MPI_CXX and KEEP_FEATURE_DEFINITIONS __MPI in test CMakeLists - Add Atom::bcast_atom/bcast_atom2 stubs in for_test.h to satisfy bcast_cell.cpp - Remove #ifdef __MPI guards from socket_driver_utils.cpp since test now initializes MPI and production binary always has MPI available * refactor(relax): KISS rename socket files, namespaces, and functions File renames: - socket_driver_utils → socket_utils - socket_driver_handlers → socket_handlers Namespace renames: - SocketDriverUtils → SocketUtils - SocketDriverHandlers → SocketHandlers - SocketFrameUtils → FrameUtils Function renames (remove redundant socket_ prefix): - bcast_socket_int → bcast_int - bcast_socket_int32 → bcast_int32 - bcast_socket_chars → bcast_chars - bcast_socket_string → bcast_string - socket_address → address - quit_if_root_io_failed → quit_if_root_failed * refactor(relax): rename socket test files to test_ prefix - socket_ipi_test.cpp → test_socket_ipi.cpp - socket_frame_test.cpp → test_socket_frame.cpp - socket_driver_test.cpp → test_socket_driver.cpp Follows AGENTS.md rule 11: new unit test files named test_<module_name>.cpp. * fix(socket_utils): guard direct MPI calls with #ifdef __MPI MPI_Comm_rank and MPI_Abort were called unconditionally in fail_during_collective_stage and is_root, breaking builds without __MPI defined. Wrap these calls (and the mpi.h include) with the standard __MPI guards. Non-MPI fallback behavior: - fail_during_collective_stage prints rank=-1 and aborts - is_root returns true (single process is always root) * fix(socket_utils): restore serial throw in fail_during_collective_stage Commit 3fea6ec dropped the #else throw branch as a redundant MPI guard, and abd84fe rebuilt the guard with std::abort() as the unconditional fallback. That regressed serial ENABLE_MPI=OFF builds: an ESolver failure now SIGABRTs instead of reaching the catch in Socket_Driver::socket_driver that reports a clean WARNING_QUIT. Move the diagnostic print, MPI_Abort, and abort back inside #ifdef __MPI and restore throw std::runtime_error(message) for serial builds, matching the original behavior from 4c95474. Serial builds remain user-facing and CI cannot catch this because the socket tests are guarded by if(ENABLE_MPI). * fix(socket_handlers): keep POSDATA state check on the shared quit path handle_posdata performed the READY-state check with a root-only quit_if_root_failed call before read_posdata, while non-root ranks fell through to read_posdata's own quit_if_root_failed. The two paths matched only because each issued exactly one bcast_int plus one bcast_string; any collective added ahead of read_posdata's quit would deadlock non-root ranks after the root quit. Pass DriverState into read_posdata and set io_failed there so all ranks pass through the single quit_if_root_failed sequence, matching the other socket handlers. --------- Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn> Co-authored-by: Xiaoyang Zhang <tsfxwbbzxy@163.com>
* source_estate/module_dm: track DMR validity with _dmr_ready flag
DensityMatrix gains a read-only is_dmr_ready() query. init_DMR() resets
the flag for all four overloads; cal_DMR()/cal_DMR_td() set it once DMR
has been computed from DMK, so freshly allocated, zeroed or file-read
DMR is reported as not ready until the first wavefunction-derived
calculation. This lets consumers (DFT+U in LCAO, next commit) replace
externally cached density-matrix pointers by reading the state of the
solver-owned DensityMatrix directly.
* source_lcao/module_dftu: read DFT+U DMR from solver-owned DensityMatrix
The DFTU LCAO operator (dft_plus_u==1) now holds a const pointer to the
ESolver-owned elecstate::DensityMatrix and reads the real-space density
matrix through it, instead of Plus_U caching two separately-set density
matrix pointers.
- DFTU<OperatorLCAO>: accept const DensityMatrix<TK,double>* in the
constructor and expose get_dmr(ispin), which returns nullptr until DMR
is ready (DensityMatrix::is_dmr_ready) so first-iteration timing
semantics are preserved without set_dmr bookkeeping.
- contributeHR and dftu_nao_fs_r obtain DMR through the operator.
- Remove Plus_U::get_dmr/set_dmr and the dm_in_dftu_d/dm_in_dftu_cd
cache pointers.
- init_dftu_lcao is de-templated and loses istep/iter/DM arguments;
the only call site is updated. HamiltLCAO (gamma and multi-k) and the
force/stress temporary operator pass DM_in / dmat.dm through.
- write_hs_r.h no longer relies on dftu_nao.h for the hamilt::HContainer
forward declaration; it declares it itself.
- dftu_lcao_test constructs a real solver-style DensityMatrix, fills DMK
and computes DMR instead of stubbing Plus_U::get_dmr; its CMake target
compiles the module_dm sources directly.
* refactor(dftu): remove redundant __LCAO guards from dftu_nao.h
The dftu module (source_lcao/module_dftu) is compiled only when
ENABLE_LCAO is on, so __LCAO is always defined when dftu_nao.h is
included by its real consumers. Drop the three #ifdef __LCAO guards
that wrapped the LCAO_Orbitals forward declaration, the init() orb
parameter, and the ptr_orb_/orb_cutoff_ members plus accessors.
The only non-LCAO file that included dftu_nao.h was chgmixing.cpp,
which uses only Plus_U_Base (already available via chgmixing.h ->
dftu_base.h). Remove that redundant include so the header is no
longer pulled into the non-LCAO build path.
* refactor(dftu): pass LCAO_Orbitals explicitly to init_dftu_lcao
Plus_U::ptr_orb_ and orb_cutoff_ were dead state: ptr_orb_ was only
read inside init_dftu_lcao via get_ptr_orb(), and orb_cutoff_ was
never read outside the class. Pass the LCAO_Orbitals pointer through
an explicit init_dftu_lcao parameter instead, drop the two members
and their accessors, and remove the now-unused orb parameter from
Plus_U::init (sole caller in lcao_set updated accordingly).
* refactor(dftu): remove empty Plus_U derived class, use Plus_U_Base everywhere
Plus_U had no data members and its init() only validated the paraV
square invariant before delegating to Plus_U_Base::init_base, while all
LCAO logic already lived in DFTU_LCAO free functions taking Plus_U_Base&.
Delete dftu_nao.{h,cpp}; move the invariant check into
LCAO_domain::set_pot, drop the unused ks_solver/nlocal init arguments,
and switch all 12 includers and the LCAO esolver to Plus_U_Base. The
destructor loses virtual since no derived class remains. No behavior
change; global dependency budget net delta 0.
* refactor(dftu): drop redundant __OPDFTUTEMPLATE fragment guard
The primary template is only defined in this header, which is already
guarded by OPDFTULCAO_H, so the inner guard can never trigger twice.
* fix(lcao): include parallel_orbitals.h directly in spar_u.h
spar_u.h declares cal_HR_dftu and cal_HR_dftu_soc with
Parallel_Orbitals references but only includes dftu_base.h, relying on
a transitive include that no longer reaches it after the recent header
cleanup. The missing type breaks the hamilt_lcao build with
"'Parallel_Orbitals' does not name a type". Include the owning header
directly so the header is self-contained.
* refactor(dftu): mechanical cleanup of dftu_nao_fs_k
- replace raw new[]/delete[] pot_onsite buffers in both the gamma and
multik loops with std::vector, removing leak risk on exception and
giving the buffers deterministic zero initialization
- remove the unused one_int constant in the gamma branch
- remove redundant trailing return statements from void functions
- rename the include guard from DFTU_FORCE_H to DFTU_NAO_FS_K_H to
match the file name
No behavior change.
* refactor(dftu): pass ks_solver explicitly to DFTU_LCAO::force_stress
force_stress read PARAM.inp.ks_solver four times directly (the
column-major layout guard and the cal_stress_gamma/cal_force_k/
cal_stress_k calls), adding a cross-layer dependency on the global
INPUT from module_dftu. Take ks_solver as an explicit argument and
supply it at the sole call site in force_stress_lcao.cpp, then drop
the parameter.h include from dftu_nao_fs_k.cpp. The global reference
now stays in the scheduling layer, which already uses PARAM.
* refactor(dftu): introduce DftuFsEnv and slim down force/stress kernels
Add a small immutable DftuFsEnv class that bundles the objects constant
for one DFT+U force/stress calculation (dftu state, unit cell, grid,
parallel orbitals, folded arrays, orbital cutoffs, ks_solver, npol) with
non-null construction and const-reference accessors.
Rebuild the five entry points around it:
- cal_force_k/cal_stress_k: 14/12 -> 5 parameters
- cal_force_gamma/cal_stress_gamma: 11/13 -> 3 parameters; the gamma
kernels now read DSloc_x/y/z and DH_r through env.fsr() instead of
seven raw pointer arguments
- force_stress: 16 -> 9 parameters; nlocal is derived from pv inside
each kernel, and l_channel/iatlnmipol2iwt are fetched from dftu inside
the kernels that need them, removing the fivefold-nested vector type
from every signature
- rename local NL/LC/N to nl/lc/nchi and drop dead constants in the
gamma kernels while touching those lines
The sole call site constructs the env and passes it through. No
computation changes.
* refactor(dftu): extract shared accumulation primitives in dftu_nao_fs_k
Step 4 of the dftu_nao_fs_k refactor. No behavior change.
- Extract three anonymous-namespace templated helpers shared by the
gamma and multi-k kernels:
- accumulate_diag_force: diagonal (iwt1 == iwt2) force term
- accumulate_diag_stress: diagonal stress term with explicit factor
- accumulate_onsite_force: DFT+U correlated-channel onsite term;
takes the l-channel and iatlnmipol2iwt tables itself
- collapse the it/ia/l/n/m/ipol "fake loop" in the onsite accumulation
to it/ia/m/ipol: l is fixed to the atom's correlated channel and n
to 0; guards for lc == -1, out-of-range lc and l_nchi < 1 preserved
- replace the dim-pointer if/else chain in cal_force_gamma with a
dsloc[3] pointer table; cal_stress_gamma keeps its three separate
pointers because fold_dSR_gamma takes them individually
- drop the now-unused l_channel / iatlnmipol2iwt local aliases in
cal_force_k and cal_force_gamma
GEMM transa/transb, alpha values, accumulation order, the -0.5 stress
prefactor, the 2.0 diagonal-stress factor and the MPI guards are all
preserved.
Verification: make -C build -j 30 (clean). Numerical regression
against gamma-only and multi-k DFT+U force/stress cases is recommended
before merge.
* refactor(dftu): split force_stress into validate/loop/finalize helpers
Step 5 of the dftu_nao_fs_k refactor. No behavior change.
- Extract the long force_stress body into four file-local functions in
an anonymous namespace:
- validate_fs_inputs: folded-matrix null checks and column-major
ks_solver layout check (the two gamma/multik branches now share a
single missing_dsloc flag each)
- run_gamma_loop / run_k_loop: rho * V_onsite GEMM plus per-k force
and stress accumulation
- finalize_stress: MPI reduction, upper-triangle mirroring and
lat0/omega scaling
- force_stress is now a short orchestrator (validate, zero, dispatch,
reduce/finalize)
- Move the four cal_* kernels out of the public header: they are only
called inside this translation unit. Drop the now-unneeded
vector3.h include from the header and include it directly in the cpp.
All GEMM arguments, accumulation order, guards and error messages are
preserved.
Verification: make -C build -j 30 (clean). Numerical regression
against gamma-only and multi-k DFT+U force/stress cases is recommended
before merge.
* refactor(dftu): reduce complexity in fs validation and onsite helper
Follow-up to the force_stress split. No behavior change.
- Extract has_valid_correlated_channel out of accumulate_onsite_force
so the channel-validity predicate is named and testable and the
accumulation loop stays below the complexity threshold
- Extract check_folded_arrays out of validate_fs_inputs: the gamma and
multik buffer checks now share one implementation, with the pointer
triples and diagnostic messages selected per path; all four original
messages are preserved verbatim
code_quality_score.py for dftu_nao_fs_k.cpp: 80 -> 89 (was 6 before
the refactor series); dftu_nao_fs_k.h: 94. Remaining deductions are
file length (ScaLAPACK GEMM argument lists dominate the line count),
the module-wide DFTU_LCAO namespace naming convention, and the public
force_stress parameter count.
Verification: make -C build -j 30 (clean).
* refactor(dftu): forward-declare ForceStressArrays in dftu_nao_fs_k.h
DftuFsEnv only holds a ForceStressArrays reference/pointer, so the
header does not need its complete definition. Replace the include with
a forward declaration and include force_stress_arrays.h directly in
the cpp, which dereferences the arrays. No behavior change.
Verification: make -C build -j 30 (clean full build).
* refactor(dftu): migrate _r free functions to DFTU_LCAO namespace
Move cal_fs_nao_r / cal_for_IJR_nao_r / cal_str_IJR_nao_r out of
namespace hamilt into namespace DFTU_LCAO to match the module's
free-function convention. The forward declarations of OperatorLCAO
and DFTU stay in hamilt; call sites use the hamilt:: qualifier for
the DFTU<OperatorLCAO<TK, TR>>* parameter type. The only external
caller, DFTU<OperatorLCAO>::cal_force_stress in dftu_nao_op.cpp, now
calls DFTU_LCAO::cal_fs_nao_r.
* refactor(dftu): extract occ channel helpers and drop unused iter param
Step 1 of dftu_nao_occ.cpp refactor: lift the per-(iat,l,n,spin)
m0/ipol0/m1/ipol1 quadruple loop in cal_occ_mat_k and cal_occ_mat_gamma
into accumulate_occ_channel_k/gamma free functions (7 params each, under
the too-many-parameters threshold). The gamma path now uses the combined
(m0_all, m1_all) channel index consistently with the multi-k path; this
is behavior-equivalent for npol=1 (nspin=1/2, the only cases that reach
the gamma path; nspin=4 hits the switch default and exits).
Drop the unused `iter` parameter from cal_occ_mat, cal_occ_mat_k,
cal_occ_mat_gamma, and the finish_dftu_lcao entry point (declaration,
definition, both explicit instantiations, and the esolver call site).
* refactor(dftu): extract k-path reduce+symmetrize into helper
Step 2 of dftu_nao_occ.cpp refactor: lift the second (it,ia,l,n) loop of
cal_occ_mat_k -- the per-channel MPI_Allreduce plus the nspin-dependent
Hermitian symmetrization -- into reduce_and_symmetrize_occ_k. The helper
reads nspin and npol from occmat so callers do not thread them through;
the main function drops its now-unused npol local. Behavior unchanged:
the Allreduce counts, switch cases, and transpose/scale operations are
moved verbatim.
* refactor(dftu): hoist per-ik and per-(it,ia,l,n) loops into helpers
Step 3 of dftu_nao_occ.cpp refactor: extract the remaining (it,ia,l,n=0)
mesh walks into two thin orchestration helpers.
- accumulate_occ_k_for_ik: walks the atom mesh for one k-point and
delegates each qualifying channel to accumulate_occ_channel_k.
- process_occ_channel_gamma: walks the atom mesh for one spin in the
gamma-only path and bundles accumulate + Allreduce + symmetrize per
channel.
Both main functions now read as setup + gemm loop + one helper call +
mixing; cyclomatic complexity drops to ~4 (cal_occ_mat_k) and ~3
(cal_occ_mat_gamma), under the 10 threshold. The gamma main function
drops its now-unused npol local. Behavior unchanged: loop bodies,
guards, Allreduce counts, and symmetrize cases are moved verbatim.
* refactor(dftu): use Parallel_Reduce wrapper, pass ks_solver explicitly, guard entry
Step 4 of dftu_nao_occ.cpp refactor:
- Replace the four direct MPI_Allreduce(... MPI_DOUBLE, MPI_SUM,
MPI_COMM_WORLD) calls in reduce_and_symmetrize_occ_k and
process_occ_channel_gamma with Parallel_Reduce::reduce_all, using
in-place semantics (the temp copy is no longer needed). This removes
the uppercase MPI_* constants and complies with the ABACUS rule that
forbids direct MPI routines.
- Drop the PARAM.inp.ks_solver read inside cal_occ_mat_k; thread
ks_solver through the cal_occ_mat template and cal_occ_mat_k as an
explicit parameter, sourced from setup_dftu_lcao.cpp. The file no
longer reads PARAM, eliminating its global_dependency finding.
- Add pv/p_ham nullptr guards at the entry of both cal_occ_mat_k and
cal_occ_mat_gamma.
Score: 49 -> 84.
* refactor(dftu): split cal_energy_correction into per-channel helpers
cal_energy_correction had cyclomatic complexity 28 from inlining the
collinear/noncollinear U-term accumulation and the double-counting
grid in one body, and read PARAM.inp.nspin directly.
Extract three helpers:
- calc_energy_u_collinear: per-(T,iat,l,n) U-term for nspin=1/2.
- calc_energy_u_noncollinear: same for nspin=4.
- calc_energy_dc_block: per-channel onsite_pot*occ double-counting sum.
cal_energy_correction now reads as a thin (T,I,l,n) walk calling the
helpers, with nspin/npol threaded in from setup_dftu_lcao.cpp, removing
the file's PARAM read. CC drops 28 -> 11; score 79 -> 98. Build clean.
* refactor(dftu): bundle folding params into FoldingCtx struct
fold_dSR_gamma (13 params) and folding_matrix_k (12 params) each
exceeded the 7-parameter threshold. Introduce a FoldingCtx struct that
bundles the six read-only shared parameters (npol, ks_solver,
orb_cutoff, ucell, pv, gd); the two functions now take the struct plus
only their per-call-specific arguments, dropping to 8 and 7 params
respectively. The three call sites in dftu_nao_fs_k.cpp build the
struct once at the top of each caller. Build clean. folding.cpp 82->92.
* refactor(dftu): split contributeHR and extract kernel functions
dftu_nao_op.cpp was 720 lines with contributeHR CC=20.
1. Split contributeHR into three private member functions:
- compute_occ_from_dmr: BRANCH 1 (DMR-based occ calculation)
- load_occ_from_file: BRANCH 2 (pre-read occ_mat loading)
- accumulate_HR_for_iat0: Step 5 (HR pair accumulation)
contributeHR now reads as a thin (T,I,l,n) walk calling the helpers;
CC drops 20 -> ~4.
2. Extract cal_HR_IJR, cal_occ, transfer_pot_onsite (both generic and
noncollinear specialization), and cal_pot_onsite into a new
dftu_nao_op_kernel.cpp translation unit. op.cpp drops from 720 to
~440 lines, under the 500-line limit. The new file carries its own
explicit template instantiations matching op.cpp. The test CMakeLists
is updated to compile the new source alongside the existing ones.
Scores: op.cpp 72->95, kernel 97. Build clean.
* refactor(dftu): drop dftu_op param from r-space force/stress pair kernels
cal_for_IJR_nao_r and cal_str_IJR_nao_r only used dftu_op to read
ucell.get_npol(); derive npol locally as (nspin == 4 ? 2 : 1), which
matches UnitCell::npol for all valid nspin values. The TK/TR template
parameters served only that argument, so both become plain free
functions with their explicit instantiations removed. Add __DEBUG
asserts for nspin and (force kernel) non-null output pointers, and
drop the now-unneeded dftu_nao_op.h include and forward declarations.
* Refactor: extract DFTU atom-pair HR/occ kernels as free functions
Move DFTU<OperatorLCAO<TK,TR>>::cal_HR_IJR and cal_occ out of the
class template into namespace DFTU_LCAO (new header dftu_nao_ijr.h):
- cal_hr_ijr<TR>: TK was unused, only TR (double or complex<double>)
is needed; npol is passed explicitly instead of reading ucell.
- cal_occ_ijr: fully non-template (all-double signature), removing
three redundant instantiations; npol is passed explicitly.
- Update the single call site of each kernel and related comments.
- Fix __DEBUG assertion in the occ kernel: occ.size() equals
m_size^2*npol^2 (4*m_size^2 for NSPIN=4), not m_size^2.
Behavior is unchanged in release builds.
* delete useless HR_fixed_done
* docs(dftu): deduplicate header doc comments in module_dftu
Slim the file-headers of dftu_nao_for_r.h / dftu_nao_str_r.h /
dftu_nao_fs_r.h so formulas and the _r/_k naming convention live in
exactly one place, and fix the parameter indentation of cal_fs_nao_r.
* style(dftu): move file-header comments below the include guard
Keep #ifndef/#define at the very top of the header and relocate the
@file doc blocks underneath the guard, so no comment sits above the
first preprocessor line. Also align dftu_nao_folding.h's @file name
and guard macro (DFTU_FOLDING_H -> DFTU_NAO_FOLDING_H) with the
actual filename.
* docs(dftu): replace implementation-detail comments with formulas
Drop comments that merely restate the control flow (branch/step
numbering, "Calls X plus the GEMM", "Reads npol from occmat so
callers...") and keep the physics in the headers instead:
- dftu_hamilt.h: pot_uterm = (V*S + (V*S)^T)/2, HR += (V*SR + SR*V)/2
- dftu_nao_op.h: HR = <phi|chi> pot_onsite <chi|phi>, HK = sum_R e^{ikR} HR;
also fix the class-level comment that wrongly described a non-local
pseudopotential with beta/D notation, and correct the EU formula
(n - n^2 instead of n^2)
- dftu_nao_occ.h: occ(m,m') = sum_R DMR(I,J,R) <phi_0|chi_m(I)> <chi_m'(J)|phi_R>
- dftu_nao_energy.h: E = E_U - E_dc with both terms spelled out
* feat(tools): add 4 documentation-style rules to code_quality_score
New surface rules in the "Naming & formatting" group:
- indented_preprocessor: '#' not at column 0, -1/line (cap 5)
- comment_above_guard: comment block above the first include guard of a
.h file, -1 per contiguous block
- doc_file_mismatch: '@file' name does not match the actual filename, -1
- duplicate_doc_block: prose line (>=40 chars) duplicated verbatim across
comment blocks, -1/line (cap 5); doxygen @-commands, decorative
separator lines, and ALL-CAPS banners are excluded to avoid false hits
on overloaded-function @PARAM lists
Adds extract_comment_blocks() helper that normalises comment text per
block while respecting string literals.
* docs(dftu): clarify the two pot_uterm usage patterns in dftu_hamilt.h
The original wording implied pot_uterm feeds into the HR accumulation,
but pot_uterm_HR_* recompute pot_onsite independently. Split the comment
into the k-space and real-space patterns to remove the false causality.
* style(dftu): drop obsolete __DFTUTEMPLATE include guard
The inner guard used to protect the primary DFTU<T> template from being
redefined when both dftu_pw.h and dftu_lcao.h declared it. The PW side
has since been renamed to DFTU_BASE, no other header declares the
primary template anymore, and the file-level DFTU_NAO_OP_H guard
already prevents re-inclusion. The reserved double-underscore
identifier was also non-conforming.
* refactor(dftu): derive npol from nspin/ucell instead of passing it
npol is fully determined by nspin (npol = nspin == 4 ? 2 : 1) or by the
objects already held by the callee (ucell.get_npol(), occmat.npol()).
Remove the redundant npol parameter/member from:
- cal_energy_correction / calc_energy_u_noncollinear / calc_energy_dc_block
(derive from nspin inside the body)
- pot_onsite_real / pot_onsite_complex (read dftu.occmat().npol())
- pot_uterm_* wrappers (stop forwarding npol)
- DftuFsEnv (npol() accessor returns ucell_->get_npol())
- OperatorDFTU (drop npol ctor arg and member)
Update call sites: setup_dftu_lcao.cpp, force_stress_lcao.cpp,
hamilt_lcao.cpp (x2), spar_u.cpp (x2), write_vxc.hpp,
dftu_nao_fs_k.cpp, dftu_nao_op_legacy.cpp.
Verification:
- cmake --build build -j$(nproc): pass
- ctest --test-dir build -R dftu --output-on-failure: 5/5 pass
* refactor(dftu): hoist is_occmat_ready guards to callers
Move the is_occmat_ready early-return out of pot_uterm_complex,
pot_uterm_real and cal_energy_correction into their callers
(OperatorDFTU::contributeHk specializations and finish_dftu_lcao),
so each low-level kernel has a single responsibility and the guard
lives at the orchestration layer.
The sparse_format::cal_HR_dftu* / pot_uterm_HR_* chain has no callers
yet but is kept intentionally: it is a complete, unwired sparse-HR
output path for the DFT+U term (mirroring cal_HR_exx) and may be
hooked up later.
Verification: full build of abacus_basic_para passes;
ctest -R dftu (5 tests) all pass with OMP_NUM_THREADS=1.
* fix(build): add dftu_nao_op_kernel.o to Makefile.Objects
b442c70 introduced dftu_nao_op_kernel.cpp and registered it in
module_dftu/CMakeLists.txt, but forgot to add the object to the
hand-written Makefile.Objects. CMake builds linked fine, but the
Makefile build failed with undefined references to
DFTU<...>::cal_pot_onsite and DFTU<...>::transfer_pot_onsite.
* refactor(dftu): drop unwired sparse-HR output path for the U term
sparse_format::cal_HR_dftu/cal_HR_dftu_soc have no callers anywhere in
the tree (verified across source/, tests/, interfaces/, python/), and
they were the only consumers of pot_uterm_HR_real/pot_uterm_HR_complex.
Remove the whole dead chain:
- delete spar_u.cpp / spar_u.h
- drop spar_u.cpp from source_lcao/CMakeLists.txt and spar_u.o from
Makefile.Objects (the latter was missed last time this was attempted)
- remove the now-unneeded spar_u.h include from spar_hsr.cpp
- delete pot_uterm_HR_real/pot_uterm_HR_complex from dftu_hamilt.cpp/h
and trim the file-header comment to the k-space pattern only
Verification: full CMake build of abacus_basic_para passes;
ctest -R dftu (5 tests) all pass with OMP_NUM_THREADS=1.
Makefile.Objects kept in sync so the GNU make build no longer
references spar_u.o.
* refactor(dftu): merge pot_uterm/pot_onsite real+complex into templates
- cal_pot_uterm<T>: replace pot_uterm_real/pot_uterm_complex with a
single template; change signature from (ik, isk) to (spin) since
callers only need isk[ik]
- cal_pot_onsite<T>: replace pot_onsite_real/pot_onsite_complex with
a single template; use static_cast<T>(val) for the double->complex
conversion
- Add extern template declarations in headers and explicit
instantiations in .cpp files for double and std::complex<double>
- Unify ScalapackConnector::gemm/tranu calls (real version previously
called pdtran_ directly)
- Update call sites in dftu_nao_op_legacy.cpp and dftu_nao_fs_k.cpp
Verified: make dftu && ctest -R dftu (5/5 passed)
* refactor(dftu): merge dftu_hamilt into dftu_nao_pots
- Move cal_pot_uterm<T> declaration from dftu_hamilt.h into
dftu_nao_pots.h
- Move cal_pot_uterm<T> implementation from dftu_hamilt.cpp into
dftu_nao_pots.cpp
- Delete dftu_hamilt.h and dftu_hamilt.cpp
- Update dftu_nao_op_legacy.cpp include from dftu_hamilt.h to
dftu_nao_pots.h
- Remove dftu_hamilt.cpp from CMakeLists.txt and dftu_hamilt.o from
Makefile.Objects
Verified: make dftu && ctest -R dftu (5/5 passed) && make -j8
* refactor(dftu): drop redundant __MPI guards around Parallel_Reduce calls
Parallel_Reduce::reduce_all is already a no-op when MPI is disabled,
so the call sites do not need their own #ifdef __MPI blocks.
* refactor(dftu): clean up cal_fs_nao_r resource allocation and skip logic
- Initialize dmR_tmp with a loop over spins instead of a nspin==2 special case.
- Skip atoms without plus-U by reusing the precomputed atom_index_all instead
of repeating iat2iait/has_l_channel inside the OpenMP loop.
- Allocate stress_tmp/stress_local/force_local only when the corresponding
quantity is actually requested.
* fix(dftu): guard all spin channels of DMR in cal_fs_nao_r
Previously only get_dmr(0) was checked for nullptr; get_dmr(1) could
still be null when nspin=2 and the density matrix was not ready, leading
to a null-pointer dereference in find_matrix. Now every spin channel is
validated before use.
* refactor(dftu): use std::copy for target-L projector extraction
Replace the hand-written nested loop over m and n with std::copy when
extracting the target_L block from the two-center integrator output.
The new form is shorter, less error-prone, and makes the memory layout
(value, deri_x, deri_y, deri_z) explicit.
* refactor(dftu): extract cal_pot_onsite as a free function
The member function DFTU<OperatorLCAO<TK,TR>>::cal_pot_onsite does not
depend on TK or TR. Pull the implementation into a non-template free
function DFTU_LCAO::cal_pot_onsite in dftu_nao_op_kernel.cpp, and make
the member function a thin wrapper. This removes the template dependency
for callers that only need the shell-level potential.
* refactor(dftu): extract cal_fs_nao_r_impl as non-template core
The body of cal_fs_nao_r never uses TK or TR; all types it touches
(UnitCell, Plus_U_Base, TwoCenterIntegrator, HContainer<double>) are
concrete. Split the implementation into cal_fs_nao_r_impl with explicit
component parameters, and reduce cal_fs_nao_r to a thin template shell
that validates the density matrix and forwards to the impl. The free
function cal_pot_onsite is declared in dftu_nao_pots.h so both the
member wrapper and the new impl can share it.
* refactor(dftu): clean up DFTU operator interface
- Remove dead declarations (cal_force_IJR, cal_stress_IJR) and unused HR member
- Make get_adjs_all() return const reference and propagate const to cal_fs_nao_r_impl
- Drop redundant cal_pot_onsite member wrapper; call the free function directly
- Correct initialize_HR comment to match its actual behavior
All changes verified with make -j$(nproc) and ctest -R dftu --output-on-failure.
* refactor(dftu): decouple force/stress from DFTU operator object
- Add non-template cal_fs_nao_r overload taking explicit environment
arguments (ucell, dftu, intor, nspin, adjs_all, dmR)
- Extract static build_adjacent_atoms() from initialize_HR() so callers
can construct adjacent-atom lists without a DFTU operator instance
- Update force_stress_lcao.cpp to call the new interface directly,
eliminating the temporary construction of a half-initialized DFTU
operator with null hsk/hR
- Remove DFTU::cal_force_stress member and the old template
cal_fs_nao_r(dftu_op, ...) wrapper, now unused
Verified with make -j$(nproc) and ctest -R dftu --output-on-failure.
* refactor(dftu): extract onsite-pot helpers from DFTU operator
Move transfer_pot_onsite and load_occ_from_file out of the DFTU
operator class so the header keeps less helper logic and the operator
focuses on orchestration.
* fix(dftu): use DMR channel count for force/stress spin loop
The DFT+U force/stress path in Force_Stress_LCAO::getForceStress built
dmR_tmp by looping is over PARAM.inp.nspin and calling
get_DMR_pointer(is + 1). For nspin=4 (non-collinear) the DensityMatrix
holds only nspin_dm = 1 real-space DMR channel (the four Pauli components
are packed into a single complex DMR, cf. setup_dm.cpp nspin==2 ? 2 : 1),
so is=1 triggered get_DMR_pointer(2) and threw std::out_of_range
("DMR spin index is out of range"), aborting the scf_u_spin4 case
(nspin=4, dft_plus_u, cal_force=1, cal_stress=1).
cal_for/str_IJR_nao_r only ever index dmR[0] for nspin=1/4 and dmR[0..1]
for nspin=2 (is0 = nspin==2 ? is : 0), so the loop upper bound is changed
to nspin_dm = (nspin==2 ? 2 : 1) to match both the DMR storage and the
consumer indexing.
Verification: built build/abacus_basic_para (v3.11.0-beta9); ran
tests/03_NAO_multik/scf_u_spin4 with mpirun -np 2, OMP_NUM_THREADS=1 ->
exit 0, no out_of_range/Aborted, cal_fs_nao_r/cal_force/getForceStress
all completed. Governance check --staged: PASS (3 warnings, net PARAM
delta -1). Note: absolute etot/force/stress values vs result.ref are a
separate pre-existing regression from the local dftu refactor series,
tracked independently of this crash fix.
* refactor(dftu): remove unused getters from DFTU operator
The five getters (get_ucell/get_dftu/get_intor/get_nspin/get_adjs_all)
were added to feed the force/stress free functions, but those callers
now receive all dependencies as explicit arguments, leaving the getters
with no users. Drop them to shrink the class interface.
Verified: build dftu_lcao_test and hamilt_lcao, ctest -R dftu_lcao_test
passes.
* refactor(dftu): tidy DFTU operator declarations
- Fix constructor declaration spelling DFTU<OperatorLCAO<TK,TR>>(...) ->
DFTU(...)
- Replace empty destructor body with = default in the header
- Drop redundant virtual on contributeHR (override already implies it)
- Inline the single-use private initialize_HR into the constructor
(timer renamed to build_adjacent_atoms)
Verified: build hamilt_lcao and dftu_lcao_test, ctest -R
dftu_lcao_test passes; agent_governance_check.py --staged clean.
* refactor(dftu): extract build_adjacent_atoms into a free function
Move build_adjacent_atoms from a static template member of
DFTU<OperatorLCAO<TK,TR>> into the new non-template free function
DFTU_LCAO::build_adjacent_atoms (dftu_nao_adj.h/.cpp). This stops
recompiling the neighbor-search code at each of the three explicit
template instantiation points and lets force_stress_lcao.cpp drop its
include of the heavy dftu_nao_op.h in favor of the lightweight
dftu_nao_adj.h.
Also fix the AdjacentAtomInfo forward declaration in dftu_nao_fs_r.h
(struct -> class, matching its real declaration).
No behavior change; docs not required (internal refactor only, no
INPUT or interface change).
Verified: cmake reconfigure, build dftu/hamilt_lcao/dftu_lcao_test,
ctest -R dftu passes (5/5); agent_governance_check.py --staged shows
only non-blocking warnings.
* refactor(dftu): extract cal_nlm_all into a free function, drop state flag
Move cal_nlm_all from a template member into the non-template free
function DFTU_LCAO::cal_nlm_all (dftu_nao_adj.h/.cpp) alongside
build_adjacent_atoms, returning the overlap table by value via the new
NlmTot alias. The operator now fills nlm_tot lazily on first
contributeHR() call, so the mutable precal_nlm_done workflow flag is
removed (governance rule 2).
No behavior change; docs not required (internal refactor only).
Verified: build dftu/hamilt_lcao/dftu_lcao_test, ctest -R dftu passes
(5/5).
* refactor(dftu): minimize header dependencies of dftu_nao_op.h
Reduce the includes of dftu_nao_op.h to what its declarations actually
need (governance rule 3):
- Drop unitcell.h, two_center_integrator.h and dftu_base.h in favor of
forward declarations (only used via pointer/reference)
- Keep sltk_grid_driver.h only because AdjacentAtomInfo is a value
member
- Move the now-needed full includes into dftu_nao_op.cpp,
dftu_nao_fs_r.cpp and test/dftu_lcao_test.cpp
This lightens the header for its includers (hamilt_lcao.cpp and the
force/stress translation units).
Verified: build dftu/hamilt_lcao/dftu_lcao_test, ctest -R dftu passes
(5/5).
* refactor(dftu): drop redundant MPI guard and auto in touched code
- Remove the redundant #ifdef __MPI around
Parallel_Reduce::reduce_all() in dftu_nao_op.cpp: the wrapper already
guards the MPI call internally, so the outer guard is dead code.
- Replace auto with explicit types in dftu_nao_adj.cpp and the touched
loop in dftu_nao_op.cpp for readability.
Verified: build dftu/hamilt_lcao/dftu_lcao_test, ctest -R dftu passes
(5/5).
* refactor(dftu): replace remaining auto with explicit types
Replace all remaining auto usages in module_dftu with explicit types:
- get_indexes_row/col results -> std::vector<int>
- get_tau() result -> const ModuleBase::Vector3<double>
- iatlnmipol2iwt() result -> its full nested std::vector<int> type
No redundant #ifdef __MPI around reduce_all remains in this module:
the wrappers that still sit under #ifdef __MPI guard
ScalapackConnector::gemm/tranu, which are MPI-only and genuinely need
the guard.
Verified: build dftu/hamilt_lcao/dftu_lcao_test, ctest -R dftu passes
(5/5).
* refactor(dftu): scope constructor timer to the whole function
Move ModuleBase::timer::start/end to wrap the entire DFTU constructor
body instead of only the build_adjacent_atoms call, and record the
timer-placement rule in AGENTS.md and agent_governance.md.
* refactor(dftu): extract compute_occ_from_dmr into DFTU_LCAO free function
Move the occupation-matrix computation (BRANCH 1 of contributeHR) out of
the DFTU<OperatorLCAO> template into DFTU_LCAO::compute_occ_from_dmr in
dftu_nao_ijr.h, alongside its cal_occ_ijr helper, so it compiles once
instead of at every explicit template instantiation point. The NlmTot
alias moves next to the overlap-table consumers in dftu_nao_ijr.h.
Also add the auto_keyword rule to code_quality_score.py: -1 per `auto`
occurrence, capped at 10 per file, counted on comment/string-stripped
content (auto_ptr does not match).
Verification:
- cmake --build build --target dftu hamilt_lcao dftu_lcao_test: OK
- OMP_NUM_THREADS=1 ctest --test-dir build -R dftu: 5/5 passed
- code_quality_score.py --format json source/source_lcao/module_dftu:
0 auto_keyword findings across 24 files
- agent_governance_check.py --staged: no deterministic findings
(docs-sync warning only; no INPUT or user-facing behavior changed,
pure internal refactor)
* refactor(dftu): extract accumulate_HR_for_iat0 into DFTU_LCAO free function
Move the HR-accumulation loop out of hamilt::DFTU<OperatorLCAO<TK,TR>>
into DFTU_LCAO::accumulate_hr_for_iat0 (dftu_nao_ijr.h), passing ucell,
hR, nlm_tot, iat0, adjs, pv and pot_onsite explicitly, matching the
member -> free function pattern used by compute_occ_from_dmr. The
existing omp critical guard on shared HR updates is preserved.
Add test_dftu_nao_ijr.cpp covering full-grid accumulation and the
missing-R-block skip path; the fixture holds UnitCell buffers in
std::vector/stack storage instead of raw new/delete. Record the
UnitCell iat2it/iat2ia ownership lesson in AGENTS.md.
Verification (OMP_NUM_THREADS=1):
- ctest --test-dir build -R dftu --output-on-failure: 6/6 passed
- valgrind dftu_nao_ijr_test: no invalid free, only OpenMPI/PMIx
MPI_Init socket noise
- python3 tools/03_code_analysis/agent_governance_check.py --staged:
no findings
* refactor(dftu): inline get_dmr helper into contributeHR
The private-use get_dmr() wrapper only forwarded to dm_->is_dmr_ready()
and dm_->get_DMR_pointer() and was called solely from contributeHR().
Inlining it narrows the public interface and makes the DMR-readiness
early exit express the check directly; the 1-based DMR index conversion
is documented at the call site.
Verified: built dftu, dftu_operator_test and dftu_lcao_test targets;
OMP_NUM_THREADS=1 ctest -R 'dftu' passes 6/6.
* refactor(dftu): compute nlm_tot in constructor, drop lazy empty() check
Both adjs_all and nlm_tot are structure snapshots: they depend only on
the atomic structure, which is fixed for the operator's lifetime (the
HamiltLCAO and its operators are rebuilt every ionic step). Moving
nlm_tot from a lazy empty()-gated computation in contributeHR() to the
constructor removes the mutable "has it been computed" workflow state
and guarantees the two structure-dependent members are always
consistent with each other.
The initializer list is limited to direct parameter passthrough; the
two snapshot computations stay in the constructor body so failures are
easy to debug.
Verification:
- cmake --build build -j --target dftu_core_test dftu_operator_test
dftu_lcao_test dftu_nao_ijr_test: pass
- OMP_NUM_THREADS=1 ctest --test-dir build -R "dftu_core_test|
dftu_operator_test|dftu_lcao_test|dftu_nao_ijr_test": 4/4 pass
- ctest 17_DS_DFTU fails on 2 PW cases, but the unmodified baseline
fails on the same 2 cases: pre-existing issue, unrelated
* docs(agents): ban non-trivial calls in constructor initializer lists
Rule 13: limit the member initializer list to direct parameter
passthrough; multi-step computations belong in the constructor body so
failures are easy to debug and intermediate results are inspectable.
* refactor(dftu): move null checks out of cal_occ_mat into caller
Null-pointer validation for pv and p_ham is a caller contract, not
internal logic. Move the check from cal_occ_mat_k/cal_occ_mat_gamma
into finish_dftu_lcao, the single call site, and drop the duplicate
branches from both cal_occ_mat specializations.
* refactor(hamilt): pass Input_para explicitly to HamiltLCAO constructor
Replace direct global PARAM.inp accesses in HamiltLCAO constructor
with an explicit const Input_para& parameter. This reduces cross-layer
control through PARAM and makes the Hamiltonian construction more
testable.
Call sites in esolver_ks_lcao, lcao_others, and esolver_double_xc
now pass *this->inp_ explicitly.
* refactor(dftu): merge dftu_nao_op_kernel.cpp into dftu_nao_pots.cpp
The kernel file held only the non-template DFTU_LCAO::cal_pot_onsite
implementation plus three redundant DFTU explicit instantiations already
present in dftu_nao_op.cpp. The function is declared in dftu_nao_pots.h,
so move the definition next to its declaration and delete the file. The
original 500-line split rationale no longer applies (dftu_nao_op.cpp is
~200 lines).
Verified: cmake --build build --target dftu and dftu_lcao_test pass;
ctest -R "dftu_lcao_test|dftu_operator_test" 2/2 passed (OMP_NUM_THREADS=1).
* style(hamilt): unify indentation and compact operator construction
Replace all tabs with 4 spaces in hamilt_lcao.cpp. Compact multi-line
new Operator(...) calls to fewer lines per call while preserving
alignment. Reduce file from 570 to ~480 lines.
---------
Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
Continues the cleanup (#7940, #7949, #7952, #7953). Four macros come off, and in three of the four files nothing is granted to anyone. - `read_sep_test.cpp` is vestigial: it carries the macro but touches nothing private in `sep.h`. The directives are deleted and nothing else changes, as with `cal_test.cpp` and `test_hsolver.cpp` in #7921. - `soc_test.cpp` read `soc.p_rot[l2p1*i + n]` five times, while `Soc` has a public `rotylm(i1, i2)` returning exactly `p_rot[l2plus1_*i1 + i2]`. Those become `soc.rotylm(i, n)` / `soc.rotylm(i+1, n)`. The sixth use was `EXPECT_NE(soc.p_rot, nullptr)`. That assertion is dropped rather than kept alive with a friend declaration: the next line already calls `soc.rotylm(0, 0)` and checks its value, which covers both "was it allocated" and "is it correct", and the guard was `EXPECT_` rather than `ASSERT_`, so it did not even stop the dereference that follows. `soc.h` is therefore untouched by this PR. - `atom_spec_test.cpp` calls the private `Pseudopot_upf::read_pseudo_upf201`, which writes thirteen members of its object and has no stateless form. It gets `friend class AtomSpecTest;` alongside the `AtomPseudoTest`, `NCPPTest` and `ReadPPTest` grants already there from #7949, plus a forwarding wrapper. The `atom.type` and `atom.ncpp` accesses in the same file are public members of `Atom` and never needed the macro. - `sltk_grid_test.cpp` wrote `PARAM.input.test_grid = 1` only to pass it into `Grid LatGrid(PARAM.input.test_grid)` -- PARAM used as a local, so it becomes one. Its genuine private access is `Grid::setMemberVariables`, 117 lines setting members from a UnitCell, so that gets `friend class SltkGridTest;` and a wrapper. `Grid::pbc` and `Grid::sradius2`, also read here, are public. Friendship is not inherited and a TEST_F body lives in a derived class, hence the wrappers -- the arrangement established in #7949. An earlier revision also removed the macro from `memory_test.cpp` and the three `propagator_test*.cpp`. Compiling without it showed both readings wrong: `memory_test` reads `Memory::name`, `class_name`, `consume` and `init_flag`, private statics reached through `::` rather than a member access; the propagator tests read `PARAM.input`, so they are reason-(a) work. Both are left alone, per the rule this series follows: remove the macro, or leave the file untouched. Macro occurrences 88 -> 84. Production change is two `friend` declarations, one of them added to a list that already exists. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…of friendship (#7964) The `#define private public` cleanup has been reaching for `friend class XxxTest;` whenever a test calls a private method. For part of those methods that is the wrong tool: measuring them shows they never touch `this` at all. A function that uses only its arguments is not a member function, and a test calling it needs neither friendship nor a wrapper -- it needs the function to be declared where it can be called. Of the ten private methods this series has granted friendship for, six use no object state. This change deals with all six, and two of them turn out not to need to exist. ## Two are dead code kept reachable only by a test `Magnetism::judge_parallel` has **no caller anywhere** and is a character-for- character duplicate of the free function `unitcell::judge_parallel` in `cal_ux.h`, which *is* used (`cal_ux.cpp`) and *is* already covered by `UcellTest.JudgeParallel`. The duplicate, its `friend class MagnetismTest;` and the fixture wrapper are removed. Coverage improves rather than shrinks: `MagnetismTest.JudgeParallel` checked both a parallel and a non-parallel pair, while `UcellTest.JudgeParallel` only checked the parallel one. The negative case moves to `UcellTest`, so the surviving, actually-used function is now better tested than before. `Pseudopot_upf::trimend` likewise has no production caller -- only its own definition and a test reaching through the access hack. Removed, along with the half of `ReadPPTest.Trim` that exercised it. ## Four become plain functions `set_pseudo_type`, `trim`, `setqfnew` and `complete_default_h` move out of `Pseudopot_upf` into `namespace pseudopot`, declared in `read_pp.h`. Their bodies are unchanged; the internal callers (`init_pseudo_reader`, `complete_default`, the qfunc expansion in `read_pp.cpp`, and `getnameval` in `read_pp_upf201.cpp`) gain the qualifier. Six forwarding wrappers disappear from `read_pp_test.cpp` and `pseudo_nc_test.cpp`, which now call the functions directly. This is better than the alternatives it replaces: unlike `friend`, it grants no special access to anyone; unlike making them public members, it does not widen the interface of `Pseudopot_upf` at all. ## What this does not achieve No `Pseudopot_upf` friend declaration is removed. All four fixtures still need `read_pseudo_upf201`, which writes thirteen members and is genuinely stateful. The only friendship eliminated here is `Magnetism`'s, and only because its sole private member was the dead duplicate. The remaining four friended methods -- `read_pseudo_upf201` (13 `this->`), `Numerical_Orbital_Lm::cal_kradial` (18) and `plot` (26), and `Grid::setMemberVariables` (34) -- cannot be handled this way: as free functions they would take either the whole object, which gains nothing, or a dozen parameters, which is worse. Extracting a pure computational core from them is a production refactor and belongs in its own proposal, not in a test-access cleanup. ## Verification Linux, `cmake -B build -G Ninja -DBUILD_TESTING=ON -DENABLE_LCAO=ON -DENABLE_MPI=ON -DENABLE_OPENMP=ON`: - Build: the only failing target is `source_lcao/module_lr/.../lr_io_krlist.cpp.o`, on `ri_util.h: RI/global/Array_Operator.h: No such file or directory`. That is pre-existing on `develop` in an environment without LibRI headers (from #7849); this PR touches neither file. Every other target compiles, and the compiler reported no member-access error anywhere, which is the direct confirmation that these six functions really were stateless. - All twelve affected tests pass: `MODULE_CELL_read_pp`, `MODULE_CELL_pseudo_nc`, `MODULE_CELL_atom_pseudo`, `MODULE_CELL_atom_spec`, `MODULE_CELL_magnetism` and the seven `MODULE_CELL_unitcell_test*` variants. - `agent_governance_check.py --base upstream/develop --head HEAD`: 0 errors. No INPUT parameter and no user-visible behaviour changed, so `docs/parameters.yaml` and `docs/advanced/input_files/input-main.md` need no update. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… plus one friend (#7965) `orb_nonlocal_lm_test.cpp` is the last file in `module_ao` carrying `#define private public`. It reaches 78 times into `Numerical_Nonlocal_Lm` from its TEST_F bodies. Most of that needs nothing from the class: ten of the members already have public accessors, so `nnl[ip].nr` becomes `nnl[ip].getNr()`, `.r_radial[ir]` becomes `.getRadial(ir)`, `.beta_k[ik]` becomes `.getBeta_k(ik)`, and so on. Six things have no public route and get `friend class NumericalNonlocalLmTest;` plus thin read-only forwarders on the fixture: the members `label`, `kcut`, `index_proj` and `rab`, and the private methods `freemem()` and `renew()`, which the FreeAndRenew test exists to exercise. Friendship is not inherited and a TEST_F body lives in a derived class, hence the forwarders -- the arrangement established in #7949. Nothing that mutates state is exposed. The r->k->r round-trip check does reach deep -- it swaps the r-space and k-space arrays of a projector, reallocates `rab`, and calls the private `get_kradial()` -- but that code lives in `NumericalNonlocalLmTest::err_r2k2r`, a member of the fixture itself, so the friend declaration covers it and it is unchanged. 28 of the 106 total accesses are inside fixture helpers like that one and needed no edit. No test expectation changed; every substitution reads the same member through the accessor that returns it. With this, `module_ao` has no `#define private public` left. Occurrences tree-wide 84 -> 83. Production change is four lines: a forward declaration and one friend. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 6. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](actions/cache@v4...v6) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…public (#7966) Continues the cleanup (#7940, #7949, #7952, #7953, and open #7963/#7964/#7965). Two class families this time, handled by the same triage: use the accessor that exists, and grant friendship only for what genuinely has no public route. Measured against the TEST_F bodies -- accesses inside fixture members need nothing, since the fixture is the friend -- the four files touch far less than their size suggests: 10, 6, 5 and 1 sites respectively. - **`pw_basis_k_test.cpp` needs nothing granted.** Its only non-public reads are `device` and `precision`, and `PW_Basis` already has `get_device()` / `get_precision()`. - **`pw_basis_test.cpp`** reads the same two through those accessors, and calls three protected routines -- `distribute_g()`, `distribute_r()` and `getstartgr()` -- which set 7, 28 and 33 members of their object and have no stateless form. Those get `friend class ::PWBasisTEST;` and three forwarders. - **`test_hsolver_pw.cpp`** has exactly one live call into protected territory, `hamiltSolvePsiK` (30 `this->`), in the NpwxLessThanNbandsDeath test; the other references to it and to `update_precondition` are commented out. It gets `friend class ::TestHSolverPW;` and one forwarder. - **`test_hsolver_sdft.cpp`** is vestigial: every `TEST_F` in it is commented out, and the `nbands` it appeared to touch is `stowf.nbands_diag`, a member of a different class. The directives are simply deleted, as with `cal_test.cpp` and `test_hsolver.cpp` in #7921. `FFT_Bundle` gains `get_device()` and `get_precision()`. The pw tests check that `PW_Basis`'s constructor propagates device and precision into its `fft_bundle`, which is a real behavioural check and not redundant, but `FFT_Bundle`'s copies were private with no accessor. `PW_Basis` already exposes exactly this pair, so this completes a parallel that was half-present rather than inventing an accessor for a test. Both friended classes live in a namespace (`ModulePW`, `hsolver`) while the fixtures are at global scope, so each needs a global forward declaration and `friend class ::Fixture;` -- an unqualified `friend class Fixture;` would name a nonexistent class inside the namespace and silently grant nothing. Occurrences tree-wide 88 -> 84. Production change is three friend declarations with their forward declarations, plus the two `FFT_Bundle` accessors. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…/ Lattice_Change_CG / Ions_Move_BFGS2) (#7967) * source_relax: Ions_Move_SD off the access hack, via getters and a free function ions_move_sd_test.cpp used `#define private public` for two separate reasons, each of which has a proper fix: - It reads back `energy_saved`, `pos_saved` and `grad_saved` to check what `allocate()` and `start()` produced. Every one of these is a read, so three const getters cover them. The names follow the `get_*` convention already used by `Ions_Move_Methods`. - It calls the private `cal_tradius_sd()`. That method is `const` and touches no member at all -- it works only on its arguments and on the shared `Ions_Move_Basic` state -- so it is now a free function in a new `ions_move_sd` namespace and the test calls it directly. Its function-local `static int accepted_number` keeps exactly the semantics it had as a member (it was already shared across instances). No friend declaration is needed, and no expected value in the test changed. The vestigial `#include "source_io/module_parameter/parameter.h"` also goes: this test never referenced PARAM. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * source_relax: Ions_Move_CG and Lattice_Change_CG off the access hack, via a test friend Both CG tests need the same two things from the class under test: they read the saved previous-step vectors (`pos0`/`lat0`, `grad0`, `cg_grad0`, `move0`) to check that `allocate()` sized and zeroed them, and they seed `move0[0]` before calling `start()` in order to drive its trial / no-trial branches. The reads alone would be served by getters, but the seeding is genuine white-box state injection: there is no input to `start()` that reproduces it without changing the expected numbers the tests assert on. So each class friends its own test fixture instead, which replaces a blanket `#define private public` over the whole header with one named declaration. Friendship is not inherited and a TEST_F body lives in a class derived from the fixture, so the fixtures gained thin `get_*` / `set_move0` forwarders. They are named `get_*` rather than bare member names because several tests declare locals called `grad0` and `cg_grad0`. `ions_move_cg_test.cpp` also drops a vestigial `#include "source_io/module_parameter/parameter.h"`; it never referenced PARAM. No expected value changed in either test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * source_relax: Ions_Move_BFGS2 off the access hack, via a test friend bfgs_test.cpp drives the private step machinery of Ions_Move_BFGS2 directly: it seeds `sign`, `pos_taud` and `force0`, then calls `DetermineStep`, `Update`, `GetPos`, `GetPostaud` and `CalculateLargestGrad` one stage at a time and inspects the resulting Hessian and positions. That is deliberate white-box testing of the algorithm's internals, so the class friends its own fixture rather than growing accessors that nothing in production would use. Friendship is not inherited and a TEST_F body lives in a class derived from the fixture, so the fixture gained `get_*` / `set_*` / `call_*` forwarders. The prefixes are not decoration: several tests declare locals named pos, force, size, steplength, dpos and maxstep, which would shadow bare names. `PARAM.inp.relax_bfgs_rmax` at the allocate() assertion is unaffected -- it reads the public half and never needed the macro. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* refactor MDCell and domain decomposition interfaces * test: include MD decomposition test sources * restore cell accessors and prepare MD neighbors in tests * fix MDCell accessor linkage --------- Co-authored-by: Fei Yang <2501213217@stu.pku.edu.cn>
…tials (USPP) (#7944) * Refactor get_pchg_pw and get_wf_pw from single .h to .h with .cpp * Feature: Support USPP partial-charge output and unify PW charge and wavefunction output handling * Add missing USPP density and PW output objects to Makefile * Remove unrelated README20260902 introduced in PR 7899 * Refactor: Centralize band-parallel operations in ParaBandOutput and fix serial spin-resolved band output * Remove `#define private public` macros from `elecstate_base_test` using `TestParameters` friend
…ration (#7923) * fix(hsolver): honor Hermitian upper triangles in native ELPA and cuSolver * fix(hsolver): honor Hermitian upper triangle in genelpa (cherry picked from commit e27ef66) * Fix second generalized ELPA transform (cherry picked from commit 53208bf) * fix(test): allocate the advertised LAPACK workspace * fix(exx): average irreducible densities over the little group Project multi-k density matrices before star restoration to preserve the symmetry assumed by reduced EXX contractions. Add complex-density and spin-channel regressions and update the Si HSE reference after independent solver and full-contraction checks. * docs: synchronize EXX symmetry description with parameter source --------- Co-authored-by: Chen Chengbing <1747193328@qq.com> Co-authored-by: TaoXia <taoxia@mail.ustc.edu.cn> Co-authored-by: Mohan Chen <mohanchen@pku.edu.cn>
* fix: use truncated pseudo-inverse for Broyden mixing * fix: apply Broyden eigenvector transforms in LAPACK layout * test: tighten Taylor TDDFT convergence and refresh energy reference
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.
update to the newest version 2026-09-14