From 2c79471f2a774e814e8df6973ae0346ba4d16140 Mon Sep 17 00:00:00 2001 From: Critsium Date: Tue, 21 Jul 2026 14:09:57 +0800 Subject: [PATCH] Refactor: move EXX file-list broadcast out of source_cell (#7635) bcast_cell.cpp reached into GlobalC::exx_info (source_hamilt/module_xc) to broadcast the ABFS/JLE orbital-file lists, making the source_cell data-structure layer depend on a higher layer. The ABFS/JLE orbital files are an LCAO-only concept, so the broadcast is placed in the LCAO EXX manager: add bcast_exx_file_lists() in source_lcao/setup_exx.{h,cpp} and invoke it at the start of Exx_NAO::init(), before Exx_LRI copies info_ri. init() runs in ESolver_KS_LCAO::before_all_runners (reused by TDDFT/DM2rho/DoubleXC; LR reuses the moved Exx_LRI), on all ranks, after setup_cell has populated the lists on rank 0 and before every consumer (RI-EXX, opt-ABFs generate_matrix, RPA postSCF). This removes the exx_info.h include, the helper, and the three broadcast calls from bcast_cell.cpp. The per-ionic-step re-broadcast previously done via bcast_unitcell is dropped, which is behaviour-neutral: the file lists are static once read from STRU. Co-Authored-By: Claude Opus 4.8 --- source/source_cell/bcast_cell.cpp | 25 ------------------- source/source_lcao/setup_exx.cpp | 41 +++++++++++++++++++++++++++++++ source/source_lcao/setup_exx.h | 13 ++++++++++ 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/source/source_cell/bcast_cell.cpp b/source/source_cell/bcast_cell.cpp index fdc34dbbf83..231414d8a64 100644 --- a/source/source_cell/bcast_cell.cpp +++ b/source/source_cell/bcast_cell.cpp @@ -1,30 +1,11 @@ #include "unitcell.h" #include "source_base/parallel_common.h" -#include "source_hamilt/module_xc/exx_info.h" // use GlobalC::exx_info - #include #include namespace unitcell { -#if defined(__MPI) && defined(__EXX) - // Broadcast a vector from rank 0 to all ranks. - // Replaces the former cereal-based ModuleBase::bcast_data_cereal, which - // was only ever used here to broadcast plain lists of ABFS file names and - // pulled source_cell into a dependency on source_lcao/module_ri. - static void bcast_string_vector(std::vector& v) - { - int size = static_cast(v.size()); - Parallel_Common::bcast_int(size); - v.resize(size); - for (int i = 0; i < size; ++i) - { - Parallel_Common::bcast_string(v[i]); - } - } -#endif - void bcast_atoms_tau(Atom* atoms, const int ntype) { @@ -131,12 +112,6 @@ namespace unitcell { Parallel_Common::bcast_string(ucell.orbital_fn[i]); } - - #ifdef __EXX - bcast_string_vector(GlobalC::exx_info.info_ri.files_abfs); - bcast_string_vector(GlobalC::exx_info.info_opt_abfs.files_abfs); - bcast_string_vector(GlobalC::exx_info.info_opt_abfs.files_jles); - #endif return; #endif } diff --git a/source/source_lcao/setup_exx.cpp b/source/source_lcao/setup_exx.cpp index d6bcc97d5c3..aa9f868fff8 100644 --- a/source/source_lcao/setup_exx.cpp +++ b/source/source_lcao/setup_exx.cpp @@ -2,6 +2,42 @@ #ifdef __EXX #include "source_lcao/module_ri/Exx_LRI_interface.h" +#include "source_hamilt/module_xc/exx_info.h" // use the global Exx_Info +#if defined(__MPI) +#include "source_base/parallel_common.h" +#include +#include +#endif +#endif + +#ifdef __EXX +#if defined(__MPI) +namespace +{ + // Broadcast a vector from rank 0 to all ranks. + // Moved here from source_cell/bcast_cell.cpp so that source_cell no longer + // depends on the XC module just to distribute these ABFS file-name lists. + void bcast_string_vector(std::vector& v) + { + int size = static_cast(v.size()); + Parallel_Common::bcast_int(size); + v.resize(size); + for (int i = 0; i < size; ++i) + { + Parallel_Common::bcast_string(v[i]); + } + } +} // namespace +#endif + +void bcast_exx_file_lists() +{ +#if defined(__MPI) + bcast_string_vector(GlobalC::exx_info.info_ri.files_abfs); + bcast_string_vector(GlobalC::exx_info.info_opt_abfs.files_abfs); + bcast_string_vector(GlobalC::exx_info.info_opt_abfs.files_jles); +#endif +} #endif template @@ -20,6 +56,11 @@ void Exx_NAO::init() // which cause the failure of the subsequent procedure reused by ESolver_LCAO_TDDFT // 2. always construct but only initialize when if(cal_exx) is true // because some members like two_level_step are used outside if(cal_exx) + + // Distribute the ABFS/JLE file lists (read from STRU on rank 0) to all ranks + // before Exx_LRI copies info_ri below. + bcast_exx_file_lists(); + if (GlobalC::exx_info.info_ri.real_number) { this->exd = std::make_shared>(GlobalC::exx_info.info_ri, GlobalC::exx_info.info_global); diff --git a/source/source_lcao/setup_exx.h b/source/source_lcao/setup_exx.h index faf232e3de9..7bc706944e4 100644 --- a/source/source_lcao/setup_exx.h +++ b/source/source_lcao/setup_exx.h @@ -47,5 +47,18 @@ class Exx_NAO }; +#ifdef __EXX +/** + * @brief Broadcast the ABFS/JLE orbital-file lists held in the global Exx_Info instance. + * + * The lists are read from STRU on rank 0 during setup_cell and must be + * distributed to all ranks before the LCAO EXX/RI module consumes them. + * This logic lives here (rather than in source_cell or the generic XC module) + * because the ABFS/JLE orbital files are an LCAO-only concept. It is invoked at + * the start of Exx_NAO::init(), before Exx_LRI copies info_ri. + */ +void bcast_exx_file_lists(); +#endif + #endif