Skip to content

Commit 156e887

Browse files
author
abacus_fixer
committed
refactor(exx): remove GlobalC::exx_info global variable
Remove the GlobalC::exx_info global instance entirely. The Exx_Info data is now owned by ESolver_KS (exx_info_obj_ member) and passed through function parameters to all consumers. Key changes: - Extract Exx_Info initialization logic from Input_Conv::Convert() into a standalone init_exx_info(Exx_Info&, const Input_para&) function in exx_info.cpp. ESolver_KS constructor calls this to initialize its owned Exx_Info object directly from input parameters. - Remove GlobalC::exx_info extern declaration and definition. - Add const Exx_Info& parameter to all functions that previously accessed GlobalC::exx_info: ctrl_runner_lcao, ctrl_scf_lcao, ctrl_iter_lcao, ctrl_output_td, write_dH_components, write_dH_sum, write_dH_exx, write_h_exx, write_Vxc, write_eband_terms, sum_HR, write_current, and their helper functions. - Update all call sites in ESolver to pass *exx_info_ (the owned Exx_Info object). - ESolver_LR (LR-TDDFT) now owns its Exx_Info as a value member initialized via init_exx_info instead of referencing the global. - Update stale include comments referencing GlobalC::exx_info.
1 parent 0b727a0 commit 156e887

33 files changed

Lines changed: 349 additions & 282 deletions

source/source_esolver/esolver_ks.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,16 @@
1414
#include "source_io/module_output/output_log.h" // use write_head
1515
#include "source_estate/elecstate_print.h" // print_etot
1616
#include "source_lcao/module_dftu/dftu.h" // mohan add 2025-11-07
17-
#include "source_hamilt/module_xc/exx_info.h" // for GlobalC::exx_info bridge
17+
#include "source_hamilt/module_xc/exx_info.h" // for init_exx_info and Exx_Info
1818

1919
namespace ModuleESolver
2020
{
2121

2222
ESolver_KS::ESolver_KS()
2323
{
24-
// ESolver owns its own Exx_Info object, copied from the global instance
25-
// initialized by Input_Conv::Convert(). This breaks the dependency on
26-
// GlobalC::exx_info from ESolver internals; the global will be removed
27-
// in a follow-up commit.
28-
exx_info_obj_ = GlobalC::exx_info;
24+
// ESolver owns its own Exx_Info object, initialized directly from input
25+
// parameters. This breaks the dependency on any global Exx_Info instance.
26+
init_exx_info(exx_info_obj_, PARAM.inp);
2927
}
3028

3129

source/source_esolver/esolver_ks.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ class ESolver_KS : public ESolver_FP
7575
bool oscillate_esolver = false; // whether esolver is oscillated
7676
bool scf_nmax_flag = false; // whether scf has reached nmax, mohan add 20250921
7777

78-
/// EXX info owned by ESolver, copied from GlobalC::exx_info during construction.
79-
/// Will become the sole owner after GlobalC::exx_info is removed.
78+
/// EXX info owned by ESolver, initialized from input parameters.
8079
Exx_Info exx_info_obj_;
8180

8281
/// Pointer to the owned Exx_Info object, for uniform access pattern.

source/source_esolver/esolver_ks_lcao.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ void ESolver_KS_LCAO<TK, TR>::after_all_runners(BaseCell& basecell)
309309
this->gd, this->psi, this->chr, hamilt_lcao,
310310
this->two_center_bundle_,
311311
this->orb_, this->pw_rho, this->pw_rhod,
312-
this->sf, this->locpp.vloc, this->exx_nao, this->solvent);
312+
this->sf, this->locpp.vloc, this->exx_nao, *this->exx_info_, this->solvent);
313313

314314

315315
#ifdef __MPI
@@ -537,7 +537,7 @@ void ESolver_KS_LCAO<TK, TR>::iter_finish(UnitCell& ucell, const int istep, int&
537537
ModuleIO::ctrl_iter_lcao<TK, TR>(ucell, PARAM.inp, this->kv, this->pelec, *this->dmat.dm,
538538
this->pv, this->gd, this->psi, this->chr, this->p_chgmix,
539539
hamilt_lcao, this->orb_, this->deepks,
540-
this->exx_nao, iter, istep, conv_esolver, this->scf_ene_thr);
540+
this->exx_nao, *this->exx_info_, iter, istep, conv_esolver, this->scf_ene_thr);
541541
}
542542

