Skip to content

Commit d5399c8

Browse files
committed
KEY fix: Hxc Hellmann-Feynman term with (T+DZ)
1 parent 61d8ddc commit d5399c8

4 files changed

Lines changed: 85 additions & 23 deletions

File tree

source/module_lr/Grad/esolver_lr_grad.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ inline auto get_exx_Ds_spin1(const elecstate::DensityMatrix<T, T>& dm,
7575
return RI_2D_Comm::split_m2D_ktoR<T>(ucell, kv, DMk_trans_pointer, pmat, /*nspin=*/1)[0];
7676
}
7777
template <typename T>
78-
inline auto get_exx_Ds_gs(elecstate::DensityMatrix<T, double>& dm,
78+
inline auto get_exx_Ds_gs(const elecstate::DensityMatrix<T, double>& dm,
7979
const UnitCell& ucell, const K_Vectors& kv, const Parallel_Orbitals& pmat, const int nspin)
8080
-> std::map<int, std::map<std::pair<int, std::array<int, 3>>, RI::Tensor<T>>>
8181
{
@@ -245,7 +245,8 @@ std::vector<ModuleBase::matrix> LR::ESolver_LR<T, TR>::cal_force(const int ispin
245245
std::cout << "Force (Hxc-DMTrans term) of state " << istate << ": " << std::endl;
246246
LR_Util::print_value(force_hxc_dmtrans.c, ucell.nat, 3);
247247

248-
ModuleBase::matrix force_hamiltgs_relaxed_diff = lr_force.cal_force_hamilt_gs_dm_relaxed_diff(relaxed_diff_dm_real, *pot_gs, /*with_ewald=*/false);
248+
const elecstate::DensityMatrix<T, double>& dm_gs = this->cal_dm_gs();
249+
ModuleBase::matrix force_hamiltgs_relaxed_diff = lr_force.cal_force_hamilt_gs_dm_relaxed_diff(relaxed_diff_dm_real, dm_gs, /*with_ewald=*/false);
249250
std::cout << "Force (GS-(T+Z) term) of state " << istate << ": " << std::endl;
250251
LR_Util::print_value(force_hamiltgs_relaxed_diff.c, ucell.nat, 3);
251252

@@ -261,8 +262,6 @@ std::vector<ModuleBase::matrix> LR::ESolver_LR<T, TR>::cal_force(const int ispin
261262
std::cout << "Force (EXX-DMTrans term) of state " << istate << ": " << std::endl;
262263
LR_Util::print_value(force_exx_dmtrans.c, ucell.nat, 3);
263264

264-
elecstate::DensityMatrix<T, double> dm_gs(&this->paraMat_, this->nspin, this->kv.kvec_d, this->nk); //DX
265-
elecstate::cal_dm_psi(&this->paraMat_all_, this->wg_ks_all, *this->psi_ks_all, dm_gs); // nbands is important here
266265
const auto& Ds_gs = get_exx_Ds_gs(dm_gs, this->ucell, this->kv, this->paraMat_, this->nspin);
267266
const auto& Ds_relaxed_diff = get_exx_Ds_spin1(relaxed_diff_dm, this->ucell, this->kv, this->paraMat_);
268267
ModuleBase::matrix force_exx_gs_diff = lr_force.cal_force_exx_gs_dm_relaxed_diff(Ds_gs, Ds_relaxed_diff, alpha);
@@ -281,6 +280,16 @@ std::vector<ModuleBase::matrix> LR::ESolver_LR<T, TR>::cal_force(const int ispin
281280
return forces;
282281
}
283282

283+
template<typename T, typename TR>
284+
elecstate::DensityMatrix<T, double> LR::ESolver_LR<T, TR>::cal_dm_gs()
285+
{
286+
elecstate::DensityMatrix<T, double> dm_gs(&this->paraMat_, this->nspin, this->kv.kvec_d, this->nk);
287+
elecstate::cal_dm_psi(&this->paraMat_all_, this->wg_ks_all, *this->psi_ks_all, dm_gs); // nbands is important here
288+
LR_Util::initialize_DMR(dm_gs, this->paraMat_, this->ucell, this->gd, this->orb_cutoff_); // nbands is not important here
289+
dm_gs.cal_DMR();
290+
return dm_gs;
291+
}
292+
284293
template<typename T, typename TR>
285294
void LR::ESolver_LR<T, TR>::test_force()
286295
{
@@ -290,11 +299,8 @@ void LR::ESolver_LR<T, TR>::test_force()
290299
#endif
291300
);
292301

293-
elecstate::DensityMatrix<T, double> dm_gs(&this->paraMat_, this->nspin, this->kv.kvec_d, this->nk); //DX
294-
elecstate::cal_dm_psi(&this->paraMat_all_, this->wg_ks_all, *this->psi_ks_all, dm_gs); // nbands is important here
295-
LR_Util::initialize_DMR(dm_gs, this->paraMat_, this->ucell, this->gd, this->orb_cutoff_); // nbands is not important here
296-
dm_gs.cal_DMR();
297-
LR_Util::print_DMR(dm_gs, this->ucell.nat, "DM(R) of ground state");
302+
const elecstate::DensityMatrix<T, double>& dm_gs = this->cal_dm_gs();
303+
// LR_Util::print_DMR(dm_gs, this->ucell.nat, "DM(R) of ground state");
298304
///========================== test 1: reproduce the force of ground state =========================
299305
// energy density matrix of the ground state
300306
elecstate::DensityMatrix<T, double> edm_gs(&this->paraMat_, this->nspin, this->kv.kvec_d, this->nk); //DX
@@ -305,7 +311,7 @@ void LR::ESolver_LR<T, TR>::test_force()
305311
LR_Util::initialize_DMR(edm_gs, this->paraMat_, this->ucell, this->gd, this->orb_cutoff_);
306312
edm_gs.cal_DMR();
307313
// ground-state force
308-
ModuleBase::matrix force_gs = lr_force.reproduce_force_gs(dm_gs, edm_gs, *this->pot_gs);
314+
ModuleBase::matrix force_gs = lr_force.reproduce_force_gs(dm_gs, edm_gs);
309315
ModuleIO::print_force(GlobalV::ofs_running, this->ucell, "Ground State FORCE (eV/Angstrom)", force_gs, false);
310316
/// ======================================= END test 1 =========================================
311317
///========================== test 2: reproduce the DX Hartree term =========================

source/module_lr/Grad/force/lr_force.cpp

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,34 @@ namespace LR
2525
return chr;
2626
}
2727

28+
template<typename TK>
29+
elecstate::Potential LR_Force<TK>::dm_to_hxc_potential(const elecstate::DensityMatrix<TK, double>& dm)
30+
{
31+
elecstate::Potential pot(nullptr/*remaining for uspp*/,
32+
&this->rhopw_, &this->ucell_, &this->locpp_.vloc, const_cast<Structure_Factor*>(&this->sf_),
33+
nullptr/*surchem*/, nullptr/*etxc*/, nullptr/*vtxc*/);
34+
PARAM.inp.vh_in_h ? pot.pot_register({ "hartree", "xc" }) : pot.pot_register({ "xc" });
35+
const Charge& charge = this->dm_to_charge(dm);
36+
pot.init_pot(0, &charge); // call update_from_charge inside
37+
return pot;
38+
}
39+
40+
template<typename TK>
41+
elecstate::Potential LR_Force<TK>::local_potential()
42+
{
43+
elecstate::Potential pot(nullptr/*remaining for uspp*/,
44+
&this->rhopw_, &this->ucell_, &this->locpp_.vloc, const_cast<Structure_Factor*>(&this->sf_),
45+
nullptr/*surchem*/, nullptr/*etxc*/, nullptr/*vtxc*/);
46+
pot.pot_register({ "local" });
47+
pot.init_pot(0, nullptr);
48+
return pot;
49+
}
50+
2851
template<typename TK>
2952
ModuleBase::matrix LR_Force<TK>::cal_force_hamilt_gs_dm_relaxed_diff(const elecstate::DensityMatrix<TK, double>& relax_diff_dm,
30-
const elecstate::Potential& pot_gs, const bool with_ewald)
53+
const elecstate::DensityMatrix<TK, double>& dm_gs,
54+
// const elecstate::Potential& pot_gs,
55+
const bool with_ewald)
3156
{
3257
const Charge chr_diff_relaxed = dm_to_charge(relax_diff_dm);
3358

@@ -39,11 +64,38 @@ namespace LR
3964
// 2. nonlocal pp (Hellmann-Feynman + Pulay)
4065
ModuleBase::matrix fvnl = cal_force_nonlocal(this->ucell_, this->kvec_d_, this->gd_, this->two_center_bundle_, relax_diff_dm);
4166

42-
// 3. local pp (Pulay) + Hartree + xc (grid integration)
67+
// // 3. local pp (Pulay) + Hartree + xc (grid integration)
68+
// ModuleBase::matrix fvl_dphi(this->ucell_.nat, 3);
69+
// ModuleBase::matrix stress_tmp; // no use now, only for passing into interfaces
70+
// PulayForceStress::cal_pulay_fs(relax_diff_dm.get_DMR_vector().size()/*nspin*/, fvl_dphi, stress_tmp,
71+
// relax_diff_dm, this->ucell_, &pot_gs, *this->gint_, true, false);
72+
73+
// 3.1. local pp (Pulay)
4374
ModuleBase::matrix fvl_dphi(this->ucell_.nat, 3);
4475
ModuleBase::matrix stress_tmp; // no use now, only for passing into interfaces
76+
elecstate::Potential pot_loc = this->local_potential();
4577
PulayForceStress::cal_pulay_fs(relax_diff_dm.get_DMR_vector().size()/*nspin*/, fvl_dphi, stress_tmp,
46-
relax_diff_dm, this->ucell_, &pot_gs, *this->gint_, true, false);
78+
relax_diff_dm, this->ucell_, &pot_loc, *this->gint_, true, false);
79+
80+
// 3.2. Hartree + xc (Pulay)
81+
// method 1
82+
// ModuleBase::matrix fgs_dphi(this->ucell_.nat, 3);
83+
// PulayForceStress::cal_pulay_fs(relax_diff_dm.get_DMR_vector().size()/*nspin*/, fgs_dphi, stress_tmp,
84+
// relax_diff_dm, this->ucell_, &pot_gs, *this->gint_, true, false);
85+
// ModuleBase::matrix fhxc_dphi = (fgs_dphi - fvl_dphi) * 0.5; // avoid double count of hxc Pulay term
86+
// method 2
87+
ModuleBase::matrix fhxc_dphi(this->ucell_.nat, 3);
88+
elecstate::Potential pot_hxc = this->dm_to_hxc_potential(dm_gs);
89+
PulayForceStress::cal_pulay_fs(relax_diff_dm.get_DMR_vector().size()/*nspin*/, fhxc_dphi, stress_tmp,
90+
relax_diff_dm, this->ucell_, &pot_hxc, *this->gint_, true, false);
91+
fhxc_dphi *= 0.5; // avoid double count
92+
93+
// 3.3 Hartree + xc (Hellmann-Feynman)
94+
ModuleBase::matrix fhxc_dvhxc(this->ucell_.nat, 3);
95+
elecstate::Potential pot_hxc_relaxed_diff = this->dm_to_hxc_potential(relax_diff_dm);
96+
PulayForceStress::cal_pulay_fs(dm_gs.get_DMR_vector().size()/*nspin*/, fhxc_dvhxc, stress_tmp,
97+
relax_diff_dm, this->ucell_, &pot_hxc_relaxed_diff, *this->gint_, false, true);
98+
fhxc_dvhxc *= 0.5; // avoid double count
4799

48100
// 4. kinetic (Pulay)
49101
std::vector<hamilt::HContainer<double>> dT = cal_hs_grad('T', this->ucell_, this->pv_, this->gd_, this->two_center_bundle_);
@@ -54,11 +106,13 @@ namespace LR
54106
ModuleIO::print_force(GlobalV::ofs_running, this->ucell_, "PW FORCE (eV/Angstrom)", f_pw, false);
55107
ModuleIO::print_force(GlobalV::ofs_running, this->ucell_, "NONLOCAL FORCE (eV/Angstrom)", fvnl, false);
56108
ModuleIO::print_force(GlobalV::ofs_running, this->ucell_, "KINETIC FORCE (eV/Angstrom)", ft_dphi, false);
57-
ModuleIO::print_force(GlobalV::ofs_running, this->ucell_, "LOCAL Pulay FORCE (pp+Hartree+XC) (eV/Angstrom)", fvl_dphi, false);
109+
ModuleIO::print_force(GlobalV::ofs_running, this->ucell_, "LOCAL-PP Pulay FORCE (eV/Angstrom)", fvl_dphi, false);
110+
ModuleIO::print_force(GlobalV::ofs_running, this->ucell_, "HARTREE+XC Pulay FORCE (eV/Angstrom)", fhxc_dphi, false);
111+
ModuleIO::print_force(GlobalV::ofs_running, this->ucell_, "HARTREE+XC Hellmann-Feynman FORCE (eV/Angstrom)", fhxc_dvhxc, false);
58112
}
59113

60114
// from the formula, we do not need the non-ortho term (overlap*edm) here.
61-
return f_pw + fvnl + ft_dphi + fvl_dphi;
115+
return f_pw + fvnl + ft_dphi + fvl_dphi + fhxc_dphi + fhxc_dvhxc;
62116
}
63117
template<typename TK>
64118
ModuleBase::matrix LR_Force<TK>::cal_force_hxc_dmtrans(const elecstate::DensityMatrix<TK, double>& dm_trans, const PotHxcLR& pot_hxc)
@@ -85,12 +139,11 @@ namespace LR
85139
template<typename TK>
86140
ModuleBase::matrix LR_Force<TK>::reproduce_force_gs(
87141
const elecstate::DensityMatrix<TK, double>& dm_gs,
88-
const elecstate::DensityMatrix<TK, double>& edm_gs,
89-
const elecstate::Potential& pot_gs)
142+
const elecstate::DensityMatrix<TK, double>& edm_gs)
90143
{
91144
this->gint_->reset_DMRGint(PARAM.inp.nspin);
92-
// Hartree+xc term
93-
ModuleBase::matrix f_gs_hf_pulay = cal_force_hamilt_gs_dm_relaxed_diff(dm_gs, pot_gs); // pw+vnl+t_dphi+vl_dphi
145+
// local + Hartree + xc term, including Hellmann-Feynman and Pulay
146+
ModuleBase::matrix f_gs_hf_pulay = cal_force_hamilt_gs_dm_relaxed_diff(dm_gs, dm_gs); // pw+vnl+t_dphi+vl_dphi
94147
// edm term
95148
ModuleBase::matrix f_nonortho = cal_force_overlap_edm(edm_gs); // overlap
96149
this->gint_->reset_DMRGint(1);

source/module_lr/Grad/force/lr_force.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ namespace LR
3939

4040
/// 1. $Tr[H_{GS}^x * (T+D^Z)]$, where GS=groud state and $(T+D^Z)$ is the relaxed difference density matrix
4141
ModuleBase::matrix cal_force_hamilt_gs_dm_relaxed_diff(const elecstate::DensityMatrix<TK, double>& relaxed_diff_dm,
42-
const elecstate::Potential& pot_gs, const bool with_ewald = true);
42+
const elecstate::DensityMatrix<TK, double>& dm_gs, const bool with_ewald = true);
43+
// const elecstate::Potential& pot_gs, const bool with_ewald = true);
4344

