ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
hamilt_casida.h
Go to the documentation of this file.
1#pragma once
2#include <typeinfo>
9#ifdef __EXX
13#endif
14namespace LR
15{
16 template<typename T>
18 {
19 public:
20 HamiltLR(std::string& xc_kernel,
21 const int& nspin,
22 const int& naos,
23 const std::vector<int>& nocc,
24 const std::vector<int>& nvirt,
25 const UnitCell& ucell_in,
26 const std::vector<double>& orb_cutoff,
27 const Grid_Driver& gd_in,
28 const psi::Psi<T>& psi_ks_in,
29 const ModuleBase::matrix& eig_ks,
30#ifdef __EXX
31 std::weak_ptr<Exx_LRI<T>> exx_lri_in,
32 const double& exx_alpha,
33#endif
34 std::weak_ptr<PotHxcLR> pot_in,
35 const K_Vectors& kv_in,
36 const std::vector<Parallel_2D>& pX_in,
37 const Parallel_2D& pc_in,
38 const Parallel_Orbitals& pmat_in,
39 const std::string& spin_type,
40 const std::string& ri_hartree_benchmark = "none",
41 const std::vector<int>& aims_nbasis = {})
42 : nspin(nspin), nocc(nocc), nvirt(nvirt), pX(pX_in), nk(kv_in.get_nks() / nspin)
43 {
44 ModuleBase::TITLE("HamiltLR", "HamiltLR");
45 if (ri_hartree_benchmark != "aims") { assert(aims_nbasis.empty()); }
46 // always use nspin=1 for transition density matrix
47 this->DM_trans = LR_Util::make_unique<elecstate::DensityMatrix<T, T>>(&pmat_in, 1, kv_in.kvec_d, nk);
48 if (ri_hartree_benchmark == "none") { LR_Util::initialize_DMR(*this->DM_trans, pmat_in, ucell_in, gd_in, orb_cutoff); }
49 // this->DM_trans->init_DMR(&gd_in, &ucell_in); // too large due to not restricted by orb_cutoff
50
51 // add the diag operator (the first one)
52 this->ops = new OperatorLRDiag<T>(eig_ks.c, pX[0], nk, nocc[0], nvirt[0]);
53 //add Hxc operator
54#ifdef __EXX
55 using TAC = std::pair<int, std::array<int, 3>>;
56 using TLRI = std::map<int, std::map<TAC, RI::Tensor<T>>>;
57 const std::string& dir = PARAM.globalv.global_readin_dir;
58 TLRI Cs_read;
59 TLRI Vs_read;
60#ifdef __DEBUG
61 // TLRI Vs_compare = LRI_CV_Tools::read_Vs_abf<T>(dir + "Vs");
62 // LRI_CV_Tools::write_Vs_abf(Vs_read, "Vs_read_from_coulomb");
63 // LRI_CV_Tools::write_Cs_ao(Cs_read, "Cs_ao_read"); // ensure Cs_ao is read correctly
64 // assert(RI_Benchmark::compare_Vs(Vs_read, Vs_compare));
65#endif
66 if (ri_hartree_benchmark != "none")
67 {
68#ifdef __EXX
69 if (spin_type == "singlet")
70 {
71 if (ri_hartree_benchmark == "aims")
72 {
73 Cs_read = LRI_CV_Tools::read_Cs_ao<T>(dir + "Cs_data_0.txt");
74 Vs_read = RI_Benchmark::read_coulomb_mat_general<T>(dir + "coulomb_mat_0.txt", Cs_read);
75 }
76 else if (ri_hartree_benchmark == "abacus")
77 {
78 Cs_read = LRI_CV_Tools::read_Cs_ao<T>(dir + "Cs");
79 Vs_read = LRI_CV_Tools::read_Vs_abf<T>(dir + "Vs");
80 }
81 if (!std::set<std::string>({ "rpa", "hf" }).count(xc_kernel)) { throw std::runtime_error("ri_hartree_benchmark is only supported for xc_kernel rpa and hf"); }
83 = new RI_Benchmark::OperatorRIHartree<T>(ucell_in, naos, nocc[0], nvirt[0], psi_ks_in,
84 Cs_read, Vs_read, ri_hartree_benchmark == "aims", aims_nbasis);
85 this->ops->add(ri_hartree_op);
86 }
87 else if (spin_type == "triplet") { std::cout << "f_Hxc based on grid integral is not needed." << std::endl; }
88#else
89 ModuleBase::WARNING_QUIT("ESolver_LR", "RI benchmark is only supported when compile with LibRI.");
90#endif
91 }
92 else
93#endif
94 {
95 OperatorLRHxc<T>* lr_hxc = new OperatorLRHxc<T>(nspin, naos, nocc, nvirt, psi_ks_in,
96 this->DM_trans, pot_in, ucell_in, orb_cutoff, gd_in, kv_in, pX_in, pc_in, pmat_in);
97 this->ops->add(lr_hxc);
98 }
99#ifdef __EXX
100 if (xc_kernel == "hf" || xc_kernel == "hse")
101 { //add Exx operator
102 if (ri_hartree_benchmark != "none" && spin_type == "singlet")
103 {
104 exx_lri_in.lock()->reset_Cs(Cs_read);
105 exx_lri_in.lock()->reset_Vs(Vs_read);
106 }
107 // std::cout << "exx_alpha=" << exx_alpha << std::endl; // the default value of exx_alpha is 0.25 when dft_functional is pbe or hse
108 hamilt::Operator<T>* lr_exx = new OperatorLREXX<T>(nspin, naos, nocc[0], nvirt[0], ucell_in, psi_ks_in,
109 this->DM_trans, exx_lri_in, kv_in, pX_in[0], pc_in, pmat_in,
110 xc_kernel == "hf" ? 1.0 : exx_alpha, //alpha
111 aims_nbasis);
112 this->ops->add(lr_exx);
113 }
114#endif
115
116 this->cal_dm_trans = [&, this](const int& is, const T* const X)->void
117 {
118 const auto psi_ks_is = LR_Util::get_psi_spin(psi_ks_in, is, nk);
119#ifdef __MPI
120 std::vector<ct::Tensor> dm_trans_2d = cal_dm_trans_pblas(X, pX[is], psi_ks_is, pc_in, naos, nocc[is], nvirt[is], pmat_in, (T)1.0 / (T)nk);
121 if (this->tdm_sym) for (auto& t : dm_trans_2d) LR_Util::matsym(t.data<T>(), naos, pmat_in);
122#else
123 std::vector<ct::Tensor> dm_trans_2d = cal_dm_trans_blas(X, psi_ks_is, nocc[is], nvirt[is], (T)1.0 / (T)nk);
124 if (this->tdm_sym) for (auto& t : dm_trans_2d) LR_Util::matsym(t.data<T>(), naos);
125#endif
126 // LR_Util::print_tensor<T>(dm_trans_2d[0], "dm_trans_2d[0]", &pmat_in);
127 // tensor to vector, then set DMK
128 for (int ik = 0;ik < nk;++ik) { this->DM_trans->set_DMK_pointer(ik, dm_trans_2d[ik].data<T>()); }
129 };
130 }
131 ~HamiltLR() { delete this->ops; }
132
133 std::vector<T> matrix()const;
134
135 void hPsi(const T* const psi_in, T* const hpsi, const int ld_psi, const int& nband) const
136 {
137 assert(ld_psi == nk * pX[0].get_local_size());
138 for (int ib = 0;ib < nband;++ib)
139 {
140 const int offset = ib * ld_psi;
141 this->cal_dm_trans(0, psi_in + offset); // calculate transition density matrix here
142 hamilt::Operator<T>* node(this->ops);
143 while (node != nullptr)
144 {
145 node->act(/*nband=*/1, ld_psi, /*npol=*/1, psi_in + offset, hpsi + offset);
146 node = (hamilt::Operator<T>*)(node->next_op);
147 }
148 }
149 }
150
151 void global2local(T* lvec, const T* gvec, const int& nband) const
152 {
153 const int npairs = nocc[0] * nvirt[0];
154 for (int ib = 0;ib < nband;++ib)
155 {
156 const int loffset_b = ib * nk * pX[0].get_local_size();
157 const int goffset_b = ib * nk * npairs;
158 for (int ik = 0;ik < nk;++ik)
159 {
160 const int loffset = loffset_b + ik * pX[0].get_local_size();
161 const int goffset = goffset_b + ik * npairs;
162 for (int lo = 0;lo < pX[0].get_col_size();++lo)
163 {
164 const int go = pX[0].local2global_col(lo);
165 for (int lv = 0;lv < pX[0].get_row_size();++lv)
166 {
167 const int gv = pX[0].local2global_row(lv);
168 lvec[loffset + lo * pX[0].get_row_size() + lv] = gvec[goffset + go * nvirt[0] + gv];
169 }
170 }
171 }
172 }
173 }
174
175 private:
176 const std::vector<int>& nocc;
177 const std::vector<int>& nvirt;
178 const int nspin = 1;
179 const int nk = 1;
180 const bool tdm_sym = false;
181 const std::vector<Parallel_2D>& pX;
182 T one()const;
185 std::unique_ptr<elecstate::DensityMatrix<T, T>> DM_trans;
186
189
190 std::function<void(const int&, const T* const)> cal_dm_trans;
191 };
192}
Definition Exx_LRI.h:51
Definition sltk_grid_driver.h:43
Definition klist.h:13
std::vector< ModuleBase::Vector3< double > > kvec_d
Cartesian coordinates of k points.
Definition klist.h:16
Definition hamilt_casida.h:18
const int nk
Definition hamilt_casida.h:179
~HamiltLR()
Definition hamilt_casida.h:131
void hPsi(const T *const psi_in, T *const hpsi, const int ld_psi, const int &nband) const
Definition hamilt_casida.h:135
HamiltLR(std::string &xc_kernel, const int &nspin, const int &naos, const std::vector< int > &nocc, const std::vector< int > &nvirt, const UnitCell &ucell_in, const std::vector< double > &orb_cutoff, const Grid_Driver &gd_in, const psi::Psi< T > &psi_ks_in, const ModuleBase::matrix &eig_ks, std::weak_ptr< PotHxcLR > pot_in, const K_Vectors &kv_in, const std::vector< Parallel_2D > &pX_in, const Parallel_2D &pc_in, const Parallel_Orbitals &pmat_in, const std::string &spin_type, const std::string &ri_hartree_benchmark="none", const std::vector< int > &aims_nbasis={})
Definition hamilt_casida.h:20
std::function< void(const int &, const T *const)> cal_dm_trans
Definition hamilt_casida.h:190
const int nspin
Definition hamilt_casida.h:178
void global2local(T *lvec, const T *gvec, const int &nband) const
Definition hamilt_casida.h:151
const std::vector< Parallel_2D > & pX
Definition hamilt_casida.h:181
const std::vector< int > & nocc
Definition hamilt_casida.h:176
const bool tdm_sym
whether to symmetrize the transition density matrix
Definition hamilt_casida.h:180
std::vector< T > matrix() const
Definition hamilt_casida.cpp:6
hamilt::Operator< T, base_device::DEVICE_CPU > * ops
first node operator, add operations from each operators
Definition hamilt_casida.h:188
std::unique_ptr< elecstate::DensityMatrix< T, T > > DM_trans
Definition hamilt_casida.h:185
const std::vector< int > & nvirt
Definition hamilt_casida.h:177
T one() const
Definition matrix.h:19
double * c
Definition matrix.h:25
This class packs the basic information of 2D-block-cyclic parallel distribution of an arbitrary matri...
Definition parallel_2d.h:12
Definition parallel_orbitals.h:9
const System_para & globalv
Definition parameter.h:30
Definition operator_ri_hartree.h:9
Definition unitcell.h:17
Definition operator.h:38
Operator * next_op
interface type 3: return a Psi-type HPsi
Definition operator.h:84
virtual void add(Operator *next)
virtual void act(const int nbands, const int nbasis, const int npol, const T *tmpsi_in, T *tmhpsi, const int ngk_ik=0, const bool is_first_node=false) const
Definition operator.h:66
Definition psi.h:37
#define T
Definition exp.cpp:237
Definition lr_util.cpp:6
psi::Psi< T > get_psi_spin(const psi::Psi< T > &psi_in, const int &is, const int &nk)
get the Psi wrapper of the selected spin from the Psi object
Definition lr_util.hpp:100
void matsym(const T *in, const int n, T *out)
Definition lr_util.hpp:70
void initialize_DMR(elecstate::DensityMatrix< T, TR > &dm, const Parallel_Orbitals &pmat, const UnitCell &ucell, const Grid_Driver &gd, const std::vector< double > &orb_cutoff)
Definition lr_util_hcontainer.h:81
Definition esolver_ks_lcao.h:19
std::vector< container::Tensor > cal_dm_trans_pblas(const T *const X_istate, const Parallel_2D &px, const psi::Psi< T > &c, const Parallel_2D &pc, const int naos, const int nocc, const int nvirt, const Parallel_2D &pmat, const T factor=(T) 1.0, const MO_TYPE type=MO_TYPE::VO)
calculate the 2d-block transition density matrix in AO basis using p?gemm
std::vector< container::Tensor > cal_dm_trans_blas(const T *const X_istate, const psi::Psi< T > &c, const int &nocc, const int &nvirt, const T factor=(T) 1.0, const MO_TYPE type=MO_TYPE::VO)
calculate the 2d-block transition density matrix in AO basis using ?gemm
void WARNING_QUIT(const std::string &, const std::string &)
Combine the functions of WARNING and QUIT.
Definition test_delley.cpp:14
void TITLE(const std::string &class_name, const std::string &function_name, const bool disable)
Definition tool_title.cpp:18
Parameter PARAM
Definition parameter.cpp:3
std::pair< int, TC > TAC
Definition ri_cv_io_test.cpp:10
std::map< int, std::map< TAC, RI::Tensor< T > > > TLRI
Definition ri_cv_io_test.cpp:12
base device SOURCES math_hegvd_test cpp endif() if(ENABLE_GOOGLEBENCH) AddTest(TARGET PERF_MODULE_HSOLVER_KERNELS LIBS parameter $
Definition CMakeLists.txt:10
std::string global_readin_dir
global readin directory
Definition system_parameter.h:43