543543
template <typename TK, typename TR>
@@ -567,7 +567,7 @@ void ESolver_KS_LCAO<TK, TR>::after_scf(UnitCell& ucell, const int istep, const
567567
this->gd, this->psi, hamilt_lcao, this->dftu, this->two_center_bundle_,
568568
this->orb_, this->pw_wfc, this->pw_rho, this->pw_big, this->sf,
569569
this->pw_rhod, this->locpp.vloc, this->solvent,
570-
this->rdmft_solver, this->deepks, this->exx_nao,
570+
this->rdmft_solver, this->deepks, this->exx_nao, *this->exx_info_,
571571
this->conv_esolver, this->scf_nmax_flag, istep);
572572

573573
//! 3) Clean up RA, which is used to serach for adjacent atoms

source/source_esolver/esolver_ks_lcao_tddft.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,8 @@ void ESolver_KS_LCAO_TDDFT<TR, Device>::after_scf(UnitCell& ucell, const int ist
580580
hamilt_lcao,
581581
this->RA,
582582
this->td_p,
583-
this->exx_nao);
583+
this->exx_nao,
584+
*this->exx_info_);
584585

585586
ModuleBase::timer::end(this->classname, "after_scf");
586587
}
Lines changed: 206 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,211 @@
11
#include "exx_info.h"
22

