From e088116bfd29d29f6ad90fb46bc9763adf71b57a Mon Sep 17 00:00:00 2001 From: Critsium Date: Wed, 22 Jul 2026 14:47:15 +0800 Subject: [PATCH] Refactor: read EXX ABFS/JLE file lists via UnitCell, decouple source_cell (#7598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit read_atom_species.cpp (source_cell) parsed the STRU ABFS_ORBITAL / ABFS_JLES_ORBITAL sections directly into GlobalC::exx_info, making the source_cell data-structure layer depend on source_hamilt/module_xc. This was the last remaining reverse dependency in source_cell. Route the lists through UnitCell instead — the same place STRU orbital-file names already live (orbital_fn, descriptor_file): - UnitCell gains neutral members abfs_orbital_files / jle_orbital_files. - read_atom_species parses the sections into those members; the exx_info.h include and the cal_exx guard are removed (absent sections are no-ops). - bcast_cell broadcasts the two members as part of bcast_unitcell. - Exx_NAO::init(ucell) copies them into GlobalC::exx_info before Exx_LRI copies info_ri, keeping the EXX-specific routing in the LCAO EXX layer. Because the lists now travel inside the (already broadcast) UnitCell, the dedicated bcast_exx_file_lists() added in #7635 is redundant and removed. After this, source_cell (non-test) includes only source_base and itself. Co-Authored-By: Claude Opus 4.8 --- source/source_cell/bcast_cell.cpp | 18 +++++++++ source/source_cell/read_atom_species.cpp | 37 ++++++++---------- source/source_cell/unitcell.h | 2 + source/source_esolver/esolver_ks_lcao.cpp | 2 +- source/source_lcao/setup_exx.cpp | 47 ++++------------------- source/source_lcao/setup_exx.h | 15 +------- 6 files changed, 45 insertions(+), 76 deletions(-) diff --git a/source/source_cell/bcast_cell.cpp b/source/source_cell/bcast_cell.cpp index 231414d8a6..344535740b 100644 --- a/source/source_cell/bcast_cell.cpp +++ b/source/source_cell/bcast_cell.cpp @@ -6,6 +6,20 @@ namespace unitcell { +#ifdef __MPI + // Broadcast a vector (size then elements) from rank 0 to all ranks. + 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) { @@ -112,6 +126,10 @@ namespace unitcell { Parallel_Common::bcast_string(ucell.orbital_fn[i]); } + + // ABFS/JLE orbital-file lists (read from STRU on rank 0, used by LCAO EXX) + bcast_string_vector(ucell.abfs_orbital_files); + bcast_string_vector(ucell.jle_orbital_files); return; #endif } diff --git a/source/source_cell/read_atom_species.cpp b/source/source_cell/read_atom_species.cpp index 3ef39d119d..91b94f0c3a 100644 --- a/source/source_cell/read_atom_species.cpp +++ b/source/source_cell/read_atom_species.cpp @@ -3,7 +3,6 @@ #include #include "source_base/tool_title.h" -#include "source_hamilt/module_xc/exx_info.h" // use GlobalC::exx_info namespace unitcell { @@ -106,33 +105,27 @@ bool read_atom_species(std::ifstream& ifa, } #ifdef __LCAO // Peize Lin add 2016-09-23 -#ifdef __MPI -#ifdef __EXX - if( GlobalC::exx_info.info_global.cal_exx || rpa ) + // Read the ABFS/JLE orbital filenames (used by LCAO EXX) into the UnitCell. + // The EXX layer copies these into the global Exx_Info during its own setup, so + // source_cell does not depend on the XC module. Absent sections are no-ops. + if( ModuleBase::GlobalFunc::SCAN_LINE_BEGIN(ifa, "ABFS_ORBITAL") ) { - if( ModuleBase::GlobalFunc::SCAN_LINE_BEGIN(ifa, "ABFS_ORBITAL") ) + for(int i=0; i> ofile; - GlobalC::exx_info.info_ri.files_abfs.push_back(ofile); - GlobalC::exx_info.info_opt_abfs.files_abfs.push_back(ofile); - } + std::string ofile; + ifa >> ofile; + ucell.abfs_orbital_files.push_back(ofile); } - if( ModuleBase::GlobalFunc::SCAN_LINE_BEGIN(ifa, "ABFS_JLES_ORBITAL") ) + } + if( ModuleBase::GlobalFunc::SCAN_LINE_BEGIN(ifa, "ABFS_JLES_ORBITAL") ) + { + for(int i=0; i> ofile; - GlobalC::exx_info.info_opt_abfs.files_jles.push_back(ofile); - } + std::string ofile; + ifa >> ofile; + ucell.jle_orbital_files.push_back(ofile); } } - -#endif // __EXX -#endif // __MPI #endif // __LCAO return true; } diff --git a/source/source_cell/unitcell.h b/source/source_cell/unitcell.h index 78098ac3d7..ecd97431b1 100644 --- a/source/source_cell/unitcell.h +++ b/source/source_cell/unitcell.h @@ -233,6 +233,8 @@ class UnitCell : public AtomProvider { std::vector orbital_fn; // filenames of orbitals, liuyu add 2022-10-19 std::string descriptor_file; // filenames of descriptor_file, liuyu add 2023-04-06 + std::vector abfs_orbital_files; // ABFS orbital filenames read from STRU "ABFS_ORBITAL" (used by LCAO EXX) + std::vector jle_orbital_files; // JLE orbital filenames read from STRU "ABFS_JLES_ORBITAL" (used by LCAO EXX) void set_iat2itia(); diff --git a/source/source_esolver/esolver_ks_lcao.cpp b/source/source_esolver/esolver_ks_lcao.cpp index e24eb7fc8d..08e46600b1 100644 --- a/source/source_esolver/esolver_ks_lcao.cpp +++ b/source/source_esolver/esolver_ks_lcao.cpp @@ -53,7 +53,7 @@ void ESolver_KS_LCAO::before_all_runners(UnitCell& ucell, const Input_pa ModuleBase::timer::start("ESolver_KS_LCAO", "before_all_runners"); // 0) init EXX - moved from constructor to ensure GlobalC::exx_info.info_global is already set - this->exx_nao.init(); + this->exx_nao.init(ucell); // 1) before_all_runners in ESolver_KS ESolver_KS::before_all_runners(ucell, inp); diff --git a/source/source_lcao/setup_exx.cpp b/source/source_lcao/setup_exx.cpp index aa9f868fff..4fdb453fcb 100644 --- a/source/source_lcao/setup_exx.cpp +++ b/source/source_lcao/setup_exx.cpp @@ -3,41 +3,6 @@ #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 @@ -48,7 +13,7 @@ Exx_NAO::~Exx_NAO(){} template -void Exx_NAO::init() +void Exx_NAO::init(const UnitCell& ucell) { #ifdef __EXX // 1. currently this initialization must be put in constructor rather than `before_all_runners()` @@ -57,9 +22,13 @@ void Exx_NAO::init() // 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(); + // The ABFS/JLE orbital-file lists are read from STRU into the UnitCell (and + // broadcast with it). Copy them into the EXX info here, before Exx_LRI copies + // info_ri below. This keeps the EXX-specific routing (which list feeds info_ri + // vs info_opt_abfs) in the LCAO EXX layer, so source_cell stays decoupled. + GlobalC::exx_info.info_ri.files_abfs = ucell.abfs_orbital_files; + GlobalC::exx_info.info_opt_abfs.files_abfs = ucell.abfs_orbital_files; + GlobalC::exx_info.info_opt_abfs.files_jles = ucell.jle_orbital_files; if (GlobalC::exx_info.info_ri.real_number) { diff --git a/source/source_lcao/setup_exx.h b/source/source_lcao/setup_exx.h index 7bc706944e..d8fc5aa0a2 100644 --- a/source/source_lcao/setup_exx.h +++ b/source/source_lcao/setup_exx.h @@ -28,7 +28,7 @@ class Exx_NAO std::shared_ptr>> exc = nullptr; #endif - void init(); + void init(const UnitCell& ucell); void before_runner( UnitCell& ucell, // unitcell @@ -47,18 +47,5 @@ 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