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+ }
0 commit comments