3+
#include "source_io/module_parameter/input_parameter.h"
4+
#include "source_base/global_function.h"
5+
6+
#include <algorithm>
7+
#include <cassert>
8+
#include <string>
9+
#include <vector>
10+
311
//----------------------------------------------------------
4-
// init "GLOBAL CLASS" object
12+
// Initialize Exx_Info from input parameters.
13+
// Extracted from Input_Conv::Convert() to allow ESolver to own
14+
// its own Exx_Info object without depending on the global instance.
15+
// Peize Lin add 2018-06-20, refactored 2026.
516
//----------------------------------------------------------
6-
namespace GlobalC
17+
bool init_exx_info(Exx_Info& exx_info, const Input_para& inp)
718
{
8-
Exx_Info exx_info;
9-
}
19+
std::string dft_functional_lower = inp.dft_functional;
20+
std::transform(inp.dft_functional.begin(),
21+
inp.dft_functional.end(),
22+
dft_functional_lower.begin(),
23+
tolower);
24+
bool generate_opt_orb = false;
25+
if (dft_functional_lower == "hf"
26+
|| dft_functional_lower == "pbe0" || dft_functional_lower == "b3lyp" || dft_functional_lower == "hse"
27+
|| dft_functional_lower == "scan0"
28+
|| dft_functional_lower == "muller" || dft_functional_lower == "power"
29+
|| dft_functional_lower == "cwp22" || dft_functional_lower == "wp22"
30+
|| dft_functional_lower == "lc_pbe"
31+
|| dft_functional_lower == "lc_wpbe"
32+
|| dft_functional_lower == "lrc_wpbe"
33+
|| dft_functional_lower == "lrc_wpbeh"
34+
|| dft_functional_lower == "cam_pbeh")
35+
{
36+
exx_info.info_global.cal_exx = true;
37+
38+
exx_info.info_global.hybrid_alpha = 0;
39+
std::vector<double> fock_alpha(inp.exx_fock_alpha.size());
40+
for(std::size_t i=0; i<fock_alpha.size(); ++i)
41+
{
42+
fock_alpha[i] = std::stod(inp.exx_fock_alpha[i]);
43+
exx_info.info_global.hybrid_alpha = std::max(std::abs(fock_alpha[i]), exx_info.info_global.hybrid_alpha);
44+
}
45+
std::vector<double> erfc_alpha(inp.exx_erfc_alpha.size());
46+
for(std::size_t i=0; i<erfc_alpha.size(); ++i)
47+
{
48+
erfc_alpha[i] = std::stod(inp.exx_erfc_alpha[i]);
49+
exx_info.info_global.hybrid_alpha = std::max(std::abs(erfc_alpha[i]), exx_info.info_global.hybrid_alpha);
50+
}
51+
assert(exx_info.info_global.hybrid_alpha>0);
52+
for(std::size_t i=0; i<fock_alpha.size(); ++i)
53+
{ fock_alpha[i] /= exx_info.info_global.hybrid_alpha; }
54+
for(std::size_t i=0; i<erfc_alpha.size(); ++i)
55+
{ erfc_alpha[i] /= exx_info.info_global.hybrid_alpha; }
56+
57+
if(!fock_alpha.empty())
58+
{
59+
if(inp.basis_type == "lcao")
60+
{
61+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Fock].resize(fock_alpha.size());
62+
for(std::size_t i=0; i<fock_alpha.size(); ++i)
63+
{
64+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Fock] = {{
65+
{"alpha", ModuleBase::GlobalFunc::TO_STRING(fock_alpha[i])},
66+
{"singularity_correction", inp.exx_singularity_correction} }};
67+
}
68+
}
69+
else if(inp.basis_type == "lcao_in_pw")
70+
{
71+
assert(fock_alpha.size() == inp.exx_fock_lambda.size());
72+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Fock].resize(fock_alpha.size());
73+
for(std::size_t i=0; i<fock_alpha.size(); ++i)
74+
{
75+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Fock] = {{
76+
{"alpha", ModuleBase::GlobalFunc::TO_STRING(fock_alpha[i])},
77+
{"lambda", inp.exx_fock_lambda[i]} }};
78+
}
79+
}
80+
else if(inp.basis_type == "pw")
81+
{
82+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Fock].resize(fock_alpha.size());
83+
for(std::size_t i=0; i<fock_alpha.size(); ++i)
84+
{
85+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Fock] = {{
86+
{"alpha", ModuleBase::GlobalFunc::TO_STRING(fock_alpha[i])} }};
87+
}
88+
}
89+
else
90+
{
91+
throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__));
92+
}
93+
}
94+
if(!erfc_alpha.empty())
95+
{
96+
assert(erfc_alpha.size() == inp.exx_erfc_omega.size());
97+
if(inp.basis_type == "lcao")
98+
{
99+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Erfc].resize(erfc_alpha.size());
100+
for(std::size_t i=0; i<erfc_alpha.size(); ++i)
101+
{
102+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Erfc] = {{
103+
{"alpha", ModuleBase::GlobalFunc::TO_STRING(erfc_alpha[i])},
104+
{"omega", ModuleBase::GlobalFunc::TO_STRING(inp.exx_erfc_omega[i])},
105+
{"singularity_correction", inp.exx_singularity_correction} }};
106+
}
107+
}
108+
else if(inp.basis_type == "pw" || inp.basis_type == "lcao_in_pw")
109+
{
110+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Erfc].resize(erfc_alpha.size());
111+
for(std::size_t i=0; i<erfc_alpha.size(); ++i)
112+
{
113+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Erfc] = {{
114+
{"alpha", ModuleBase::GlobalFunc::TO_STRING(erfc_alpha[i])},
115+
{"omega", ModuleBase::GlobalFunc::TO_STRING(inp.exx_erfc_omega[i])} }};
116+
}
117+
}
118+
}
119+
}
120+
#ifdef __EXX
121+
else if (dft_functional_lower == "opt_orb")
122+
{
123+
exx_info.info_global.cal_exx = false;
124+
generate_opt_orb = true;
125+
}
126+
#endif
127+
else
128+
{
129+
exx_info.info_global.cal_exx = false;
130+
}
131+
132+
if (inp.rpa && exx_info.info_global.coulomb_param.empty())
133+
{
134+
if (inp.basis_type != "lcao")
135+
{
136+
throw std::invalid_argument("RPA currently expects basis_type=lcao when initializing RI Coulomb parameters.");
137+
}
138+
exx_info.info_global.hybrid_alpha = 1.0;
139+
exx_info.info_global.ccp_type = Conv_Coulomb_Pot_K::Ccp_Type::Hf;
140+
exx_info.info_global.coulomb_param[Conv_Coulomb_Pot_K::Coulomb_Type::Fock] = {{
141+
{"alpha", "1"},
142+
{"singularity_correction", inp.exx_singularity_correction}
143+
}};
144+
}
145+
146+
// info_global.ccp_type will be removed in the future. these codes for pw and lcao_in_pw temporarily
147+
if (dft_functional_lower == "hf"
148+
|| dft_functional_lower == "pbe0" || dft_functional_lower == "b3lyp"
149+
|| dft_functional_lower == "scan0"
150+
|| dft_functional_lower == "muller" || dft_functional_lower == "power")
151+
{
152+
exx_info.info_global.ccp_type = Conv_Coulomb_Pot_K::Ccp_Type::Hf;
153+
}
154+
// use the error function erf(w|r-r'|), exx just has the short-range part
155+
else if (dft_functional_lower == "hse"
156+
|| dft_functional_lower == "cwp22")
157+
{
158+
exx_info.info_global.ccp_type = Conv_Coulomb_Pot_K::Ccp_Type::Erfc;
159+
}
160+
// use the error function erf(w|r-r'|), exx just has the long-range part
161+
else if ( dft_functional_lower == "wp22" )
162+
{
163+
exx_info.info_global.ccp_type = Conv_Coulomb_Pot_K::Ccp_Type::Erf;
164+
}
165+
166+
if (exx_info.info_global.cal_exx
167+
#ifdef __EXX
168+
|| generate_opt_orb
169+
|| inp.rpa
170+
#endif
171+
)
172+
{
173+
// EXX case, convert all EXX related variables
174+
if(!inp.exx_erfc_omega.empty())
175+
{ exx_info.info_global.hse_omega = std::stod(inp.exx_erfc_omega[0]); }
176+
if(!inp.exx_fock_lambda.empty())
177+
{ exx_info.info_lip.lambda = std::stod(inp.exx_fock_lambda[0]); }
178+
exx_info.info_global.separate_loop = inp.exx_separate_loop;
179+
exx_info.info_global.hybrid_step = inp.exx_hybrid_step;
180+
exx_info.info_global.mixing_beta_for_loop1 = inp.exx_mixing_beta;
181+
182+
exx_info.info_ri.real_number = std::stoi(inp.exx_real_number);
183+
exx_info.info_ri.pca_threshold = inp.exx_pca_threshold;
184+
exx_info.info_ri.C_threshold = inp.exx_c_threshold;
185+
exx_info.info_ri.V_threshold = inp.exx_v_threshold;
186+
exx_info.info_ri.dm_threshold = inp.exx_dm_threshold;
187+
exx_info.info_ri.C_grad_threshold = inp.exx_c_grad_threshold;
188+
exx_info.info_ri.V_grad_threshold = inp.exx_v_grad_threshold;
189+
exx_info.info_ri.C_grad_R_threshold = inp.exx_c_grad_r_threshold;
190+
exx_info.info_ri.V_grad_R_threshold = inp.exx_v_grad_r_threshold;
191+
exx_info.info_ri.ccp_rmesh_times = std::stod(inp.exx_ccp_rmesh_times);
192+
exx_info.info_ri.exx_symmetry_realspace = inp.exx_symmetry_realspace;
193+
exx_info.info_ri.Cs_inv_thr = inp.exx_cs_inv_thr;
194+
exx_info.info_ri.shrink_abfs_pca_thr = inp.shrink_abfs_pca_thr;
195+
exx_info.info_ri.shrink_LU_inv_thr = inp.shrink_LU_inv_thr;
196+
exx_info.info_ri.coul_moment = inp.exx_coul_moment;
197+
exx_info.info_ri.rotate_abfs = inp.exx_rotate_abfs;
198+
exx_info.info_ri.multip_moments_threshold = inp.exx_multip_moments_threshold;
199+
exx_info.info_opt_abfs.pca_threshold = inp.exx_pca_threshold;
200+
exx_info.info_opt_abfs.abfs_Lmax = inp.exx_opt_orb_lmax;
201+
exx_info.info_opt_abfs.ecut_exx = inp.exx_opt_orb_ecut;
202+
exx_info.info_opt_abfs.tolerence = inp.exx_opt_orb_tolerence;
203+
204+
// Space-group symmetry is supported for LCAO EXX (nspin=1,2 via restore_dm/restore_HR;
205+
// nspin=4/SOC via restore_dm + restore_HR_nspin4), so symmetry=1 is honored here.
206+
207+
exx_info.sync_from_global();
208+
}
209+
210+
return generate_opt_orb;
211+
}

