ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
rdmft_tools.h
Go to the documentation of this file.
1//==========================================================
2// Author: Jingang Han
3// DATE : 2024-03-11
4//==========================================================
5#ifndef RDMFT_TOOLS_H
6#define RDMFT_TOOLS_H
7
8#include "source_psi/psi.h"
23
27
28
29#ifdef __EXX
32// there are some operator reload to print data in different formats
33#endif
34
35#include <iostream>
36#include <type_traits>
37#include <complex>
38#include <vector>
39#include <iomanip>
40
41
42
43namespace rdmft
44{
45
47// for the dft-xc-functional part of xc-functional, just use the default is right! Or don't use the function
48double occNum_func(double eta, int symbol = 0, const std::string XC_func_rdmft = "hf", const double alpha_power = 1.0);
49
50
51template <typename TK>
53{
54 TK* pwfc = &wfc(0, 0, 0);
55 for(int i=0; i<wfc.size(); ++i) { pwfc[i] = std::conj( pwfc[i] );
56}
57}
58
59
60template <>
62
63
64// wfc and H_wfc need to be k_firest and provide wfc(ik, 0, 0) and H_wfc(ik, 0, 0)
66template <typename TK>
67void HkPsi(const Parallel_Orbitals* ParaV, const TK& HK, const TK& wfc, TK& H_wfc)
68{
69
70 const int one_int = 1;
71 //const double one_double = 1.0, zero_double = 0.0;
72 const std::complex<double> one_complex = {1.0, 0.0};
73 const std::complex<double> zero_complex = {0.0, 0.0};
74 const char N_char = 'N';
75 const char C_char = 'C'; // Using 'C' is consistent with the formula
76
77#ifdef __MPI
78 const int nbasis = ParaV->desc[2];
79 const int nbands = ParaV->desc_wfc[3];
80
81 //because wfc(bands, basis'), H(basis, basis'), we do wfc*H^T(in the perspective of cpp, not in fortran). And get H_wfc(bands, basis) is correct.
82 pzgemm_( &C_char, &N_char, &nbasis, &nbands, &nbasis, &one_complex, &HK, &one_int, &one_int, ParaV->desc,
83 &wfc, &one_int, &one_int, ParaV->desc_wfc, &zero_complex, &H_wfc, &one_int, &one_int, ParaV->desc_wfc );
84#endif
85}
86
87
88template <>
89void HkPsi<double>(const Parallel_Orbitals* ParaV, const double& HK, const double& wfc, double& H_wfc);
90
91
93template <typename TK>
94void cal_bra_op_ket(const Parallel_Orbitals* ParaV, const Parallel_2D& para_Eij_in, const TK& wfc, const TK& H_wfc, std::vector<TK>& Dmn)
95{
96 const int one_int = 1;
97 const std::complex<double> one_complex = {1.0, 0.0};
98 const std::complex<double> zero_complex = {0.0, 0.0};
99 const char N_char = 'N';
100 const char C_char = 'C';
101
102 const int nrow_bands = para_Eij_in.get_row_size();
103 const int ncol_bands = para_Eij_in.get_col_size();
104
105#ifdef __MPI
106 const int nbasis = ParaV->desc[2];
107 const int nbands = ParaV->desc_wfc[3];
108
109 pzgemm_( &C_char, &N_char, &nbands, &nbands, &nbasis, &one_complex, &wfc, &one_int, &one_int, ParaV->desc_wfc,
110 &H_wfc, &one_int, &one_int, ParaV->desc_wfc, &zero_complex, &Dmn[0], &one_int, &one_int, para_Eij_in.desc );
111#endif
112}
113
114
115template <>
116void cal_bra_op_ket<double>(const Parallel_Orbitals* ParaV, const Parallel_2D& para_Eij_in,
117 const double& wfc, const double& H_wfc, std::vector<double>& Dmn);
118
119
121template <typename TK>
122void _diagonal_in_serial(const Parallel_2D& para_Eij_in, const std::vector<TK>& Dmn, double* wfcHwfc)
123{
124 const int nrow_bands = para_Eij_in.get_row_size();
125 const int ncol_bands = para_Eij_in.get_col_size();
126
127 for(int i=0; i<nrow_bands; ++i)
128 {
129 int i_global = para_Eij_in.local2global_row(i);
130 for(int j=0; j<ncol_bands; ++j)
131 {
132 int j_global = para_Eij_in.local2global_col(j);
133 if(i_global==j_global)
134 {
135 // because the Dmn obtained from pzgemm_() is stored column-major
136 wfcHwfc[j_global] = std::real( Dmn[i+j*nrow_bands] );
137 }
138 }
139 }
140}
141
142
144template <typename TK>
145void occNum_MulPsi(const Parallel_Orbitals* ParaV, const ModuleBase::matrix& occ_number, psi::Psi<TK>& wfc, int symbol = 0,
146 const std::string XC_func_rdmft = "hf", const double alpha = 1.0)
147{
148 const int nk_local = wfc.get_nk();
149 const int nbands_local = wfc.get_nbands();
150 const int nbasis_local = wfc.get_nbasis();
151
152 // const int nbasis = ParaV->desc[2]; // need to be deleted
153 // const int nbands = ParaV->desc_wfc[3];
154
155 for (int ik = 0; ik < nk_local; ++ik)
156 {
157 for (int ib_local = 0; ib_local < nbands_local; ++ib_local) // ib_local < nbands_local , some problem, ParaV->ncol_bands
158 {
159 const double occNum_local = occNum_func( occ_number(ik, ParaV->local2global_col(ib_local)), symbol, XC_func_rdmft, alpha);
160 TK* wfc_pointer = &(wfc(ik, ib_local, 0));
161 BlasConnector::scal(nbasis_local, occNum_local, wfc_pointer, 1);
162 }
163 }
164}
165
166
168template <typename TK>
169void add_psi(const Parallel_Orbitals* ParaV,
170 const K_Vectors* kv,
171 const ModuleBase::matrix& occ_number,
172 psi::Psi<TK>& psi_TV,
173 psi::Psi<TK>& psi_hartree,
174 psi::Psi<TK>& psi_dft_XC,
175 psi::Psi<TK>& psi_exx_XC,
176 psi::Psi<TK>& occNum_Hpsi,
177 const std::string XC_func_rdmft = "hf",
178 const double alpha = 1.0)
179{
180 const int nk = psi_TV.get_nk();
181 const int nbn_local = psi_TV.get_nbands();
182 const int nbs_local = psi_TV.get_nbasis();
183 occNum_MulPsi(ParaV, occ_number, psi_TV);
184 occNum_MulPsi(ParaV, occ_number, psi_hartree);
185 occNum_MulPsi(ParaV, occ_number, psi_dft_XC);
186 occNum_MulPsi(ParaV, occ_number, psi_exx_XC, 2, XC_func_rdmft, alpha);
187
188 // const int nbasis = ParaV->desc[2];
189 // const int nbands = ParaV->desc_wfc[3];
190
191 for(int ik=0; ik<nk; ++ik)
192 {
193 for(int inbn=0; inbn<nbn_local; ++inbn)
194 {
195 TK* p_occNum_Hpsi = &( occNum_Hpsi(ik, inbn, 0) );
196 for(int inbs=0; inbs<nbs_local; ++inbs)
197 {
198 p_occNum_Hpsi[inbs] = psi_TV(ik, inbn, inbs) + psi_hartree(ik, inbn, inbs) + psi_dft_XC(ik, inbn, inbs) + psi_exx_XC(ik, inbn, inbs);
199 }
200
201 // test, consider the wk into psi or dE/d(wfc)
202 BlasConnector::scal(nbs_local, kv->wk[ik], p_occNum_Hpsi, 1);
203 }
204 }
205
206}
207
213void occNum_Mul_wfcHwfc(const ModuleBase::matrix& occ_number,
214 const ModuleBase::matrix& wfcHwfc,
215 ModuleBase::matrix& occNum_wfcHwfc,
216 int symbol = 0,
217 const std::string XC_func_rdmft = "hf",
218 const double alpha = 1.0);
219
220
225void add_occNum(const K_Vectors& kv,
226 const ModuleBase::matrix& occ_number,
227 const ModuleBase::matrix& wfcHwfc_TV_in,
228 const ModuleBase::matrix& wfcHwfc_hartree_in,
229 const ModuleBase::matrix& wfcHwfc_dft_XC_in,
230 const ModuleBase::matrix& wfcHwfc_exx_XC_in,
231 ModuleBase::matrix& occNum_wfcHwfc,
232 const std::string XC_func_rdmft = "hf",
233 const double alpha = 1.0);
234
235
237void add_wfcHwfc(const ModuleBase::matrix& wg,
238 const ModuleBase::matrix& wk_fun_occNum,
239 const ModuleBase::matrix& wfcHwfc_TV_in,
240 const ModuleBase::matrix& wfcHwfc_hartree_in,
241 const ModuleBase::matrix& wfcHwfc_XC_in,
242 ModuleBase::matrix& occNum_wfcHwfc,
243 const std::string XC_func_rdmft,
244 const double alpha);
245
246
248double getEnergy(const ModuleBase::matrix& occNum_wfcHwfc);
249
250
251
252
253
254
256template <typename TK, typename TR>
257class Veff_rdmft : public hamilt::OperatorLCAO<TK, TR>
258{
259 public:
266 const std::vector<ModuleBase::Vector3<double>>& kvec_d_in,
267 elecstate::Potential* pot_in,
269 const UnitCell* ucell_in,
270 const std::vector<double>& orb_cutoff,
271 const Grid_Driver* GridD_in,
272 const int& nspin,
273 const Charge* charge_in,
274 const ModulePW::PW_Basis* rho_basis_in,
275 const ModuleBase::matrix* vloc_in,
276 const ModuleBase::ComplexMatrix* sf_in,
277 const std::string potential_in,
278 double* etxc_in = nullptr,
279 double* vtxc_in = nullptr)
280 : GK(GK_in), orb_cutoff_(orb_cutoff), pot(pot_in), ucell(ucell_in),
281 gd(GridD_in), hamilt::OperatorLCAO<TK, TR>(hsk_in, kvec_d_in, hR_in), charge_(charge_in),
282 rho_basis_(rho_basis_in), vloc_(vloc_in), sf_(sf_in), potential_(potential_in), etxc(etxc_in), vtxc(vtxc_in)
283 {
285
286 this->initialize_HR(ucell_in, GridD_in);
287#ifdef __OLD_GINT
288 GK_in->initialize_pvpR(*ucell_in, GridD_in, nspin);
289#endif
290 }
293 const std::vector<ModuleBase::Vector3<double>>& kvec_d_in,
294 elecstate::Potential* pot_in,
296 const UnitCell* ucell_in,
297 const std::vector<double>& orb_cutoff,
298 const Grid_Driver* GridD_in,
299 const int& nspin,
300 const Charge* charge_in,
301 const ModulePW::PW_Basis* rho_basis_in,
302 const ModuleBase::matrix* vloc_in,
303 const ModuleBase::ComplexMatrix* sf_in,
304 const std::string potential_in,
305 double* etxc_in = nullptr,
306 double* vtxc_in = nullptr)
307 : GG(GG_in), orb_cutoff_(orb_cutoff), pot(pot_in), hamilt::OperatorLCAO<TK, TR>(hsk_in, kvec_d_in, hR_in),
308 ucell(ucell_in), gd(GridD_in), charge_(charge_in), rho_basis_(rho_basis_in), vloc_(vloc_in), sf_(sf_in),
309 potential_(potential_in), etxc(etxc_in), vtxc(vtxc_in)
310 {
312
313 this->initialize_HR(ucell_in, GridD_in);
314#ifdef __OLD_GINT
315 GG_in->initialize_pvpR(*ucell_in, GridD_in, nspin);
316#endif
317 }
318
320
327 virtual void contributeHR() override;
328
330
332
333 private:
334 // used for k-dependent grid integration.
335 Gint_k* GK = nullptr;
336
337 // used for gamma only algorithms.
338 Gint_Gamma* GG = nullptr;
339
340 std::vector<double> orb_cutoff_;
341
342 // Charge calculating method in LCAO base and contained grid base calculation: DM_R, DM, pvpR_reduced
343
345
346 int nspin = 1;
348
354 void initialize_HR(const UnitCell* ucell_in, const Grid_Driver* GridD_in);
355
356 // added by jghan
357
359
360 std::string potential_;
361
363
365
367
368 double* etxc;
369
370 double* vtxc;
371
372};
373
374}
375
376#endif
static void scal(const int n, const float alpha, float *X, const int incX, base_device::AbacusDevice_t device_type=base_device::AbacusDevice_t::CpuDevice)
Definition blas_connector_vector.cpp:80
Definition charge.h:20
Definition gint_gamma.h:23
Definition gint_k.h:13
void initialize_pvpR(const UnitCell &unitcell, const Grid_Driver *gd, const int &nspin)
calculate the neighbor atoms of each atom in this processor size of BaseMatrix with be the non-parall...
Definition gint_old.cpp:141
Definition sltk_grid_driver.h:43
Definition klist.h:13
std::vector< double > wk
Direct coordinates of k points.
Definition klist.h:18
Definition complexmatrix.h:14
3 elements vector
Definition vector3.h:22
Definition matrix.h:19
A class which can convert a function of "r" to the corresponding linear superposition of plane waves ...
Definition pw_basis.h:56
This class packs the basic information of 2D-block-cyclic parallel distribution of an arbitrary matri...
Definition parallel_2d.h:12
int local2global_col(const int ilc) const
get the global index of a local index (col)
Definition parallel_2d.h:63
int get_row_size() const
number of local rows
Definition parallel_2d.h:21
int local2global_row(const int ilr) const
get the global index of a local index (row)
Definition parallel_2d.h:57
int desc[9]
ScaLAPACK descriptor.
Definition parallel_2d.h:103
int get_col_size() const
number of local columns
Definition parallel_2d.h:27
Definition parallel_orbitals.h:9
int desc_wfc[9]
Definition parallel_orbitals.h:37
Definition unitcell.h:16
Definition potential_new.h:48
Definition hcontainer.h:144
Definition hs_matrix_k.hpp:11
Definition operator_lcao.h:12
OperatorLCAO(HS_Matrix_K< TK > *hsk_in, const std::vector< ModuleBase::Vector3< double > > &kvec_d_in, HContainer< TR > *hR_in)
H(R) matrix, R is the Bravis lattice vector.
Definition operator_lcao.h:15
enum calculation_type cal_type
Definition operator.h:107
Definition psi.h:37
const int & get_nbands() const
Definition psi.cpp:342
const int & get_nk() const
Definition psi.cpp:336
size_t size() const
Definition psi.cpp:354
const int & get_nbasis() const
Definition psi.cpp:348
this part of the code is copying from class Veff and do some modifications.
Definition rdmft_tools.h:258
Veff_rdmft(Gint_Gamma *GG_in, hamilt::HS_Matrix_K< TK > *hsk_in, const std::vector< ModuleBase::Vector3< double > > &kvec_d_in, elecstate::Potential *pot_in, hamilt::HContainer< TR > *hR_in, const UnitCell *ucell_in, const std::vector< double > &orb_cutoff, const Grid_Driver *GridD_in, const int &nspin, const Charge *charge_in, const ModulePW::PW_Basis *rho_basis_in, const ModuleBase::matrix *vloc_in, const ModuleBase::ComplexMatrix *sf_in, const std::string potential_in, double *etxc_in=nullptr, double *vtxc_in=nullptr)
Definition rdmft_tools.h:291
double * etxc
Definition rdmft_tools.h:368
Veff_rdmft(Gint_k *GK_in, hamilt::HS_Matrix_K< TK > *hsk_in, const std::vector< ModuleBase::Vector3< double > > &kvec_d_in, elecstate::Potential *pot_in, hamilt::HContainer< TR > *hR_in, const UnitCell *ucell_in, const std::vector< double > &orb_cutoff, const Grid_Driver *GridD_in, const int &nspin, const Charge *charge_in, const ModulePW::PW_Basis *rho_basis_in, const ModuleBase::matrix *vloc_in, const ModuleBase::ComplexMatrix *sf_in, const std::string potential_in, double *etxc_in=nullptr, double *vtxc_in=nullptr)
Construct a new Veff object for multi-kpoint calculation.
Definition rdmft_tools.h:264
double * vtxc
Definition rdmft_tools.h:370
std::string potential_
Definition rdmft_tools.h:360
const ModuleBase::ComplexMatrix * sf_
Definition rdmft_tools.h:366
Gint_k * GK
Definition rdmft_tools.h:335
const Grid_Driver * gd
Definition rdmft_tools.h:331
elecstate::Potential * pot
Definition rdmft_tools.h:344
int current_spin
Definition rdmft_tools.h:347
Gint_Gamma * GG
Definition rdmft_tools.h:338
virtual void contributeHR() override
contributeHR() is used to calculate the HR matrix <phi_{\mu, 0}|V_{eff}|phi_{\nu, R}> the contributio...
const ModulePW::PW_Basis * rho_basis_
Definition rdmft_tools.h:362
const UnitCell * ucell
Definition rdmft_tools.h:329
const Charge * charge_
Definition rdmft_tools.h:358
int nspin
Definition rdmft_tools.h:346
void initialize_HR(const UnitCell *ucell_in, const Grid_Driver *GridD_in)
initialize HR, search the nearest neighbor atoms HContainer is used to store the electronic kinetic m...
Definition rdmft_tools.cpp:199
const ModuleBase::matrix * vloc_
Definition rdmft_tools.h:364
std::vector< double > orb_cutoff_
Definition rdmft_tools.h:340
Definition hamilt.h:12
Reduced Density Matrix Functional Theory (RDMFT)
Definition rdmft.cpp:24
void cal_bra_op_ket< double >(const Parallel_Orbitals *ParaV, const Parallel_2D &para_Eij_in, const double &wfc, const double &H_wfc, std::vector< double > &Dmn)
Definition rdmft_tools.cpp:55
void HkPsi< double >(const Parallel_Orbitals *ParaV, const double &HK, const double &wfc, double &H_wfc)
Definition rdmft_tools.cpp:31
void occNum_Mul_wfcHwfc(const ModuleBase::matrix &occ_number, const ModuleBase::matrix &wfcHwfc, ModuleBase::matrix &occNum_wfcHwfc, int symbol, const std::string XC_func_rdmft, const double alpha)
occNum_wfcHwfc = occNum*wfcHwfc + occNum_wfcHwfc
Definition rdmft_tools.cpp:82
void add_occNum(const K_Vectors &kv, const ModuleBase::matrix &occ_number, const ModuleBase::matrix &wfcHwfc_TV_in, const ModuleBase::matrix &wfcHwfc_hartree_in, const ModuleBase::matrix &wfcHwfc_dft_XC_in, const ModuleBase::matrix &wfcHwfc_exx_XC_in, ModuleBase::matrix &occNum_wfcHwfc, const std::string XC_func_rdmft, const double alpha)
Default symbol = 0 for the gradient of Etotal with respect to occupancy, symbol = 1 for the relevant ...
Definition rdmft_tools.cpp:100
void conj_psi< double >(psi::Psi< double > &wfc)
Definition rdmft_tools.cpp:28
void cal_bra_op_ket(const Parallel_Orbitals *ParaV, const Parallel_2D &para_Eij_in, const TK &wfc, const TK &H_wfc, std::vector< TK > &Dmn)
implement matrix multiplication of sum_mu conj(wfc(ik, m ,mu)) * op_wfc(ik, n, mu)
Definition rdmft_tools.h:94
double getEnergy(const ModuleBase::matrix &occNum_wfcHwfc)
give certain occNum_wfcHwfc, get the corresponding energy
Definition rdmft_tools.cpp:146
void HkPsi(const Parallel_Orbitals *ParaV, const TK &HK, const TK &wfc, TK &H_wfc)
implement matrix multiplication of Hk^dagger and psi
Definition rdmft_tools.h:67
void add_psi(const Parallel_Orbitals *ParaV, const K_Vectors *kv, const ModuleBase::matrix &occ_number, psi::Psi< TK > &psi_TV, psi::Psi< TK > &psi_hartree, psi::Psi< TK > &psi_dft_XC, psi::Psi< TK > &psi_exx_XC, psi::Psi< TK > &occNum_Hpsi, const std::string XC_func_rdmft="hf", const double alpha=1.0)
add psi with eta and g(eta)
Definition rdmft_tools.h:169
void _diagonal_in_serial(const Parallel_2D &para_Eij_in, const std::vector< TK > &Dmn, double *wfcHwfc)
for Dmn that conforms to the 2d-block rule, get its diagonal elements
Definition rdmft_tools.h:122
double occNum_func(const double eta, const int symbol, const std::string XC_func_rdmft, double alpha)
now support XC_func_rdmft = "hf", "muller", "power", "pbe", "pbe0". "wp22" and "cwp22" is realizing.
Definition rdmft_tools.cpp:163
void occNum_MulPsi(const Parallel_Orbitals *ParaV, const ModuleBase::matrix &occ_number, psi::Psi< TK > &wfc, int symbol=0, const std::string XC_func_rdmft="hf", const double alpha=1.0)
realize occNum_wfc = occNum * wfc. Calling this function and we can get wfc = occNum*wfc.
Definition rdmft_tools.h:145
void add_wfcHwfc(const ModuleBase::matrix &wg, const ModuleBase::matrix &wk_fun_occNum, const ModuleBase::matrix &wfcHwfc_TV_in, const ModuleBase::matrix &wfcHwfc_hartree_in, const ModuleBase::matrix &wfcHwfc_XC_in, ModuleBase::matrix &occNum_wfcHwfc, const std::string XC_func_rdmft, const double alpha)
do wk*g(occNum)*wfcHwfc and add for TV, hartree, XC. This function just use once, so it can be replac...
Definition rdmft_tools.cpp:129
void conj_psi(psi::Psi< TK > &wfc)
Definition rdmft_tools.h:52
void pzgemm_(const char *transa, const char *transb, const int *M, const int *N, const int *K, const std::complex< double > *alpha, const std::complex< double > *A, const int *IA, const int *JA, const int *DESCA, const std::complex< double > *B, const int *IB, const int *JB, const int *DESCB, const std::complex< double > *beta, std::complex< double > *C, const int *IC, const int *JC, const int *DESCC)