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 template <typename TGint>
21 HamiltLR(std::string& xc_kernel,
22 const int& nspin,
23 const int& naos,
24 const std::vector<int>& nocc,
25 const std::vector<int>& nvirt,
26 const UnitCell& ucell_in,
27 const std::vector<double>& orb_cutoff,
28 const Grid_Driver& gd_in,
29 const psi::Psi<T>& psi_ks_in,
30 const ModuleBase::matrix& eig_ks,
31#ifdef __EXX
32 std::weak_ptr<Exx_LRI<T>> exx_lri_in,
33 const double& exx_alpha,
34#endif
35 TGint* gint_in,
36 std::weak_ptr<PotHxcLR> pot_in,
37 const K_Vectors& kv_in,
38 const std::vector<Parallel_2D>& pX_in,
39 const Parallel_2D& pc_in,
40 const Parallel_Orbitals& pmat_in,
41 const std::string& spin_type,
42 const std::string& ri_hartree_benchmark = "none",
43 const std::vector<int>& aims_nbasis = {})
44 : nspin(nspin), nocc(nocc), nvirt(nvirt), pX(pX_in), nk(kv_in.get_nks() / nspin)
45 {
46 ModuleBase::TITLE("HamiltLR", "HamiltLR");
47 if (ri_hartree_benchmark != "aims") { assert(aims_nbasis.empty()); }
48 // always use nspin=1 for transition density matrix
49 this->DM_trans = LR_Util::make_unique<elecstate::DensityMatrix<T, T>>(&pmat_in, 1, kv_in.kvec_d, nk);
50 if (ri_hartree_benchmark == "none") { LR_Util::initialize_DMR(*this->DM_trans, pmat_in, ucell_in, gd_in, orb_cutoff); }
51 // this->DM_trans->init_DMR(&gd_in, &ucell_in); // too large due to not restricted by orb_cutoff
52
53 // add the diag operator (the first one)
54 this->ops = new OperatorLRDiag<T>(eig_ks.c, pX[0], nk, nocc[0], nvirt[0]);
55 //add Hxc operator
56#ifdef __EXX
57 using TAC = std::pair<int, std::array<int, 3>>;
58 using TLRI = std::map<int, std::map<TAC, RI::Tensor<T>>>;
59 const std::string& dir = PARAM.globalv.global_readin_dir;
60 TLRI Cs_read;
61 TLRI Vs_read;
62#ifdef __DEBUG
63 // TLRI Vs_compare = LRI_CV_Tools::read_Vs_abf<T>(dir + "Vs");
64 // LRI_CV_Tools::write_Vs_abf(Vs_read, "Vs_read_from_coulomb");
65 // LRI_CV_Tools::write_Cs_ao(Cs_read, "Cs_ao_read"); // ensure Cs_ao is read correctly
66 // assert(RI_Benchmark::compare_Vs(Vs_read, Vs_compare));
67#endif
68 if (ri_hartree_benchmark != "none")
69 {
70#ifdef __EXX
71 if (spin_type == "singlet")
72 {
73 if (ri_hartree_benchmark == "aims")
74 {
75 Cs_read = LRI_CV_Tools::read_Cs_ao<T>(dir + "Cs_data_0.txt");
76 Vs_read = RI_Benchmark::read_coulomb_mat_general<T>(dir + "coulomb_mat_0.txt", Cs_read);
77 }
78 else if (ri_hartree_benchmark == "abacus")
79 {
80 Cs_read = LRI_CV_Tools::read_Cs_ao<T>(dir + "Cs");
81 Vs_read = LRI_CV_Tools::read_Vs_abf<T>(dir + "Vs");
82 }
83 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"); }
85 = new RI_Benchmark::OperatorRIHartree<T>(ucell_in, naos, nocc[0], nvirt[0], psi_ks_in,
86 Cs_read, Vs_read, ri_hartree_benchmark == "aims", aims_nbasis);
87 this->ops->add(ri_hartree_op);
88 }
89 else if (spin_type == "triplet") { std::cout << "f_Hxc based on grid integral is not needed." << std::endl; }
90#else
91 ModuleBase::WARNING_QUIT("ESolver_LR", "RI benchmark is only supported when compile with LibRI.");
92#endif
93 }
94 else
95#endif
96 {
97 OperatorLRHxc<T>* lr_hxc = new OperatorLRHxc<T>(nspin, naos, nocc, nvirt, psi_ks_in,
98 this->DM_trans, gint_in, pot_in, ucell_in, orb_cutoff, gd_in, kv_in, pX_in, pc_in, pmat_in);
99 this->ops->add(lr_hxc);
100 }
101#ifdef __EXX
102 if (xc_kernel == "hf" || xc_kernel == "hse")
103 { //add Exx operator
104 if (ri_hartree_benchmark != "none" && spin_type == "singlet")
105 {
106 exx_lri_in.lock()->reset_Cs(Cs_read);
107 exx_lri_in.lock()->reset_Vs(Vs_read);
108 }
109 // std::cout << "exx_alpha=" << exx_alpha << std::endl; // the default value of exx_alpha is 0.25 when dft_functional is pbe or hse
110 hamilt::Operator<T>* lr_exx = new OperatorLREXX<T>(nspin, naos, nocc[0], nvirt[0], ucell_in, psi_ks_in,
111 this->DM_trans, exx_lri_in, kv_in, pX_in[0], pc_in, pmat_in,
112 xc_kernel == "hf" ? 1.0 : exx_alpha, //alpha
113 aims_nbasis);
114 this->ops->add(lr_exx);
115 }
116#endif
117
118 this->cal_dm_trans = [&, this](const int& is, const T* const X)->void
119 {
120 const auto psi_ks_is = LR_Util::get_psi_spin(psi_ks_in, is, nk);
121#ifdef __MPI
122 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);
123 if (this->tdm_sym) for (auto& t : dm_trans_2d) LR_Util::matsym(t.data<T>(), naos, pmat_in);
124#else
125 std::vector<ct::Tensor> dm_trans_2d = cal_dm_trans_blas(X, psi_ks_is, nocc[is], nvirt[is], (T)1.0 / (T)nk);
126 if (this->tdm_sym) for (auto& t : dm_trans_2d) LR_Util::matsym(t.data<T>(), naos);
127#endif
128 // LR_Util::print_tensor<T>(dm_trans_2d[0], "dm_trans_2d[0]", &pmat_in);
129 // tensor to vector, then set DMK
130 for (int ik = 0;ik < nk;++ik) { this->DM_trans->set_DMK_pointer(ik, dm_trans_2d[ik].data<T>()); }
131 };
132 }
133 ~HamiltLR() { delete this->ops; }
134
135 std::vector<T> matrix()const;
136
137 void hPsi(const T* const psi_in, T* const hpsi, const int ld_psi, const int& nband) const
138 {
139 assert(ld_psi == nk * pX[0].get_local_size());
140 for (int ib = 0;ib < nband;++ib)
141 {
142 const int offset = ib * ld_psi;
143 this->cal_dm_trans(0, psi_in + offset); // calculate transition density matrix here
144 hamilt::Operator<T>* node(this->ops);
145 while (node != nullptr)
146 {
147 node->act(/*nband=*/1, ld_psi, /*npol=*/1, psi_in + offset, hpsi + offset);
148 node = (hamilt::Operator<T>*)(node->next_op);
149 }
150 }
151 }
152
153 void global2local(T* lvec, const T* gvec, const int& nband) const
154 {
155 const int npairs = nocc[0] * nvirt[0];
156 for (int ib = 0;ib < nband;++ib)
157 {
158 const int loffset_b = ib * nk * pX[0].get_local_size();
159 const int goffset_b = ib * nk * npairs;
160 for (int ik = 0;ik < nk;++ik)
161 {
162 const int loffset = loffset_b + ik * pX[0].get_local_size();
163 const int goffset = goffset_b + ik * npairs;
164 for (int lo = 0;lo < pX[0].get_col_size();++lo)
165 {
166 const int go = pX[0].local2global_col(lo);
167 for (int lv = 0;lv < pX[0].get_row_size();++lv)
168 {
169 const int gv = pX[0].local2global_row(lv);
170 lvec[loffset + lo * pX[0].get_row_size() + lv] = gvec[goffset + go * nvirt[0] + gv];
171 }
172 }
173 }
174 }
175 }
176
177 private:
178 const std::vector<int>& nocc;
179 const std::vector<int>& nvirt;
180 const int nspin = 1;
181 const int nk = 1;
182 const bool tdm_sym = false;
183 const std::vector<Parallel_2D>& pX;
184 T one()const;
187 std::unique_ptr<elecstate::DensityMatrix<T, T>> DM_trans;
188
191
192 std::function<void(const int&, const T* const)> cal_dm_trans;
193 };
194}
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:181
~HamiltLR()
Definition hamilt_casida.h:133
void hPsi(const T *const psi_in, T *const hpsi, const int ld_psi, const int &nband) const
Definition hamilt_casida.h:137
std::function< void(const int &, const T *const)> cal_dm_trans
Definition hamilt_casida.h:192
const int nspin
Definition hamilt_casida.h:180
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, TGint *gint_in, 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:21
void global2local(T *lvec, const T *gvec, const int &nband) const
Definition hamilt_casida.h:153
const std::vector< Parallel_2D > & pX
Definition hamilt_casida.h:183
const std::vector< int > & nocc
Definition hamilt_casida.h:178
const bool tdm_sym
whether to symmetrize the transition density matrix
Definition hamilt_casida.h:182
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:190
std::unique_ptr< elecstate::DensityMatrix< T, T > > DM_trans
Definition hamilt_casida.h:187
const std::vector< int > & nvirt
Definition hamilt_casida.h:179
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:16
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:37
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_dngvd_test cpp endif() if(ENABLE_GOOGLEBENCH) AddTest(TARGET PERF_MODULE_HSOLVER_KERNELS LIBS parameter $
Definition CMakeLists.txt:10
Definition gint_template.h:6
std::string global_readin_dir
global readin directory
Definition system_parameter.h:43