source/source_hamilt/module_xc/exx_info.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ struct Exx_Info
2121
}
2222
};
2323

24-
namespace GlobalC
25-
{
26-
extern Exx_Info exx_info;
27-
}
24+
/// Forward declaration for Input_para (full definition in input_parameter.h)
25+
struct Input_para;
26+
27+
/// Initialize an Exx_Info object from input parameters.
28+
/// Returns true if opt_orb mode is requested (generate_opt_orb).
29+
bool init_exx_info(Exx_Info& exx_info, const Input_para& inp);
2830

2931
#endif

source/source_hamilt/module_xc/libxc_mgga_wrap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#ifdef __LIBXC
66

7-
#include "source_hamilt/module_xc/exx_info.h" // use GlobalC::exx_info
7+
#include "source_hamilt/module_xc/exx_info.h" // for Exx_Info type
88
#include "source_hamilt/module_xc/xc_functional.h"
99
#include "libxc_abacus.h"
1010
#include <array>

source/source_hamilt/module_xc/libxc_setup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "source_base/formatter.h"
77

88
#ifdef __EXX
9-
#include "source_hamilt/module_xc/exx_info.h" // use GlobalC::exx_info
9+
#include "source_hamilt/module_xc/exx_info.h" // for Exx_Info type
1010
#endif
1111

