ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
Exx_LRI.hpp
Go to the documentation of this file.
1//=======================
2// AUTHOR : Peize Lin
4// DATE : 2022-08-17
5//=======================
6
7#ifndef EXX_LRI_HPP
8#define EXX_LRI_HPP
9
10#include "Exx_LRI.h"
11#include "RI_2D_Comm.h"
12#include "RI_Util.h"
17#include "source_base/timer.h"
21
22#include <RI/distribute/Distribute_Equally.h>
23#include <RI/global/Map_Operator-3.h>
24
25#include <fstream>
26#include <string>
27
28template<typename Tdata>
29void Exx_LRI<Tdata>::init(const MPI_Comm &mpi_comm_in,
30 const UnitCell &ucell,
31 const K_Vectors &kv_in,
32 const LCAO_Orbitals& orb)
33{
34 ModuleBase::TITLE("Exx_LRI","init");
35 ModuleBase::timer::tick("Exx_LRI", "init");
36
37 this->mpi_comm = mpi_comm_in;
38 this->p_kv = &kv_in;
39 this->orb_cutoff_ = orb.cutoffs();
40
41 this->lcaos = Exx_Abfs::Construct_Orbs::change_orbs( orb, this->info.kmesh_times );
43
44 const std::vector<std::vector<std::vector<Numerical_Orbital_Lm>>>
45 abfs_same_atom = Exx_Abfs::Construct_Orbs::abfs_same_atom(ucell, orb, this->lcaos, this->info.kmesh_times, this->info.pca_threshold );
46 if(this->info.files_abfs.empty())
47 { this->abfs = abfs_same_atom;}
48 else
49 { this->abfs = Exx_Abfs::IO::construct_abfs( abfs_same_atom, orb, this->info.files_abfs, this->info.kmesh_times ); }
52
53 this->coulomb_settings = RI_Util::update_coulomb_settings(this->info.coulomb_param, ucell, this->p_kv);
54
55 std::shared_ptr<ORB_gaunt_table> MGT = std::make_shared<ORB_gaunt_table>();
56 for(const auto &settings_list : this->coulomb_settings)
57 {
58 this->exx_objs[settings_list.first].abfs_ccp = Conv_Coulomb_Pot_K::cal_orbs_ccp(this->abfs, settings_list.second.second, this->info.ccp_rmesh_times);
59 this->exx_objs[settings_list.first].cv.set_orbitals(ucell, orb,
60 this->lcaos, this->abfs, this->exx_objs[settings_list.first].abfs_ccp,
61 this->info.kmesh_times, MGT, settings_list.second.first );
62 }
63
64 ModuleBase::timer::tick("Exx_LRI", "init");
65}
66
67template<typename Tdata>
69 const bool write_cv)
70{
71 ModuleBase::TITLE("Exx_LRI","cal_exx_ions");
72 ModuleBase::timer::tick("Exx_LRI", "cal_exx_ions");
73
74 std::vector<TA> atoms(ucell.nat);
75 for(int iat=0; iat<ucell.nat; ++iat)
76 { atoms[iat] = iat; }
77 std::map<TA,TatomR> atoms_pos;
78 for(int iat=0; iat<ucell.nat; ++iat)
79 { atoms_pos[iat] = RI_Util::Vector3_to_array3( ucell.atoms[ ucell.iat2it[iat] ].tau[ ucell.iat2ia[iat] ] ); }
80 const std::array<TatomR,Ndim> latvec
84 const std::array<Tcell,Ndim> period = {this->p_kv->nmp[0], this->p_kv->nmp[1], this->p_kv->nmp[2]};
85
86 this->exx_lri.set_parallel(this->mpi_comm, atoms_pos, latvec, period);
87
88 // std::max(3) for gamma_only, list_A2 should contain cell {-1,0,1}. In the future distribute will be neighbour.
89 const std::array<Tcell,Ndim> period_Vs = LRI_CV_Tools::cal_latvec_range<Tcell>(1+this->info.ccp_rmesh_times, ucell, orb_cutoff_);
90 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA,std::array<Tcell,Ndim>>>>>
91 list_As_Vs = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Vs, 2, false);
92
93 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>> Vs;
94 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, Ndim>>> dVs;
95 for(const auto &settings_list : this->coulomb_settings)
96 {
97 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>
98 Vs_temp = this->exx_objs[settings_list.first].cv.cal_Vs(ucell,
99 list_As_Vs.first, list_As_Vs.second[0],
100 {{"writable_Vws",true}});
101 this->exx_objs[settings_list.first].cv.Vws = LRI_CV_Tools::get_CVws(ucell,Vs_temp);
102 Vs = Vs.empty() ? Vs_temp : LRI_CV_Tools::add(Vs, Vs_temp);
103
105 {
106 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, Ndim>>>
107 dVs_temp = this->exx_objs[settings_list.first].cv.cal_dVs(ucell,
108 list_As_Vs.first, list_As_Vs.second[0],
109 {{"writable_dVws",true}});
110 this->exx_objs[settings_list.first].cv.dVws = LRI_CV_Tools::get_dCVws(ucell,dVs_temp);
111 dVs = dVs.empty() ? dVs_temp : LRI_CV_Tools::add(dVs, dVs_temp);
112 }
113 }
114 if (write_cv && GlobalV::MY_RANK == 0)
116 this->exx_lri.set_Vs(std::move(Vs), this->info.V_threshold);
117
119 {
120 std::array<std::map<TA, std::map<TAC, RI::Tensor<Tdata>>>, Ndim>
121 dVs_order = LRI_CV_Tools::change_order(std::move(dVs));
122 this->exx_lri.set_dVs(std::move(dVs_order), this->info.V_grad_threshold);
124 {
125 std::array<std::array<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,3>,3> dVRs = LRI_CV_Tools::cal_dMRs(ucell,dVs_order);
126 this->exx_lri.set_dVRs(std::move(dVRs), this->info.V_grad_R_threshold);
127 }
128 }
129
130 const std::array<Tcell,Ndim> period_Cs = LRI_CV_Tools::cal_latvec_range<Tcell>(2, ucell,orb_cutoff_);
131 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA,std::array<Tcell,Ndim>>>>>
132 list_As_Cs = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Cs, 2, false);
133
134 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>> Cs;
135 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, 3>>> dCs;
136 for(const auto &settings_list : this->coulomb_settings)
137 {
138 if(settings_list.second.first)
139 {
140 std::pair<std::map<TA, std::map<TAC, RI::Tensor<Tdata>>>,
141 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, 3>>>>
142 Cs_dCs = this->exx_objs[settings_list.first].cv.cal_Cs_dCs(
143 ucell,
144 list_As_Cs.first, list_As_Cs.second[0],
145 {{"cal_dC",PARAM.inp.cal_force||PARAM.inp.cal_stress},
146 {"writable_Cws",true}, {"writable_dCws",true}, {"writable_Vws",false}, {"writable_dVws",false}});
147 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>> &Cs_temp = std::get<0>(Cs_dCs);
148 this->exx_objs[settings_list.first].cv.Cws = LRI_CV_Tools::get_CVws(ucell,Cs_temp);
149 Cs = Cs.empty() ? Cs_temp : LRI_CV_Tools::add(Cs, Cs_temp);
150
152 {
153 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, 3>>> &dCs_temp = std::get<1>(Cs_dCs);
154 this->exx_objs[settings_list.first].cv.dCws = LRI_CV_Tools::get_dCVws(ucell,dCs_temp);
155 dCs = dCs.empty() ? dCs_temp : LRI_CV_Tools::add(dCs, dCs_temp);
156 }
157 }
158 }
159 if (write_cv && GlobalV::MY_RANK == 0)
161 this->exx_lri.set_Cs(std::move(Cs), this->info.C_threshold);
162
164 {
165 std::array<std::map<TA, std::map<TAC, RI::Tensor<Tdata>>>, Ndim>
166 dCs_order = LRI_CV_Tools::change_order(std::move(dCs));
167 this->exx_lri.set_dCs(std::move(dCs_order), this->info.C_grad_threshold);
169 {
170 std::array<std::array<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,3>,3> dCRs = LRI_CV_Tools::cal_dMRs(ucell,dCs_order);
171 this->exx_lri.set_dCRs(std::move(dCRs), this->info.C_grad_R_threshold);
172 }
173 }
174 ModuleBase::timer::tick("Exx_LRI", "cal_exx_ions");
175}
176
177template<typename Tdata>
178void Exx_LRI<Tdata>::cal_exx_elec(const std::vector<std::map<TA, std::map<TAC, RI::Tensor<Tdata>>>>& Ds,
179 const UnitCell& ucell,
180 const Parallel_Orbitals& pv,
181 const ModuleSymmetry::Symmetry_rotation* p_symrot)
182{
183 ModuleBase::TITLE("Exx_LRI","cal_exx_elec");
184 ModuleBase::timer::tick("Exx_LRI", "cal_exx_elec");
185
186 const std::vector<std::tuple<std::set<TA>, std::set<TA>>> judge = RI_2D_Comm::get_2D_judge(ucell,pv);
187
188 if(p_symrot)
189 { this->exx_lri.set_symmetry(true, p_symrot->get_irreducible_sector()); }
190 else
191 { this->exx_lri.set_symmetry(false, {}); }
192
193 this->Hexxs.resize(PARAM.inp.nspin);
194 this->Eexx = 0;
195 for(int is=0; is<PARAM.inp.nspin; ++is)
196 {
197 const std::string suffix = ((PARAM.inp.cal_force || PARAM.inp.cal_stress) ? std::to_string(is) : "");
198
199 this->exx_lri.set_Ds(Ds[is], this->info.dm_threshold, suffix);
200 this->exx_lri.cal_Hs({ "","",suffix });
201
202 if (!p_symrot)
203 {
204 this->Hexxs[is] = RI::Communicate_Tensors_Map_Judge::comm_map2_first(
205 this->mpi_comm, std::move(this->exx_lri.Hs), std::get<0>(judge[is]), std::get<1>(judge[is]));
206 }
207 else
208 {
209 // reduce but not repeat
210 auto Hs_a2D = this->exx_lri.post_2D.set_tensors_map2(this->exx_lri.Hs);
211 // rotate locally without repeat
212 Hs_a2D = p_symrot->restore_HR(ucell.symm, ucell.atoms, ucell.st, 'H', Hs_a2D);
213 // cal energy using full Hs without repeat
214 this->exx_lri.energy = this->exx_lri.post_2D.cal_energy(
215 this->exx_lri.post_2D.saves["Ds_" + suffix],
216 this->exx_lri.post_2D.set_tensors_map2(Hs_a2D));
217 // get repeated full Hs for abacus
218 this->Hexxs[is] = RI::Communicate_Tensors_Map_Judge::comm_map2_first(
219 this->mpi_comm, std::move(Hs_a2D), std::get<0>(judge[is]), std::get<1>(judge[is]));
220 }
221 this->Eexx += std::real(this->exx_lri.energy);
222 post_process_Hexx(this->Hexxs[is]);
223 }
224 this->Eexx = post_process_Eexx(this->Eexx);
225 this->exx_lri.set_symmetry(false, {});
226 ModuleBase::timer::tick("Exx_LRI", "cal_exx_elec");
227}
228
229template<typename Tdata>
230void Exx_LRI<Tdata>::post_process_Hexx( std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> &Hexxs_io ) const
231{
232 ModuleBase::TITLE("Exx_LRI","post_process_Hexx");
233 constexpr Tdata frac = -1 * 2; // why? Hartree to Ry?
234 const std::function<void(RI::Tensor<Tdata>&)>
235 multiply_frac = [&frac](RI::Tensor<Tdata> &t)
236 { t = t*frac; };
237 RI::Map_Operator::for_each( Hexxs_io, multiply_frac );
238}
239
240template<typename Tdata>
241double Exx_LRI<Tdata>::post_process_Eexx(const double& Eexx_in) const
242{
243 ModuleBase::TITLE("Exx_LRI","post_process_Eexx");
244 const double SPIN_multiple = std::map<int, double>{ {1,2}, {2,1}, {4,1} }.at(PARAM.inp.nspin); // why?
245 const double frac = -SPIN_multiple;
246 return frac * Eexx_in;
247}
248
249/*
250post_process_old
251{
252 // D
253 const std::map<int,double> SPIN_multiple = {{1,0.5}, {2,1}, {4,1}}; // ???
254 DR *= SPIN_multiple.at(NSPIN);
255
256 // H
257 HR *= -2;
258
259 // E
260 const std::map<int,double> SPIN_multiple = {{1,2}, {2,1}, {4,1}}; // ???
261 energy *= SPIN_multiple.at(PARAM.inp.nspin); // ?
262 energy /= 2; // /2 for Ry
263}
264*/
265
266template<typename Tdata>
268{
269 ModuleBase::TITLE("Exx_LRI","cal_exx_force");
270 ModuleBase::timer::tick("Exx_LRI", "cal_exx_force");
271
272 this->force_exx.create(nat, Ndim);
273 for(int is=0; is<PARAM.inp.nspin; ++is)
274 {
275 this->exx_lri.cal_force({"","",std::to_string(is),"",""});
276 for(std::size_t idim=0; idim<Ndim; ++idim) {
277 for(const auto &force_item : this->exx_lri.force[idim]) {
278 this->force_exx(force_item.first, idim) += std::real(force_item.second);
279 } }
280 }
281
282 const double SPIN_multiple = std::map<int,double>{{1,2}, {2,1}, {4,1}}.at(PARAM.inp.nspin); // why?
283 const double frac = -2 * SPIN_multiple; // why?
284 this->force_exx *= frac;
285 ModuleBase::timer::tick("Exx_LRI", "cal_exx_force");
286}
287
288
289template<typename Tdata>
290void Exx_LRI<Tdata>::cal_exx_stress(const double& omega, const double& lat0)
291{
292 ModuleBase::TITLE("Exx_LRI","cal_exx_stress");
293 ModuleBase::timer::tick("Exx_LRI", "cal_exx_stress");
294
295 this->stress_exx.create(Ndim, Ndim);
296 for(int is=0; is<PARAM.inp.nspin; ++is)
297 {
298 this->exx_lri.cal_stress({"","",std::to_string(is),"",""});
299 for(std::size_t idim0=0; idim0<Ndim; ++idim0) {
300 for(std::size_t idim1=0; idim1<Ndim; ++idim1) {
301 this->stress_exx(idim0,idim1) += std::real(this->exx_lri.stress(idim0,idim1));
302 } }
303 }
304
305 const double SPIN_multiple = std::map<int,double>{{1,2}, {2,1}, {4,1}}.at(PARAM.inp.nspin); // why?
306 const double frac = 2 * SPIN_multiple / omega * lat0; // why?
307 this->stress_exx *= frac;
308
309 ModuleBase::timer::tick("Exx_LRI", "cal_exx_stress");
310}
311
312/*
313template<typename Tdata>
314std::vector<std::vector<int>> Exx_LRI<Tdata>::get_abfs_nchis() const
315{
316 std::vector<std::vector<int>> abfs_nchis;
317 for (const auto& abfs_T : this->abfs)
318 {
319 std::vector<int> abfs_nchi_T;
320 for (const auto& abfs_L : abfs_T)
321 { abfs_nchi_T.push_back(abfs_L.size()); }
322 abfs_nchis.push_back(abfs_nchi_T);
323 }
324 return abfs_nchis;
325}
326*/
327
328#endif
std::vector< ModuleBase::Vector3< double > > tau
Definition atom_spec.h:36
static void print_orbs_size(const UnitCell &ucell, const std::vector< std::vector< std::vector< Numerical_Orbital_Lm > > > &orbs, std::ostream &os)
Definition exx_abfs-construct_orbs.cpp:476
static void filter_empty_orbs(std::vector< std::vector< std::vector< Numerical_Orbital_Lm > > > &orbs)
Definition exx_abfs-construct_orbs.cpp:546
static std::vector< std::vector< std::vector< Numerical_Orbital_Lm > > > abfs_same_atom(const UnitCell &ucell, const LCAO_Orbitals &orb, const std::vector< std::vector< std::vector< Numerical_Orbital_Lm > > > &lcaos, const double kmesh_times_mot, const double times_threshold=0)
Definition exx_abfs-construct_orbs.cpp:81
static std::vector< std::vector< std::vector< Numerical_Orbital_Lm > > > change_orbs(const LCAO_Orbitals &orb_in, const double kmesh_times)
Definition exx_abfs-construct_orbs.cpp:11
static std::vector< std::vector< std::vector< Numerical_Orbital_Lm > > > construct_abfs(const LCAO_Orbitals &orbs, const std::vector< std::string > &files_abfs, const double kmesh_times=1)
Definition exx_abfs-io.cpp:13
void post_process_Hexx(std::map< TA, std::map< TAC, RI::Tensor< Tdata > > > &Hexxs_io) const
Definition Exx_LRI.hpp:230
void init(const MPI_Comm &mpi_comm_in, const UnitCell &ucell, const K_Vectors &kv_in, const LCAO_Orbitals &orb)
Definition Exx_LRI.hpp:29
void cal_exx_elec(const std::vector< std::map< TA, std::map< TAC, RI::Tensor< Tdata > > > > &Ds, const UnitCell &ucell, const Parallel_Orbitals &pv, const ModuleSymmetry::Symmetry_rotation *p_symrot=nullptr)
Definition Exx_LRI.hpp:178
double post_process_Eexx(const double &Eexx_in) const
Definition Exx_LRI.hpp:241
std::pair< TA, TC > TAC
Definition Exx_LRI.h:57
int TA
Definition Exx_LRI.h:53
void cal_exx_ions(const UnitCell &ucell, const bool write_cv=false)
Definition Exx_LRI.hpp:68
void cal_exx_force(const int &nat)
Definition Exx_LRI.hpp:267
void cal_exx_stress(const double &omega, const double &lat0)
Definition Exx_LRI.hpp:290
Definition klist.h:13
Definition ORB_read.h:19
std::vector< double > cutoffs() const
Definition ORB_read.cpp:40
static void tick(const std::string &class_name_in, const std::string &name_in)
Use twice at a time: the first time, set start_flag to false; the second time, calculate the time dur...
Definition timer.cpp:62
Definition symmetry_rotation.h:16
std::map< int, std::map< std::pair< int, TC >, RI::Tensor< Tdata > > > restore_HR(const Symmetry &symm, const Atom *atoms, const Statistics &st, const char mode, const std::map< int, std::map< std::pair< int, TC >, RI::Tensor< Tdata > > > &HR_irreduceble) const
Definition symmetry_rotation_R.hpp:40
const std::map< Tap, std::set< TC > > & get_irreducible_sector() const
Definition symmetry_rotation.h:23
Definition parallel_orbitals.h:9
const Input_para & inp
Definition parameter.h:26
const System_para & globalv
Definition parameter.h:30
Definition unitcell.h:17
int *& iat2it
Definition unitcell.h:49
Atom * atoms
Definition unitcell.h:19
ModuleSymmetry::Symmetry symm
Definition unitcell.h:57
int & nat
Definition unitcell.h:48
ModuleBase::Vector3< double > & a2
Definition unitcell.h:38
ModuleBase::Vector3< double > & a3
Definition unitcell.h:38
int *& iat2ia
Definition unitcell.h:50
ModuleBase::Vector3< double > & a1
Definition unitcell.h:38
Statistics st
Definition unitcell.h:46
T cal_orbs_ccp(const T &orbs, const std::map< Conv_Coulomb_Pot_K::Coulomb_Type, std::vector< std::map< std::string, std::string > > > &coulomb_param, const double rmesh_times)
int MY_RANK
global index of process
Definition global_variable.cpp:21
std::ofstream ofs_running
Definition global_variable.cpp:38
std::vector< std::array< T, N > > add(const std::vector< std::array< T, N > > &v1, const std::vector< std::array< T, N > > &v2)
Definition LRI_CV_Tools.hpp:223
std::map< int, std::map< int, std::map< Abfs::Vector3_Order< double >, RI::Tensor< Tdata > > > > get_CVws(const UnitCell &ucell, const std::map< TA, std::map< std::pair< TA, std::array< Tcell, 3 > >, RI::Tensor< Tdata > > > &CVs)
Definition LRI_CV_Tools.hpp:386
std::array< std::vector< T >, N > change_order(std::vector< std::array< T, N > > &&ds_in)
Definition LRI_CV_Tools.hpp:306
std::map< int, std::map< int, std::map< Abfs::Vector3_Order< double >, std::array< RI::Tensor< Tdata >, 3 > > > > get_dCVws(const UnitCell &ucell, const std::map< TA, std::map< std::pair< TA, std::array< Tcell, 3 > >, std::array< RI::Tensor< Tdata >, 3 > > > &dCVs)
Definition LRI_CV_Tools.hpp:413
void write_Cs_ao(const TLRI< T > &Vs, const std::string &file_path)
Definition write_ri_cv.hpp:50
std::array< std::array< std::map< TA, std::map< std::pair< TA, TC >, RI::Tensor< Tdata > > >, 3 >, 3 > cal_dMRs(const UnitCell &ucell, const std::array< std::map< TA, std::map< std::pair< TA, TC >, RI::Tensor< Tdata > > >, 3 > &dMs)
Definition LRI_CV_Tools.hpp:524
void write_Vs_abf(const TLRI< T > &Vs, const std::string &file_path)
Definition write_ri_cv.hpp:105
void TITLE(const std::string &class_name, const std::string &function_name, const bool disable)
Definition tool_title.cpp:18
std::vector< std::tuple< std::set< TA >, std::set< TA > > > get_2D_judge(const UnitCell &ucell, const Parallel_2D &pv)
Definition RI_2D_Comm.cpp:15
std::array< Tcell, 3 > Vector3_to_array3(const ModuleBase::Vector3< Tcell > &v)
Definition RI_Util.h:32
std::map< Conv_Coulomb_Pot_K::Coulomb_Method, std::pair< bool, std::map< Conv_Coulomb_Pot_K::Coulomb_Type, std::vector< std::map< std::string, std::string > > > > > update_coulomb_settings(const std::map< Conv_Coulomb_Pot_K::Coulomb_Type, std::vector< std::map< std::string, std::string > > > &coulomb_param, const UnitCell &ucell, const K_Vectors *p_kv)
Definition RI_Util.hpp:105
Parameter PARAM
Definition parameter.cpp:3
bool cal_force
calculate the force
Definition input_parameter.h:32
int nspin
LDA ; LSDA ; non-linear spin.
Definition input_parameter.h:85
bool cal_stress
calculate the stress
Definition input_parameter.h:33
std::string global_out_dir
global output directory
Definition system_parameter.h:42