4445
/// 2. $Tr[S^x * (EDM)]
4546
ModuleBase::matrix cal_force_overlap_edm(const elecstate::DensityMatrix<TK, double>& edm);
@@ -62,8 +63,8 @@ namespace LR
6263
// test functions
6364
/// reproduce the force of the ground state
6465
ModuleBase::matrix reproduce_force_gs(const elecstate::DensityMatrix<TK, double>& dm_gs,
65-
const elecstate::DensityMatrix<TK, double>& edm_gs,
66-
const elecstate::Potential& pot_gs);
66+
const elecstate::DensityMatrix<TK, double>& edm_gs);
67+
6768
/// repreduce the ground state local term
6869
ModuleBase::matrix reproduce_force_gs_loc(const elecstate::DensityMatrix<TK, double>& dm_gs,
6970
const elecstate::Potential& pot_gs);
@@ -84,7 +85,8 @@ namespace LR
8485
#endif
8586

8687
Charge dm_to_charge(const elecstate::DensityMatrix<TK, double>& dm);
87-
88+
elecstate::Potential dm_to_hxc_potential(const elecstate::DensityMatrix<TK, double>& dm);
89+
elecstate::Potential local_potential();
8890
// probably move frome the ground state?
8991
// void build_dHS()
9092
};

source/module_lr/esolver_lrtd_lcao.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ namespace LR
148148
ct::Tensor solve_zvector_eqation(const int ispin);
149149
std::vector<ModuleBase::matrix> cal_force(const int ispin);
150150
void test_force(); // test: reproduce the force of ground state
151+
elecstate::DensityMatrix<T, double> cal_dm_gs(); ///< ground-state density matrix
151152

152153
#ifdef __EXX
153154
/// Tdata of Exx_LRI is same as T, for the reason, see operator_lr_exx.h

0 commit comments

Comments
 (0)