1212
#include <xc.h>

source/source_hsolver/test/test_hsolver_pw.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include "hsolver_pw_sup.h"
1212
#include "hsolver_supplementary_mock.h"
1313
#include "source_base/global_variable.h"
14-
#include "source_hamilt/module_xc/exx_info.h" // use GlobalC::exx_info
14+
#include "source_hamilt/module_xc/exx_info.h" // for Exx_Info type
1515
#include "source_hsolver/hsolver_pw.h"
1616
#undef private
1717
#undef protected

source/source_io/module_ctrl/ctrl_iter_lcao.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "ctrl_iter_lcao.h" // use ctrl_iter_lcao()
22

33
#include "source_base/global_variable.h" // use GlobalC
4+
#include "source_hamilt/module_xc/exx_info.h"
45
#ifdef __MLALGO
56
#include "source_lcao/module_deepks/lcao_deepks.h"
67
#include "source_lcao/module_deepks/lcao_deepks_iface.h"
@@ -28,6 +29,7 @@ void ctrl_iter_lcao(UnitCell& ucell, // unit cell *
2829
LCAO_Orbitals &orb, // orbital info *
2930
Setup_DeePKS<TK> &deepks,
3031
Exx_NAO<TK> &exx_nao,
32+
const Exx_Info& exx_info,
3133
int &iter,
3234
const int istep,
3335
bool &conv_esolver,
@@ -47,8 +49,8 @@ void ctrl_iter_lcao(UnitCell& ucell, // unit cell *
4749
}
4850

4951
#ifdef __EXX
50-
bool cal_exx = GlobalC::exx_info.info_global.cal_exx;
51-
bool real_number = GlobalC::exx_info.info_ri.real_number;
52+
bool cal_exx = exx_info.info_global.cal_exx;
53+
bool real_number = exx_info.info_ri.real_number;
5254

5355
if (inp.calculation != "nscf")
5456
{
@@ -98,6 +100,7 @@ template void ctrl_iter_lcao<double, double>(UnitCell& ucell, // unit cell *
98100
LCAO_Orbitals &orb, // orbital info *
99101
Setup_DeePKS<double> &deepks,
100102
Exx_NAO<double> &exx_nao,
103+
const Exx_Info& exx_info,
101104
int &iter,
102105
const int istep,
103106
bool &conv_esolver,
@@ -118,6 +121,7 @@ template void ctrl_iter_lcao<std::complex<double>, double>(UnitCell& ucell, // u
118121
LCAO_Orbitals &orb, // orbital info *
119122
Setup_DeePKS<std::complex<double>> &deepks,
120123
Exx_NAO<std::complex<double>> &exx_nao,
124+
const Exx_Info& exx_info,
121125
int &iter,
122126
const int istep,
123127
bool &conv_esolver,
@@ -138,6 +142,7 @@ template void ctrl_iter_lcao<std::complex<double>, std::complex<double>>(UnitCel
138142
LCAO_Orbitals &orb, // orbital info *
139143
Setup_DeePKS<std::complex<double>> &deepks,
140144
Exx_NAO<std::complex<double>> &exx_nao,
145+
const Exx_Info& exx_info,
141146
int &iter,
142147
const int istep,
143148
bool &conv_esolver,

0 commit comments

Comments
 (0)