From 21e9caf1102d319ce5c757bac3ed113e83724b2c Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 08:21:47 +0800 Subject: [PATCH 01/23] refactor(dftu_base): reorganize Plus_U_Base members by access level Group the previously interleaved public/protected sections of Plus_U_Base into a single public block followed by a single protected block. No member is moved between access levels and no signature or implementation is changed; this only consolidates the layout so that follow-up changes to access permissions are easier to review. --- source/source_pw/module_pwdft/dftu_base.h | 72 +++++++++++------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/source/source_pw/module_pwdft/dftu_base.h b/source/source_pw/module_pwdft/dftu_base.h index 7885f6f8fa..2f17e535ef 100644 --- a/source/source_pw/module_pwdft/dftu_base.h +++ b/source/source_pw/module_pwdft/dftu_base.h @@ -11,18 +11,20 @@ class Plus_U_Base { + //============================================================= + // public section + //============================================================= public: Plus_U_Base(); ~Plus_U_Base(); - public: /// allocate relevant data structures (base part, no LCAO types) void init_base(UnitCell& cell, const int npol, const int nspin, const std::vector& orbital_corr, const bool yukawa_potential, - const std::string& global_readin_dir, + const std::string& global_read_in_dir, const std::string& global_out_dir, const std::string& init_chg, const std::string& device, @@ -44,7 +46,6 @@ class Plus_U_Base int nspin = 0; // --- Accessors --- - double get_u_current(int it) const { return u_current[it]; } double get_u_target(int it) const { return u_target[it]; } int get_num_u_types() const { return static_cast(u_current.size()); } @@ -59,18 +60,6 @@ class Plus_U_Base void set_energy(const double &e) { energy_u = e; } void set_double_energy() { energy_u *= 2.0; } - protected: - double energy_u = 0.0; - - int cal_type = 3; - std::string device; - int kpar = 1; - - // transform between iwt index and it, ia, L, N and m index - std::vector>>>> - iatlnmipol2iwt; - - public: /// interface for PW base /// calculate the local occupation number matrix for PW based wave functions void cal_occ_pw(const int iter, @@ -129,24 +118,6 @@ class Plus_U_Base bool is_mixing_enabled() const { return mixing_dftu != 0; } void enable_mixing() { mixing_dftu = 1; } - protected: - void copy_occ_mat(const UnitCell& ucell); - void zero_occ_mat(const UnitCell& ucell); - void mix_occ_mat(const UnitCell& ucell, const double& mixing_beta); - void set_occ_mat(const UnitCell& ucell); - - std::vector> eff_pot_pw; - std::vector eff_pot_pw_index; - std::vector uom_array; - std::vector uom_save; - - // Yukawa-related members (base part, no LCAO dependency) - double lambda = 0.0; - std::vector>>> Fk; - std::vector>> U_Yukawa; - std::vector>> J_Yukawa; - - public: /// get occupation matrix element occ_mat[iat][l][n][spin](m1,m2) double get_occ_mat(const int iat, const int l, const int n, const int spin, const int m1, const int m2) const @@ -181,7 +152,39 @@ class Plus_U_Base // dftu_io::write_occup_m. They access Plus_U_Base via public getters. // mohan refactored 2025-11-08 //============================================================= + + bool use_yukawa = false; + + //============================================================= + // protected section + //============================================================= protected: + double energy_u = 0.0; + + int cal_type = 3; + std::string device; + int kpar = 1; + + // transform between iwt index and it, ia, L, N and m index + std::vector>>>> + iatlnmipol2iwt; + + void copy_occ_mat(const UnitCell& ucell); + void zero_occ_mat(const UnitCell& ucell); + void mix_occ_mat(const UnitCell& ucell, const double& mixing_beta); + void set_occ_mat(const UnitCell& ucell); + + std::vector> eff_pot_pw; + std::vector eff_pot_pw_index; + std::vector uom_array; + std::vector uom_save; + + // Yukawa-related members (base part, no LCAO dependency) + double lambda = 0.0; + std::vector>>> Fk; + std::vector>> U_Yukawa; + std::vector>> J_Yukawa; + void read_occup_m(const UnitCell& ucell, const std::string& fn, const std::string& init_chg, @@ -195,9 +198,6 @@ class Plus_U_Base // In dftu_yukawa.cpp // Relevant for calculating U using Yukawa potential //============================================================= - - public: - bool use_yukawa = false; }; From fd252007edaa0c31d0135612dc8a35ac1639b57e Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 09:19:45 +0800 Subject: [PATCH 02/23] refactor(dftu_base): encapsulate Plus_U_Base data members Move all public data members of Plus_U_Base to protected so that external code is forced to go through accessors. This tightens encapsulation of the U values, the DFT+U configuration flags, the occ_mat state flag, and the occupation matrices themselves. New public getters added for the existing external read sites: - get_uramping() replaces dftu.uramping reads in chgmixing.cpp - get_occ_mat_ctrl() replaces dftu.occ_mat_ctrl reads in setup_dftu_pw.cpp and setup_dftu_lcao.cpp - use_yukawa() replaces dftu.use_yukawa reads in dftu_output.cpp The data member use_yukawa is renamed to use_yukawa_ so the getter can keep the natural name; the 9 internal bare-name accesses in dftu_base.cpp / dftu_lcao.cpp / dftu_tools.cpp / dftu_yukawa.cpp are updated accordingly. External write access is limited to the unit-test fixture DFTUTest::SetUp, which writes u_current, orbital_corr and resizes occ_mat directly. Rather than exposing setters for these one-off test scenarios, DFTUTest is declared as a friend of Plus_U_Base. gtest TEST_F derives DFTUTest_xxx_Test whose TestBody does not inherit the friend declaration, so a small const helper occ_mat_c(iat, spin, icc) is added to DFTUTest itself; the three affected EXPECT_NEAR sites in dftu_lcao_test.cpp call it instead of touching dftu.occ_mat directly. Two hamilt::DFTU> methods (cal_v_of_u in dftu_lcao_op.cpp, cal_force_stress in dftu_fs.cpp) read this->dftu->u_current[T0]; both are switched to the existing get_u_current(T0) accessor. --- .../source_estate/module_charge/chgmixing.cpp | 10 +-- source/source_lcao/module_dftu/dftu_fs.cpp | 2 +- source/source_lcao/module_dftu/dftu_lcao.cpp | 4 +- .../source_lcao/module_dftu/dftu_lcao_op.cpp | 2 +- source/source_lcao/module_dftu/dftu_tools.cpp | 4 +- .../source_lcao/module_dftu/dftu_yukawa.cpp | 4 +- .../module_dftu/test/dftu_lcao_test.cpp | 15 ++++- source/source_lcao/setup_dftu_lcao.cpp | 2 +- source/source_pw/module_pwdft/dftu_base.cpp | 8 +-- source/source_pw/module_pwdft/dftu_base.h | 61 +++++++++---------- source/source_pw/module_pwdft/dftu_output.cpp | 2 +- .../source_pw/module_pwdft/setup_dftu_pw.cpp | 2 +- 12 files changed, 62 insertions(+), 54 deletions(-) diff --git a/source/source_estate/module_charge/chgmixing.cpp b/source/source_estate/module_charge/chgmixing.cpp index b15f28a8d7..7931d36b60 100644 --- a/source/source_estate/module_charge/chgmixing.cpp +++ b/source/source_estate/module_charge/chgmixing.cpp @@ -145,11 +145,11 @@ void module_charge::chgmixing_ks_pw(const int iter, // scf iteration number if (inp.dft_plus_u) { - if (dftu.uramping > 0.01 && !dftu.u_converged()) + if (dftu.get_uramping() > 0.01 && !dftu.u_converged()) { p_chgmix->mixing_restart_step = inp.scf_nmax + 1; } - if (dftu.uramping > 0.01) + if (dftu.get_uramping() > 0.01) { bool do_uramping = true; if (inp.sc_mag_switch) @@ -197,7 +197,7 @@ void module_charge::chgmixing_ks_lcao(const int iter, // scf iteration number dftu.enable_mixing(); } // this output will be removed once the feeature is stable - if (dftu.uramping > 0.01) + if (dftu.get_uramping() > 0.01) { std::cout << " U-Ramping! Current U = "; for (int i = 0; i < dftu.get_num_u_types(); i++) @@ -216,7 +216,7 @@ void module_charge::chgmixing_ks_lcao(const int iter, // scf iteration number if (inp.dft_plus_u) { dftu.uramping_update(); // update U by uramping if uramping > 0.01 - if (dftu.uramping > 0.01) + if (dftu.get_uramping() > 0.01) { std::cout << " U-Ramping! Current U = "; for (int i = 0; i < dftu.get_num_u_types(); i++) @@ -225,7 +225,7 @@ void module_charge::chgmixing_ks_lcao(const int iter, // scf iteration number } std::cout << " eV " << std::endl; } - if (dftu.uramping > 0.01 && !dftu.u_converged()) + if (dftu.get_uramping() > 0.01 && !dftu.u_converged()) { p_chgmix->mixing_restart_step = inp.scf_nmax + 1; } diff --git a/source/source_lcao/module_dftu/dftu_fs.cpp b/source/source_lcao/module_dftu/dftu_fs.cpp index 72f2ffcce0..3fff048293 100644 --- a/source/source_lcao/module_dftu/dftu_fs.cpp +++ b/source/source_lcao/module_dftu/dftu_fs.cpp @@ -141,7 +141,7 @@ void DFTU>::cal_force_stress(const bool cal_force, this->dftu->get_occ_mat_flat(iat0, target_L, occ); // calculate VU - const double u_value = this->dftu->u_current[T0]; + const double u_value = this->dftu->get_u_current(T0); std::vector VU(occ.size()); double eu_tmp = 0; this->cal_v_of_u(occ, tlp1, u_value, &VU[0], eu_tmp); diff --git a/source/source_lcao/module_dftu/dftu_lcao.cpp b/source/source_lcao/module_dftu/dftu_lcao.cpp index 67e915e071..b4f89242cb 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao.cpp @@ -175,7 +175,7 @@ void Plus_U::cal_energy_correction(const UnitCell& ucell, * this->occ_mat[iat][l][n][spin](m1, m0); } } - if (use_yukawa) + if (use_yukawa_) { this->energy_u += 0.5 * (this->U_Yukawa[T][l][n] - this->J_Yukawa[T][l][n]) * (nm_trace - nm2_trace); @@ -210,7 +210,7 @@ void Plus_U::cal_energy_correction(const UnitCell& ucell, } } } - if (use_yukawa) + if (use_yukawa_) { this->energy_u += 0.5 * (this->U_Yukawa[T][l][n] - this->J_Yukawa[T][l][n]) * (nm_trace - nm2_trace); diff --git a/source/source_lcao/module_dftu/dftu_lcao_op.cpp b/source/source_lcao/module_dftu/dftu_lcao_op.cpp index 9497cacabc..0ddf17e560 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao_op.cpp @@ -369,7 +369,7 @@ void hamilt::DFTU>::contributeHR() // VU = U * (1/2 * delta(m,m') - occ(m,m')) for each spin channel // Energy: EU = U * 1/2 * occ(m,m') * occ(m',m) ModuleBase::timer::start("DFTU", "cal_vu"); - const double u_value = this->dftu->u_current[T0]; + const double u_value = this->dftu->get_u_current(T0); std::vector VU_tmp(occ.size()); // mohan update 2025-11: get_energy/set_energy are now instance methods diff --git a/source/source_lcao/module_dftu/dftu_tools.cpp b/source/source_lcao/module_dftu/dftu_tools.cpp index 6e86daeccf..954cff79ff 100644 --- a/source/source_lcao/module_dftu/dftu_tools.cpp +++ b/source/source_lcao/module_dftu/dftu_tools.cpp @@ -158,7 +158,7 @@ double Plus_U::get_onebody_eff_pot(const int T, case 3: // simplified formalism and FLL double counting if (new_occ_mat) { - if (use_yukawa) + if (use_yukawa_) { if (m0 == m1) { @@ -179,7 +179,7 @@ double Plus_U::get_onebody_eff_pot(const int T, } else { - if (use_yukawa) + if (use_yukawa_) { if (m0 == m1) { VU = (this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) diff --git a/source/source_lcao/module_dftu/dftu_yukawa.cpp b/source/source_lcao/module_dftu/dftu_yukawa.cpp index e743909243..9f9c8ff75f 100644 --- a/source/source_lcao/module_dftu/dftu_yukawa.cpp +++ b/source/source_lcao/module_dftu/dftu_yukawa.cpp @@ -64,7 +64,7 @@ void Plus_U::cal_slater_Fk(const UnitCell& ucell, { ModuleBase::TITLE("Plus_U", "cal_slater_Fk"); - if (use_yukawa) + if (use_yukawa_) { for (int chi = 0; chi < ucell.atoms[T].l_nchi[L]; chi++) { @@ -111,7 +111,7 @@ void Plus_U::cal_slater_Fk(const UnitCell& ucell, void Plus_U::cal_slater_UJ(const UnitCell& ucell, double** rho, const int& nrxx) { ModuleBase::TITLE("Plus_U", "cal_slater_UJ"); - if (!use_yukawa) + if (!use_yukawa_) { return; } diff --git a/source/source_lcao/module_dftu/test/dftu_lcao_test.cpp b/source/source_lcao/module_dftu/test/dftu_lcao_test.cpp index d782609039..f89a4351d7 100644 --- a/source/source_lcao/module_dftu/test/dftu_lcao_test.cpp +++ b/source/source_lcao/module_dftu/test/dftu_lcao_test.cpp @@ -111,6 +111,15 @@ class DFTUTest : public ::testing::Test delete[] ucell.atoms; } + // Helper for TEST_F bodies: gtest-derived classes do not inherit + // the friend declaration, so direct dftu.occ_mat[...] access from + // TestBody would fail to compile. This wrapper runs inside + // DFTUTest, which is a friend of Plus_U_Base. + double occ_mat_c(int iat, int spin, int icc) const + { + return dftu.occ_mat[iat][2][0][spin].c[icc]; + } + #ifdef __MPI void init_parav() { @@ -172,7 +181,7 @@ TEST_F(DFTUTest, constructHRd2d) { for (int icc = 0; icc < 25; icc++) { - EXPECT_NEAR(dftu.occ_mat[iat][2][0][0].c[icc], 0.5, 1e-10); + EXPECT_NEAR(occ_mat_c(iat, 0, icc), 0.5, 1e-10); } } // check the value of HR @@ -230,7 +239,7 @@ TEST_F(DFTUTest, constructHRd2cd) { for (int icc = 0; icc < 25; icc++) { - EXPECT_NEAR(dftu.occ_mat[iat][2][0][0].c[icc], 0.5, 1e-10); + EXPECT_NEAR(occ_mat_c(iat, 0, icc), 0.5, 1e-10); } } // check the value of HR @@ -263,7 +272,7 @@ TEST_F(DFTUTest, constructHRd2cd) { for (int icc = 0; icc < 25; icc++) { - EXPECT_NEAR(dftu.occ_mat[iat][2][0][1].c[icc], 0.5, 1e-10); + EXPECT_NEAR(occ_mat_c(iat, 1, icc), 0.5, 1e-10); } } } diff --git a/source/source_lcao/setup_dftu_lcao.cpp b/source/source_lcao/setup_dftu_lcao.cpp index 307fb21379..34b9867706 100644 --- a/source/source_lcao/setup_dftu_lcao.cpp +++ b/source/source_lcao/setup_dftu_lcao.cpp @@ -61,7 +61,7 @@ void finish_dftu_lcao(const int iter, /// new DFT+U method calculates energy in Hamiltonian if (dft_plus_u == 2) { - if (dftu_ptr->occ_mat_ctrl != 2) + if (dftu_ptr->get_occ_mat_ctrl() != 2) { dftu_cal_occup_m(iter, ucell, dm_vec, kv, mixing_beta, static_cast*>(hamilt_lcao_ptr), *dftu_ptr); diff --git a/source/source_pw/module_pwdft/dftu_base.cpp b/source/source_pw/module_pwdft/dftu_base.cpp index abc2d918e8..e7b8343337 100644 --- a/source/source_pw/module_pwdft/dftu_base.cpp +++ b/source/source_pw/module_pwdft/dftu_base.cpp @@ -54,7 +54,7 @@ void Plus_U_Base::init_base(UnitCell& cell, this->nspin = nspin; this->orbital_corr = orbital_corr; - this->use_yukawa = yukawa_potential; + this->use_yukawa_ = yukawa_potential; this->uramping = uramping; this->occ_mat_ctrl = occ_mat_ctrl; this->mixing_dftu = mixing_dftu; @@ -178,7 +178,7 @@ void Plus_U_Base::init_base(UnitCell& cell, this->uom_array.resize(pot_index, 0.0); this->uom_save.resize(pot_index, 0.0); - if (use_yukawa) + if (use_yukawa_) { this->Fk.resize(cell.ntype); @@ -247,7 +247,7 @@ void Plus_U_Base::init_base(UnitCell& cell, void Plus_U_Base::uramping_update() { // Yukawa calculates U directly every iteration, no need for ramping - if (use_yukawa) { + if (use_yukawa_) { return; } // if uramping < 0.1, use the original U @@ -272,7 +272,7 @@ void Plus_U_Base::uramping_update() bool Plus_U_Base::u_converged() { // Yukawa calculates U directly every iteration, always considered converged - if (use_yukawa) { + if (use_yukawa_) { return true; } for (int i = 0; i < static_cast(this->u_target.size()); i++) diff --git a/source/source_pw/module_pwdft/dftu_base.h b/source/source_pw/module_pwdft/dftu_base.h index 2f17e535ef..91aad6e211 100644 --- a/source/source_pw/module_pwdft/dftu_base.h +++ b/source/source_pw/module_pwdft/dftu_base.h @@ -9,8 +9,12 @@ #include +class DFTUTest; + class Plus_U_Base { + friend class DFTUTest; + //============================================================= // public section //============================================================= @@ -24,7 +28,7 @@ class Plus_U_Base const int nspin, const std::vector& orbital_corr, const bool yukawa_potential, - const std::string& global_read_in_dir, + const std::string& global_readin_dir, const std::string& global_out_dir, const std::string& init_chg, const std::string& device, @@ -37,15 +41,7 @@ class Plus_U_Base void uramping_update(); bool u_converged(); - std::vector u_current; - std::vector u_target; - std::vector orbital_corr; - double uramping = 0.0; - int occ_mat_ctrl = 0; - int mixing_dftu = 0; - int nspin = 0; - - // --- Accessors --- + // --- Accessors for U values and orbital configuration --- double get_u_current(int it) const { return u_current[it]; } double get_u_target(int it) const { return u_target[it]; } int get_num_u_types() const { return static_cast(u_current.size()); } @@ -53,6 +49,11 @@ class Plus_U_Base bool has_correlated_orbital(int it) const { return orbital_corr[it] != -1; } const int* get_orbital_corr_data() const { return orbital_corr.data(); } + // --- Accessors for DFT+U configuration --- + double get_uramping() const { return uramping; } + int get_occ_mat_ctrl() const { return occ_mat_ctrl; } + bool use_yukawa() const { return use_yukawa_; } + double get_U_Yukawa(int it, int l, int n) const { return U_Yukawa[it][l][n]; } double get_J_Yukawa(int it, int l, int n) const { return J_Yukawa[it][l][n]; } @@ -109,8 +110,6 @@ class Plus_U_Base } // dftu can be calculated only after occ_mat has been initialized - bool occ_mat_initialized = false; - bool is_occ_mat_initialized() const { return occ_mat_initialized; } void mark_occ_mat_initialized() { occ_mat_initialized = true; } void mark_occ_mat_dirty() { occ_mat_initialized = false; } @@ -142,23 +141,28 @@ class Plus_U_Base void set_occ_mat_flat(const int iat, const int l, const int spin, const std::vector& occ); - // local occupancy matrix of the correlated subspace - std::vector>>> occ_mat; - std::vector>>> occ_mat_save; + protected: + // --- U values and orbital configuration (set in init_base) --- + std::vector u_current; + std::vector u_target; + std::vector orbital_corr; + + // --- DFT+U configuration flags --- + double uramping = 0.0; + int occ_mat_ctrl = 0; + int mixing_dftu = 0; + int nspin = 0; + bool use_yukawa_ = false; - //============================================================= - // output() and write_occup_m() have been extracted to free functions - // in source_pw/module_pwdft/dftu_output.cpp as dftu_io::output and - // dftu_io::write_occup_m. They access Plus_U_Base via public getters. - // mohan refactored 2025-11-08 - //============================================================= + // --- State flags --- + // dftu can be calculated only after occ_mat has been initialized + bool occ_mat_initialized = false; - bool use_yukawa = false; + // --- Occupation matrices --- + std::vector>>> occ_mat; + std::vector>>> occ_mat_save; - //============================================================= - // protected section - //============================================================= - protected: + // --- Internal state --- double energy_u = 0.0; int cal_type = 3; @@ -193,11 +197,6 @@ class Plus_U_Base void local_occup_bcast(const UnitCell& ucell, int nspin, int npol); - - //============================================================= - // In dftu_yukawa.cpp - // Relevant for calculating U using Yukawa potential - //============================================================= }; diff --git a/source/source_pw/module_pwdft/dftu_output.cpp b/source/source_pw/module_pwdft/dftu_output.cpp index 0a01b3ec5a..7236804449 100644 --- a/source/source_pw/module_pwdft/dftu_output.cpp +++ b/source/source_pw/module_pwdft/dftu_output.cpp @@ -113,7 +113,7 @@ void output(const Plus_U_Base& dftu, continue; } - if (!dftu.use_yukawa) + if (!dftu.use_yukawa()) { GlobalV::ofs_running << " Type=" << T+1 << " L=" << L << " ORBITAL=" << 0 << " U=" << dftu.get_u_current(T) * ModuleBase::Ry_to_eV << " eV" << std::endl; diff --git a/source/source_pw/module_pwdft/setup_dftu_pw.cpp b/source/source_pw/module_pwdft/setup_dftu_pw.cpp index fbab39d9db..93b93b03f7 100644 --- a/source/source_pw/module_pwdft/setup_dftu_pw.cpp +++ b/source/source_pw/module_pwdft/setup_dftu_pw.cpp @@ -25,7 +25,7 @@ void iter_init_dftu_pw(const int iter, return; } - if (dftu.occ_mat_ctrl != 2) + if (dftu.get_occ_mat_ctrl() != 2) { dftu.cal_occ_pw(iter, psi, wg, ucell, p_chgmix, isk); } From 25314b40c48609e95891ae1050c58af71ae53959 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 09:28:33 +0800 Subject: [PATCH 03/23] =?UTF-8?q?=E9=87=8D=E6=9E=84=20dftu=5Ffolding.cpp?= =?UTF-8?q?=EF=BC=9A=E6=8A=BD=E5=8F=96=E9=82=BB=E5=B1=85=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E4=B8=8E=E7=9F=A9=E9=98=B5=E7=B4=A2=E5=BC=95=E4=B8=A4=E4=B8=AA?= =?UTF-8?q?=E8=BE=85=E5=8A=A9=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 fold_dSR_gamma 和 folding_matrix_k 中的重复代码抽取为两个 private 成员函数,消除重复逻辑并统一行为。 新增辅助函数(声明于 dftu_lcao.h,实现于 dftu_folding.cpp): - is_adjacent_pair(): 原子对相邻性判断(直接截断 + 三体重叠桥接) - get_linear_index(): 按 ks_solver 选择行/列主序的本地矩阵索引 主函数精简效果: - fold_dSR_gamma: 113 行 -> 85 行 - folding_matrix_k: 156 行 -> 109 行 - 邻居判断逻辑副本数: 2 -> 1 - 矩阵索引逻辑副本数: 2 -> 1(且修复了 G 版写死列主序的不一致) 顺手清理: - 删除 fold_dSR_gamma 中未使用的 iat0、start0 声明(死代码) - 删除 folding_matrix_k 中冗余的 atom1 重复声明 - 删除两个函数中不再需要的 dtau/dtau1/dtau2/tau0 局部变量 - 统一了 G 版的矩阵索引判断(原本硬编码列主序,现在和 K 版一致) 公共 API 与调用点: - fold_dSR_gamma / folding_matrix_k / folding_matrix_k_new 签名不变 - 调用方 dftu_force.cpp、dftu_occup.cpp 无需修改 验证: - python3 tools/03_code_analysis/agent_governance_check.py --staged 结果: no findings - g++ -std=c++11 -fsyntax-only(针对 dftu_folding.cpp、dftu_lcao.h、 dftu_force.cpp、dftu_occup.cpp)均通过,无错误无警告 - 未做完整 CMake build 与 ctest 运行时测试,因当前环境无 build 目录 (仅有预编译的 abacus_max_para 可执行文件) --- .../source_lcao/module_dftu/dftu_folding.cpp | 257 ++++++++---------- source/source_lcao/module_dftu/dftu_lcao.h | 17 ++ 2 files changed, 130 insertions(+), 144 deletions(-) diff --git a/source/source_lcao/module_dftu/dftu_folding.cpp b/source/source_lcao/module_dftu/dftu_folding.cpp index 4958f9ad59..c055767855 100644 --- a/source/source_lcao/module_dftu/dftu_folding.cpp +++ b/source/source_lcao/module_dftu/dftu_folding.cpp @@ -7,6 +7,50 @@ #include "source_hamilt/module_hcontainer/hcontainer.h" #include "source_hamilt/module_hcontainer/hcontainer_funcs.h" +bool Plus_U::is_adjacent_pair(const UnitCell& ucell, + const Grid_Driver& gd, + const int T1, + const int T2, + const ModuleBase::Vector3& tau1, + const ModuleBase::Vector3& tau2) const +{ + const ModuleBase::Vector3 dtau = tau2 - tau1; + const double distance = dtau.norm() * ucell.lat0; + const double rcut = orb_cutoff_[T1] + orb_cutoff_[T2]; + if (distance < rcut) + { + return true; + } + // Three-body bridging: pair is not directly adjacent but shares a + // common nonlocal projector center T0 that overlaps both orbitals. + for (int ad0 = 0; ad0 < gd.getAdjacentNum() + 1; ++ad0) + { + const int T0 = gd.getType(ad0); + const int I0 = gd.getNatom(ad0); + const ModuleBase::Vector3 tau0 = gd.getAdjacentTau(ad0); + const double distance1 = (tau0 - tau1).norm() * ucell.lat0; + const double distance2 = (tau0 - tau2).norm() * ucell.lat0; + const double rcut1 = orb_cutoff_[T1] + ucell.infoNL->get_rcut_max(T0); + const double rcut2 = orb_cutoff_[T2] + ucell.infoNL->get_rcut_max(T0); + if (distance1 < rcut1 && distance2 < rcut2) + { + return true; + } + } + return false; +} + +int Plus_U::get_linear_index(const int mu, + const int nu, + const Parallel_Orbitals& pv) const +{ + if (ModuleBase::GlobalFunc::IS_COLUMN_MAJOR_KS_SOLVER(this->ks_solver)) + { + return mu + nu * pv.nrow; + } + return mu * pv.ncol + nu; +} + void Plus_U::fold_dSR_gamma(const UnitCell& ucell, const Parallel_Orbitals& pv, const Grid_Driver* gd, @@ -37,8 +81,7 @@ void Plus_U::fold_dSR_gamma(const UnitCell& ucell, } int nnr = 0; - ModuleBase::Vector3 tau1, tau2, dtau; - ModuleBase::Vector3 dtau1, dtau2, tau0; + ModuleBase::Vector3 tau1, tau2; for (int T1 = 0; T1 < ucell.ntype; ++T1) { @@ -52,68 +95,41 @@ void Plus_U::fold_dSR_gamma(const UnitCell& ucell, { const int T2 = gd->getType(ad); const int I2 = gd->getNatom(ad); - const int start2 = ucell.itiaiw2iwt(T2, I2, 0); Atom* atom2 = &ucell.atoms[T2]; tau2 = gd->getAdjacentTau(ad); - dtau = tau2 - tau1; - double distance = dtau.norm() * ucell.lat0; - double rcut = orb_cutoff_[T1] + orb_cutoff_[T2]; - bool adj = false; - if (distance < rcut) - { - adj = true; - } - else if (distance >= rcut) + + if (!is_adjacent_pair(ucell, *gd, T1, T2, tau1, tau2)) { - for (int ad0 = 0; ad0 < gd->getAdjacentNum() + 1; ++ad0) - { - const int T0 = gd->getType(ad0); - const int I0 = gd->getNatom(ad0); - const int iat0 = ucell.itia2iat(T0, I0); - const int start0 = ucell.itiaiw2iwt(T0, I0, 0); - tau0 = gd->getAdjacentTau(ad0); - dtau1 = tau0 - tau1; - dtau2 = tau0 - tau2; - double distance1 = dtau1.norm() * ucell.lat0; - double distance2 = dtau2.norm() * ucell.lat0; - double rcut1 = orb_cutoff_[T1] + ucell.infoNL->get_rcut_max(T0); - double rcut2 = orb_cutoff_[T2] + ucell.infoNL->get_rcut_max(T0); - if (distance1 < rcut1 && distance2 < rcut2) - { - adj = true; - break; - } - } + continue; } - if (adj) + const int start2 = ucell.itiaiw2iwt(T2, I2, 0); + for (int jj = 0; jj < atom1->nw * this->npol; ++jj) { - for (int jj = 0; jj < atom1->nw * this->npol; ++jj) + const int jj0 = jj / this->npol; + const int iw1_all = start1 + jj0; + const int mu = pv.global2local_row(iw1_all); + if (mu < 0) + { + continue; + } + + for (int kk = 0; kk < atom2->nw * this->npol; ++kk) { - const int jj0 = jj / this->npol; - const int iw1_all = start1 + jj0; - const int mu = pv.global2local_row(iw1_all); - if (mu < 0) - { - continue; - } - - for (int kk = 0; kk < atom2->nw * this->npol; ++kk) + const int kk0 = kk / this->npol; + const int iw2_all = start2 + kk0; + const int nu = pv.global2local_col(iw2_all); + if (nu < 0) { - const int kk0 = kk / this->npol; - const int iw2_all = start2 + kk0; - const int nu = pv.global2local_col(iw2_all); - if (nu < 0) - { - continue; - } - - dSR_gamma[nu * pv.nrow + mu] += dS_ptr[nnr] * dh_r[nnr * 3 + dim2]; - - ++nnr; - } // kk - } // jj - } // adj + continue; + } + + const int iic = get_linear_index(mu, nu, pv); + dSR_gamma[iic] += dS_ptr[nnr] * dh_r[nnr * 3 + dim2]; + + ++nnr; + } // kk + } // jj } // ad } // I1 } // T1 @@ -150,14 +166,9 @@ void Plus_U::folding_matrix_k(const UnitCell& ucell, } int nnr = 0; - ModuleBase::Vector3 dtau; ModuleBase::Vector3 tau1; ModuleBase::Vector3 tau2; - ModuleBase::Vector3 dtau1; - ModuleBase::Vector3 dtau2; - ModuleBase::Vector3 tau0; - for (int T1 = 0; T1 < ucell.ntype; ++T1) { Atom* atom1 = &ucell.atoms[T1]; @@ -165,7 +176,6 @@ void Plus_U::folding_matrix_k(const UnitCell& ucell, { tau1 = atom1->tau[I1]; gd.Find_atom(ucell, tau1, T1, I1); - Atom* atom1 = &ucell.atoms[T1]; const int start1 = ucell.itiaiw2iwt(T1, I1, 0); // (2) search among all adjacent atoms. @@ -176,100 +186,59 @@ void Plus_U::folding_matrix_k(const UnitCell& ucell, Atom* atom2 = &ucell.atoms[T2]; tau2 = gd.getAdjacentTau(ad); - dtau = tau2 - tau1; - double distance = dtau.norm() * ucell.lat0; - double rcut = orb_cutoff_[T1] + orb_cutoff_[T2]; - - bool adj = false; - if (distance < rcut) + if (!is_adjacent_pair(ucell, gd, T1, T2, tau1, tau2)) { - adj = true; + continue; } - else if (distance >= rcut) + + // (3) calculate the nu of atom (T2, I2) + const int start2 = ucell.itiaiw2iwt(T2, I2, 0); + //------------------------------------------------ + // exp(k dot dR) + // dR is the index of box in Crystal coordinates + //------------------------------------------------ + ModuleBase::Vector3 dR(gd.getBox(ad).x, gd.getBox(ad).y, gd.getBox(ad).z); + const double arg = (kvec_d * dR) * ModuleBase::TWO_PI; + const std::complex kphase = std::complex(cos(arg), sin(arg)); + + //-------------------------------------------------- + // calculate how many matrix elements are in + // this processor. + //-------------------------------------------------- + for (int ii = 0; ii < atom1->nw * this->npol; ii++) { - for (int ad0 = 0; ad0 < gd.getAdjacentNum() + 1; ++ad0) + // the index of orbitals in this processor + const int iw1_all = start1 + ii; + const int mu = pv.global2local_row(iw1_all); + if (mu < 0) { - const int T0 = gd.getType(ad0); - const int I0 = gd.getNatom(ad0); - - tau0 = gd.getAdjacentTau(ad0); - dtau1 = tau0 - tau1; - dtau2 = tau0 - tau2; + continue; + } - double distance1 = dtau1.norm() * ucell.lat0; - double distance2 = dtau2.norm() * ucell.lat0; + for (int jj = 0; jj < atom2->nw * this->npol; jj++) + { + int iw2_all = start2 + jj; + const int nu = pv.global2local_col(iw2_all); + if (nu < 0) + { + continue; + } - double rcut1 = orb_cutoff_[T1] + ucell.infoNL->get_rcut_max(T0); - double rcut2 = orb_cutoff_[T2] + ucell.infoNL->get_rcut_max(T0); + const int iic = get_linear_index(mu, nu, pv); - if (distance1 < rcut1 && distance2 < rcut2) + if (dim1 <= 3) { - adj = true; - break; + mat_k[iic] += mat_ptr[nnr] * kphase; } - } - } - - if (adj) - { - // (3) calculate the nu of atom (T2, I2) - const int start2 = ucell.itiaiw2iwt(T2, I2, 0); - //------------------------------------------------ - // exp(k dot dR) - // dR is the index of box in Crystal coordinates - //------------------------------------------------ - ModuleBase::Vector3 dR(gd.getBox(ad).x, gd.getBox(ad).y, gd.getBox(ad).z); - const double arg = (kvec_d * dR) * ModuleBase::TWO_PI; - const std::complex kphase = std::complex(cos(arg), sin(arg)); - - //-------------------------------------------------- - // calculate how many matrix elements are in - // this processor. - //-------------------------------------------------- - for (int ii = 0; ii < atom1->nw * this->npol; ii++) - { - // the index of orbitals in this processor - const int iw1_all = start1 + ii; - const int mu = pv.global2local_row(iw1_all); - if (mu < 0) - { - continue; - } - - for (int jj = 0; jj < atom2->nw * this->npol; jj++) + else { - int iw2_all = start2 + jj; - const int nu = pv.global2local_col(iw2_all); - if (nu < 0) - { - continue; - } - - int iic = 0; - if (ModuleBase::GlobalFunc::IS_COLUMN_MAJOR_KS_SOLVER(this->ks_solver)) - { - iic = mu + nu * pv.nrow; - } - else - { - iic = mu * pv.ncol + nu; - } - - if (dim1 <= 3) - { - mat_k[iic] += mat_ptr[nnr] * kphase; - } - else - { - mat_k[iic] += mat_ptr[nnr] * fsr.DH_r[nnr * 3 + dim2] * kphase; - } - - ++nnr; - } // kk - } // jj - } // adj + mat_k[iic] += mat_ptr[nnr] * fsr.DH_r[nnr * 3 + dim2] * kphase; + } + ++nnr; + } // jj + } // ii } // ad } // I1 } // T1 diff --git a/source/source_lcao/module_dftu/dftu_lcao.h b/source/source_lcao/module_dftu/dftu_lcao.h index d617814a87..213458b331 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.h +++ b/source/source_lcao/module_dftu/dftu_lcao.h @@ -140,6 +140,23 @@ class Plus_U : public Plus_U_Base // Subroutines for folding S and dS matrix //============================================================= + /// @brief Judge whether atom pair (T1,I1) and (T2,I2,tau2) are adjacent + /// by direct orbital cutoff overlap or three-body bridging via a + /// common nonlocal projector center T0. + /// @return true if the pair should be processed + bool is_adjacent_pair(const UnitCell& ucell, + const Grid_Driver& gd, + const int T1, + const int T2, + const ModuleBase::Vector3& tau1, + const ModuleBase::Vector3& tau2) const; + + /// @brief Get the linear index of local matrix element (mu, nu) based on + /// ks_solver (column-major or row-major). + int get_linear_index(const int mu, + const int nu, + const Parallel_Orbitals& pv) const; + void fold_dSR_gamma(const UnitCell& ucell, const Parallel_Orbitals& pv, const Grid_Driver* gd, From 08661e4091541361a949d390f47ab2aa97d87a4b Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 10:35:15 +0800 Subject: [PATCH 04/23] refactor(dftu_pw): merge CPU/GPU branches into template, drop unused iter param The CPU and GPU branches of cal_occ_pw (formerly L32-110 and L113-188) were near-verbatim duplicates, differing only in the device template parameter of OnsiteProjector and Psi. Merge them into a single template member function accumulate_occ_one_k, with explicit instantiation controlling CPU always compiled and GPU only under __CUDA/__ROCM. Also drop the iter parameter from cal_occ_pw signature since it was never used in the function body; update the call site in setup_dftu_pw.cpp accordingly. Files changed: - source/source_pw/module_pwdft/dftu_base.h - drop const int iter param from cal_occ_pw declaration - add template member declaration accumulate_occ_one_k - source/source_pw/module_pwdft/dftu_pw.cpp - drop iter param from cal_occ_pw implementation - replace ~80 lines of CPU/GPU duplicate code with two template calls - add accumulate_occ_one_k template definition and explicit instantiations at end of file - source/source_pw/module_pwdft/setup_dftu_pw.cpp - drop iter argument at call site Effects: - ~80 lines of duplicate code removed from dftu_pw.cpp - CPU/GPU inner loops (iat/ib/m1/m2 + nspin==4 Pauli block assembly) now maintained in a single template implementation - psi::Psi visibility confirmed transitively via onsite_proj.h Pending verification (build delegated to user): - make module_pwdft incremental build - DFT+U ctest (e.g. MODULE_DFTU label) - GPU build path (__CUDA/__ROCM) explicit instantiation --- source/source_pw/module_pwdft/dftu_base.h | 12 +- source/source_pw/module_pwdft/dftu_pw.cpp | 247 +++++++----------- .../source_pw/module_pwdft/setup_dftu_pw.cpp | 2 +- 3 files changed, 105 insertions(+), 156 deletions(-) diff --git a/source/source_pw/module_pwdft/dftu_base.h b/source/source_pw/module_pwdft/dftu_base.h index 91aad6e211..3c10b3e6ea 100644 --- a/source/source_pw/module_pwdft/dftu_base.h +++ b/source/source_pw/module_pwdft/dftu_base.h @@ -61,10 +61,9 @@ class Plus_U_Base void set_energy(const double &e) { energy_u = e; } void set_double_energy() { energy_u *= 2.0; } - /// interface for PW base + /// interface for PW basis /// calculate the local occupation number matrix for PW based wave functions - void cal_occ_pw(const int iter, - const void* psi_in, + void cal_occ_pw(const void* psi_in, const ModuleBase::matrix& wg_in, const UnitCell& cell, Charge_Mixing* p_chgmix, @@ -178,6 +177,13 @@ class Plus_U_Base void mix_occ_mat(const UnitCell& ucell, const double& mixing_beta); void set_occ_mat(const UnitCell& ucell); + /// accumulate occ_mat from psi for all k-points (per-device template) + template + void accumulate_occ_one_k(const void* psi_in, + const ModuleBase::matrix& wg_in, + const UnitCell& cell, + const int* isk); + std::vector> eff_pot_pw; std::vector eff_pot_pw_index; std::vector uom_array; diff --git a/source/source_pw/module_pwdft/dftu_pw.cpp b/source/source_pw/module_pwdft/dftu_pw.cpp index 2a03d47169..e256e7c78f 100644 --- a/source/source_pw/module_pwdft/dftu_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_pw.cpp @@ -18,8 +18,7 @@ /// nspin=4 (npol=2): spinor calculation; /// occ_mat has a single matrix of size (2*tlp1) x (2*tlp1) per atom /// storing all 4 Pauli blocks contiguously. -void Plus_U_Base::cal_occ_pw(const int iter, - const void* psi_in, +void Plus_U_Base::cal_occ_pw(const void* psi_in, const ModuleBase::matrix& wg_in, const UnitCell& cell, Charge_Mixing* p_chgmix, @@ -31,160 +30,12 @@ void Plus_U_Base::cal_occ_pw(const int iter, if(this->device == "cpu") { - auto* onsite_p = projectors::OnsiteProjector::get_instance(); - const psi::Psi>* psi_p = (const psi::Psi>*)psi_in; - const int nbands = psi_p->get_nbands(); - const int npol = psi_p->get_npol(); - for(int ik = 0; ik < psi_p->get_nk(); ik++) - { - int is = (this->nspin == 2) ? isk[ik] : 0; - psi_p->fix_k(ik); - onsite_p->tabulate_atomic(ik); - - onsite_p->overlap_proj_psi(nbands*npol, psi_p->get_pointer()); - const std::complex* becp = onsite_p->get_h_becp(); - int nkb = onsite_p->get_size_becp() / nbands / npol; - - int begin_ih = 0; - for(int iat = 0; iat < cell.nat; iat++) - { - const int it = cell.iat2it[iat]; - const int nh = onsite_p->get_nh(iat); - const int target_l = get_orbital_corr(it); - if(!has_correlated_orbital(it)) - { - begin_ih += nh; - continue; - } - const int m_begin = target_l * target_l; - const int tlp1 = 2 * target_l + 1; - const int tlp1_2 = tlp1 * tlp1; - if(this->nspin == 4) - { - for(int ib = 0;ib occ[4]; - occ[0] = weight * conj(becp[index_m1]) * becp[index_m2]; - occ[1] = weight * conj(becp[index_m1]) * becp[index_m2 + nkb]; - occ[2] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2]; - occ[3] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb]; - this->occ_mat[iat][target_l][0][0].c[ind_m1m2] += (occ[0] + occ[3]).real(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real(); - ind_m1m2++; - } - } - }// ib - } - else // nspin=1 or nspin=2 - { - for(int ib = 0;ibocc_mat[iat][target_l][0][is].c[ind_m1m2] += weight * (conj(becp[index_m1]) * becp[index_m2]).real(); - ind_m1m2++; - } - } - }// ib - } - begin_ih += nh; - }// iat - - }// ik + this->accumulate_occ_one_k(psi_in, wg_in, cell, isk); } #if defined(__CUDA) || defined(__ROCM) else { - auto* onsite_p = projectors::OnsiteProjector::get_instance(); - const psi::Psi, base_device::DEVICE_GPU>* psi_p = (const psi::Psi, base_device::DEVICE_GPU>*)psi_in; - const int nbands = psi_p->get_nbands(); - const int npol = psi_p->get_npol(); - for(int ik = 0; ik < psi_p->get_nk(); ik++) - { - int is = (this->nspin == 2) ? isk[ik] : 0; - psi_p->fix_k(ik); - onsite_p->tabulate_atomic(ik); - - onsite_p->overlap_proj_psi(nbands*npol, psi_p->get_pointer()); - const std::complex* becp = onsite_p->get_h_becp(); - int nkb = onsite_p->get_size_becp() / nbands / npol; - int begin_ih = 0; - for(int iat = 0; iat < cell.nat; iat++) - { - const int it = cell.iat2it[iat]; - const int nh = onsite_p->get_nh(iat); - const int target_l = get_orbital_corr(it); - if(!has_correlated_orbital(it)) - { - begin_ih += nh; - continue; - } - const int m_begin = target_l * target_l; - const int tlp1 = 2 * target_l + 1; - const int tlp1_2 = tlp1 * tlp1; - if(this->nspin == 4) - { - for(int ib = 0;ib occ[4]; - occ[0] = weight * conj(becp[index_m1]) * becp[index_m2]; - occ[1] = weight * conj(becp[index_m1]) * becp[index_m2 + nkb]; - occ[2] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2]; - occ[3] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb]; - this->occ_mat[iat][target_l][0][0].c[ind_m1m2] += (occ[0] + occ[3]).real(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real(); - ind_m1m2++; - } - } - }// ib - } - else // nspin=1 or nspin=2 - { - for(int ib = 0;ibocc_mat[iat][target_l][0][is].c[ind_m1m2] += weight * (conj(becp[index_m1]) * becp[index_m2]).real(); - ind_m1m2++; - } - } - }// ib - } - begin_ih += nh; - }// iat - }// ik + this->accumulate_occ_one_k(psi_in, wg_in, cell, isk); } #endif @@ -347,3 +198,95 @@ void Plus_U_Base::cal_occ_pw(const int iter, ModuleBase::timer::end("Plus_U_Base", "cal_occ_pw"); } + +template +void Plus_U_Base::accumulate_occ_one_k(const void* psi_in, + const ModuleBase::matrix& wg_in, + const UnitCell& cell, + const int* isk) +{ + auto* onsite_p = projectors::OnsiteProjector::get_instance(); + const psi::Psi, Device>* psi_p = + (const psi::Psi, Device>*)psi_in; + const int nbands = psi_p->get_nbands(); + const int npol = psi_p->get_npol(); + for(int ik = 0; ik < psi_p->get_nk(); ik++) + { + int is = (this->nspin == 2) ? isk[ik] : 0; + psi_p->fix_k(ik); + onsite_p->tabulate_atomic(ik); + + onsite_p->overlap_proj_psi(nbands*npol, psi_p->get_pointer()); + const std::complex* becp = onsite_p->get_h_becp(); + int nkb = onsite_p->get_size_becp() / nbands / npol; + + int begin_ih = 0; + for(int iat = 0; iat < cell.nat; iat++) + { + const int it = cell.iat2it[iat]; + const int nh = onsite_p->get_nh(iat); + const int target_l = get_orbital_corr(it); + if(!has_correlated_orbital(it)) + { + begin_ih += nh; + continue; + } + const int m_begin = target_l * target_l; + const int tlp1 = 2 * target_l + 1; + const int tlp1_2 = tlp1 * tlp1; + if(this->nspin == 4) + { + for(int ib = 0; ib < nbands; ib++) + { + const double weight = wg_in(ik, ib); + int ind_m1m2 = 0; + for(int m1 = 0; m1 < tlp1; m1++) + { + const int index_m1 = ib*npol*nkb + begin_ih + m_begin + m1; + for(int m2 = 0; m2 < tlp1; m2++) + { + const int index_m2 = ib*npol*nkb + begin_ih + m_begin + m2; + std::complex occ[4]; + occ[0] = weight * conj(becp[index_m1]) * becp[index_m2]; + occ[1] = weight * conj(becp[index_m1]) * becp[index_m2 + nkb]; + occ[2] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2]; + occ[3] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb]; + this->occ_mat[iat][target_l][0][0].c[ind_m1m2] += (occ[0] + occ[3]).real(); + this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real(); + this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag(); + this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real(); + ind_m1m2++; + } + } + } + } + else // nspin=1 or nspin=2 + { + for(int ib = 0; ib < nbands; ib++) + { + const double weight = wg_in(ik, ib); + int ind_m1m2 = 0; + for(int m1 = 0; m1 < tlp1; m1++) + { + const int index_m1 = ib*nkb + begin_ih + m_begin + m1; + for(int m2 = 0; m2 < tlp1; m2++) + { + const int index_m2 = ib*nkb + begin_ih + m_begin + m2; + this->occ_mat[iat][target_l][0][is].c[ind_m1m2] += weight * (conj(becp[index_m1]) * becp[index_m2]).real(); + ind_m1m2++; + } + } + } + } + begin_ih += nh; + } + } +} + +// explicit instantiations +template void Plus_U_Base::accumulate_occ_one_k( + const void*, const ModuleBase::matrix&, const UnitCell&, const int*); +#if defined(__CUDA) || defined(__ROCM) +template void Plus_U_Base::accumulate_occ_one_k( + const void*, const ModuleBase::matrix&, const UnitCell&, const int*); +#endif diff --git a/source/source_pw/module_pwdft/setup_dftu_pw.cpp b/source/source_pw/module_pwdft/setup_dftu_pw.cpp index 93b93b03f7..a49a99f4d6 100644 --- a/source/source_pw/module_pwdft/setup_dftu_pw.cpp +++ b/source/source_pw/module_pwdft/setup_dftu_pw.cpp @@ -27,7 +27,7 @@ void iter_init_dftu_pw(const int iter, if (dftu.get_occ_mat_ctrl() != 2) { - dftu.cal_occ_pw(iter, psi, wg, ucell, p_chgmix, isk); + dftu.cal_occ_pw(psi, wg, ucell, p_chgmix, isk); } dftu_io::output(dftu, ucell, PARAM.inp.out_chg[0], PARAM.globalv.global_out_dir, PARAM.inp.nspin, PARAM.globalv.npol); } From 9e5caa437634558a5ff7d8c96c17802cfbd34e3c Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 10:52:17 +0800 Subject: [PATCH 05/23] refactor(dftu_folding): extract Plus_U folding helpers into free functions The five private member functions of Plus_U defined in dftu_folding.cpp (is_adjacent_pair, get_linear_index, fold_dSR_gamma, folding_matrix_k, folding_matrix_k_new) were pure folding helpers that only read data members without relying on class invariants. Extract them into free functions declared in the new dftu_folding.h, removing them from the Plus_U class API in dftu_lcao.h. The free functions live in namespace dftu_folding and take the data they need (orb_cutoff, ks_solver, npol, gamma_only_local, nspin) as direct parameters instead of receiving a Plus_U reference. Since all callers are Plus_U member functions, they read this->member directly and pass the values in, so no getters or friendship are required. The function names drop the dftu_ prefix since the namespace already qualifies them (call sites read dftu_folding::folding_matrix_k(...)). No Plus_U members are deleted: three of the five (npol, gamma_only_local, nspin) are still read by other Plus_U member functions, and the other two (orb_cutoff_, ks_solver) are kept to avoid PARAM coupling or cascading signature changes through the public API. Also rename the include guard of dftu_lcao.h from DFTU_H to DFTU_LCAO_H to match the filename (consistent with the new dftu_folding.h guard DFTU_FOLDING_H); confirmed no other translation unit references DFTU_H. Files changed: - source/source_lao/module_dftu/dftu_folding.h (NEW) - declare 5 free function prototypes under __LCAO, wrapped in namespace dftu_folding - source/source_lao/module_dftu/dftu_folding.cpp - rewrite 5 member functions as free functions in namespace dftu_folding, taking data params - member access (this->orb_cutoff_ etc.) replaced by parameters - internal calls use unqualified names within the namespace - source/source_lao/module_dftu/dftu_lcao.h - remove the 5 private member function declarations - rename include guard DFTU_H -> DFTU_LCAO_H - member variables and public API unchanged - source/source_lao/module_dftu/dftu_force.cpp - include dftu_folding.h; update 3 call sites in cal_force_k / cal_stress_k / cal_stress_gamma to dftu_folding::folding_matrix_k / dftu_folding::fold_dSR_gamma - source/source_lao/module_dftu/dftu_occup.cpp - include dftu_folding.h; update 1 call site in cal_occup_m_k to dftu_folding::folding_matrix_k_new Effects: - Plus_U class fully decoupled from folding details; dftu_lcao.h no longer mentions any folding function - No getters, no friend declarations, no member-variable deletion - TITLE/timer labels ("Plus_U", "fold_dSR_gamma" etc.) intentionally preserved to keep profiling tooling stable Verification (partial, full build delegated to user): - cmake --build build_std_para --target dftu -> [100%] Built target dftu - full abacus build and DFTU ctest pending --- .../source_lcao/module_dftu/dftu_folding.cpp | 134 ++++++++++-------- source/source_lcao/module_dftu/dftu_folding.h | 92 ++++++++++++ source/source_lcao/module_dftu/dftu_force.cpp | 10 +- source/source_lcao/module_dftu/dftu_lcao.h | 59 +------- source/source_lcao/module_dftu/dftu_occup.cpp | 3 +- 5 files changed, 178 insertions(+), 120 deletions(-) create mode 100644 source/source_lcao/module_dftu/dftu_folding.h diff --git a/source/source_lcao/module_dftu/dftu_folding.cpp b/source/source_lcao/module_dftu/dftu_folding.cpp index c055767855..feab5ff4d0 100644 --- a/source/source_lcao/module_dftu/dftu_folding.cpp +++ b/source/source_lcao/module_dftu/dftu_folding.cpp @@ -1,4 +1,5 @@ #ifdef __LCAO +#include "dftu_folding.h" #include "dftu_lcao.h" #include "source_base/timer.h" #include "source_io/module_parameter/parameter.h" @@ -7,16 +8,19 @@ #include "source_hamilt/module_hcontainer/hcontainer.h" #include "source_hamilt/module_hcontainer/hcontainer_funcs.h" -bool Plus_U::is_adjacent_pair(const UnitCell& ucell, - const Grid_Driver& gd, - const int T1, - const int T2, - const ModuleBase::Vector3& tau1, - const ModuleBase::Vector3& tau2) const +namespace dftu_folding { + +bool is_adjacent_pair(const std::vector& orb_cutoff, + const UnitCell& ucell, + const Grid_Driver& gd, + const int T1, + const int T2, + const ModuleBase::Vector3& tau1, + const ModuleBase::Vector3& tau2) { const ModuleBase::Vector3 dtau = tau2 - tau1; const double distance = dtau.norm() * ucell.lat0; - const double rcut = orb_cutoff_[T1] + orb_cutoff_[T2]; + const double rcut = orb_cutoff[T1] + orb_cutoff[T2]; if (distance < rcut) { return true; @@ -30,8 +34,8 @@ bool Plus_U::is_adjacent_pair(const UnitCell& ucell, const ModuleBase::Vector3 tau0 = gd.getAdjacentTau(ad0); const double distance1 = (tau0 - tau1).norm() * ucell.lat0; const double distance2 = (tau0 - tau2).norm() * ucell.lat0; - const double rcut1 = orb_cutoff_[T1] + ucell.infoNL->get_rcut_max(T0); - const double rcut2 = orb_cutoff_[T2] + ucell.infoNL->get_rcut_max(T0); + const double rcut1 = orb_cutoff[T1] + ucell.infoNL->get_rcut_max(T0); + const double rcut2 = orb_cutoff[T2] + ucell.infoNL->get_rcut_max(T0); if (distance1 < rcut1 && distance2 < rcut2) { return true; @@ -40,45 +44,49 @@ bool Plus_U::is_adjacent_pair(const UnitCell& ucell, return false; } -int Plus_U::get_linear_index(const int mu, - const int nu, - const Parallel_Orbitals& pv) const +int get_linear_index(const std::string& ks_solver, + const int mu, + const int nu, + const Parallel_Orbitals& pv) { - if (ModuleBase::GlobalFunc::IS_COLUMN_MAJOR_KS_SOLVER(this->ks_solver)) + if (ModuleBase::GlobalFunc::IS_COLUMN_MAJOR_KS_SOLVER(ks_solver)) { return mu + nu * pv.nrow; } return mu * pv.ncol + nu; } -void Plus_U::fold_dSR_gamma(const UnitCell& ucell, - const Parallel_Orbitals& pv, - const Grid_Driver* gd, - double* dsloc_x, - double* dsloc_y, - double* dsloc_z, - double* dh_r, - const int dim1, - const int dim2, - double* dSR_gamma) +void fold_dSR_gamma(int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const UnitCell& ucell, + const Parallel_Orbitals& pv, + const Grid_Driver* gd, + double* dsloc_x, + double* dsloc_y, + double* dsloc_z, + double* dh_r, + const int dim1, + const int dim2, + double* dSR_gamma) { ModuleBase::TITLE("Plus_U", "fold_dSR_gamma"); ModuleBase::GlobalFunc::ZEROS(dSR_gamma, pv.nloc); double* dS_ptr = nullptr; - if(dim1 == 0) - { - dS_ptr = dsloc_x; - } - else if(dim1 == 1) - { - dS_ptr = dsloc_y; - } - else if (dim1 == 2) - { - dS_ptr = dsloc_z; - } + if (dim1 == 0) + { + dS_ptr = dsloc_x; + } + else if (dim1 == 1) + { + dS_ptr = dsloc_y; + } + else if (dim1 == 2) + { + dS_ptr = dsloc_z; + } int nnr = 0; ModuleBase::Vector3 tau1, tau2; @@ -98,15 +106,15 @@ void Plus_U::fold_dSR_gamma(const UnitCell& ucell, Atom* atom2 = &ucell.atoms[T2]; tau2 = gd->getAdjacentTau(ad); - if (!is_adjacent_pair(ucell, *gd, T1, T2, tau1, tau2)) + if (!is_adjacent_pair(orb_cutoff, ucell, *gd, T1, T2, tau1, tau2)) { continue; } const int start2 = ucell.itiaiw2iwt(T2, I2, 0); - for (int jj = 0; jj < atom1->nw * this->npol; ++jj) + for (int jj = 0; jj < atom1->nw * npol; ++jj) { - const int jj0 = jj / this->npol; + const int jj0 = jj / npol; const int iw1_all = start1 + jj0; const int mu = pv.global2local_row(iw1_all); if (mu < 0) @@ -114,9 +122,9 @@ void Plus_U::fold_dSR_gamma(const UnitCell& ucell, continue; } - for (int kk = 0; kk < atom2->nw * this->npol; ++kk) + for (int kk = 0; kk < atom2->nw * npol; ++kk) { - const int kk0 = kk / this->npol; + const int kk0 = kk / npol; const int iw2_all = start2 + kk0; const int nu = pv.global2local_col(iw2_all); if (nu < 0) @@ -124,7 +132,7 @@ void Plus_U::fold_dSR_gamma(const UnitCell& ucell, continue; } - const int iic = get_linear_index(mu, nu, pv); + const int iic = get_linear_index(ks_solver, mu, nu, pv); dSR_gamma[iic] += dS_ptr[nnr] * dh_r[nnr * 3 + dim2]; ++nnr; @@ -137,15 +145,18 @@ void Plus_U::fold_dSR_gamma(const UnitCell& ucell, return; } -void Plus_U::folding_matrix_k(const UnitCell& ucell, - const Grid_Driver& gd, - ForceStressArrays& fsr, - const Parallel_Orbitals& pv, - const int ik, - const int dim1, - const int dim2, - std::complex* mat_k, - const ModuleBase::Vector3& kvec_d) +void folding_matrix_k(int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const UnitCell& ucell, + const Grid_Driver& gd, + ForceStressArrays& fsr, + const Parallel_Orbitals& pv, + const int ik, + const int dim1, + const int dim2, + std::complex* mat_k, + const ModuleBase::Vector3& kvec_d) { ModuleBase::TITLE("Plus_U", "folding_matrix_k"); ModuleBase::timer::start("Plus_U", "folding_matrix_k"); @@ -187,7 +198,7 @@ void Plus_U::folding_matrix_k(const UnitCell& ucell, tau2 = gd.getAdjacentTau(ad); - if (!is_adjacent_pair(ucell, gd, T1, T2, tau1, tau2)) + if (!is_adjacent_pair(orb_cutoff, ucell, gd, T1, T2, tau1, tau2)) { continue; } @@ -206,7 +217,7 @@ void Plus_U::folding_matrix_k(const UnitCell& ucell, // calculate how many matrix elements are in // this processor. //-------------------------------------------------- - for (int ii = 0; ii < atom1->nw * this->npol; ii++) + for (int ii = 0; ii < atom1->nw * npol; ii++) { // the index of orbitals in this processor const int iw1_all = start1 + ii; @@ -216,7 +227,7 @@ void Plus_U::folding_matrix_k(const UnitCell& ucell, continue; } - for (int jj = 0; jj < atom2->nw * this->npol; jj++) + for (int jj = 0; jj < atom2->nw * npol; jj++) { int iw2_all = start2 + jj; const int nu = pv.global2local_col(iw2_all); @@ -225,7 +236,7 @@ void Plus_U::folding_matrix_k(const UnitCell& ucell, continue; } - const int iic = get_linear_index(mu, nu, pv); + const int iic = get_linear_index(ks_solver, mu, nu, pv); if (dim1 <= 3) { @@ -247,27 +258,30 @@ void Plus_U::folding_matrix_k(const UnitCell& ucell, return; } -void Plus_U::folding_matrix_k_new(const int ik, - hamilt::Hamilt>* p_ham) +void folding_matrix_k_new(const std::string& ks_solver, + bool gamma_only_local, + int nspin, + const int ik, + hamilt::Hamilt>* p_ham) { ModuleBase::TITLE("Plus_U", "folding_matrix_k_new"); ModuleBase::timer::start("Plus_U", "folding_matrix_k_new"); int hk_type = 0; - if (ModuleBase::GlobalFunc::IS_COLUMN_MAJOR_KS_SOLVER(this->ks_solver)) + if (ModuleBase::GlobalFunc::IS_COLUMN_MAJOR_KS_SOLVER(ks_solver)) { hk_type = 1; } // get SR and fold to mat_k - if(this->gamma_only_local) + if (gamma_only_local) { dynamic_cast*>(p_ham) ->updateSk(ik, hk_type); } else { - if(this->nspin != 4) + if (nspin != 4) { dynamic_cast, double>*>(p_ham) ->updateSk(ik, hk_type); @@ -282,4 +296,6 @@ void Plus_U::folding_matrix_k_new(const int ik, ModuleBase::timer::end("Plus_U", "folding_matrix_k_new"); } +} // namespace dftu_folding + #endif // __LCAO diff --git a/source/source_lcao/module_dftu/dftu_folding.h b/source/source_lcao/module_dftu/dftu_folding.h new file mode 100644 index 0000000000..2c7a21023a --- /dev/null +++ b/source/source_lcao/module_dftu/dftu_folding.h @@ -0,0 +1,92 @@ +/// @file dftu_folding.h +/// @brief Free-function helpers for folding S/dS matrices, extracted from +/// Plus_U. Each function takes the data it needs (orb_cutoff, +/// ks_solver, npol, gamma_only_local, nspin) as direct parameters; +/// no Plus_U reference is required, so the helpers are fully decoupled +/// from the class and unit-testable. +#ifndef DFTU_FOLDING_H +#define DFTU_FOLDING_H + +#include "source_basis/module_ao/parallel_orbitals.h" +#include "source_cell/module_neighbor/sltk_grid_driver.h" +#include "source_cell/unitcell.h" +#include "source_lcao/force_stress_arrays.h" +#include "source_hamilt/hamilt.h" + +#include +#include +#include + +#ifdef __LCAO + +namespace dftu_folding { + +/// @brief Judge whether atom pair (T1,I1) and (T2,I2,tau2) are adjacent +/// by direct orbital cutoff overlap or three-body bridging via a +/// common nonlocal projector center T0. +/// @param orb_cutoff orbital cutoff radii per atom type +/// @return true if the pair should be processed +bool is_adjacent_pair(const std::vector& orb_cutoff, + const UnitCell& ucell, + const Grid_Driver& gd, + int T1, + int T2, + const ModuleBase::Vector3& tau1, + const ModuleBase::Vector3& tau2); + +/// @brief Get the linear index of local matrix element (mu, nu) based on +/// ks_solver (column-major or row-major). +int get_linear_index(const std::string& ks_solver, + int mu, + int nu, + const Parallel_Orbitals& pv); + +/// @brief Fold the dSR matrix for gamma-only calculations. +/// npol is the spin-polarization factor; orb_cutoff and ks_solver +/// are forwarded to is_adjacent_pair and get_linear_index. +void fold_dSR_gamma(int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const UnitCell& ucell, + const Parallel_Orbitals& pv, + const Grid_Driver* gd, + double* dsloc_x, + double* dsloc_y, + double* dsloc_z, + double* dh_r, + int dim1, + int dim2, + double* dSR_gamma); + +// dim1 = 0 : S, for Hamiltonian +// dim1 = 1-3 : dS, for force +// dim1 = 4-6 : dS * dR, for stress +void folding_matrix_k(int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const UnitCell& ucell, + const Grid_Driver& gd, + ForceStressArrays& fsr, + const Parallel_Orbitals& pv, + int ik, + int dim1, + int dim2, + std::complex* mat_k, + const ModuleBase::Vector3& kvec_d); + +/** + * @brief new function of folding_S_matrix + * only for Hamiltonian now, for force and stress will be developed later + * use HContainer as input and output in mat_k +*/ +void folding_matrix_k_new(const std::string& ks_solver, + bool gamma_only_local, + int nspin, + int ik, + hamilt::Hamilt>* p_ham); + +} // namespace dftu_folding + +#endif // __LCAO + +#endif // DFTU_FOLDING_H diff --git a/source/source_lcao/module_dftu/dftu_force.cpp b/source/source_lcao/module_dftu/dftu_force.cpp index 3f119721bb..f139f3fb0a 100644 --- a/source/source_lcao/module_dftu/dftu_force.cpp +++ b/source/source_lcao/module_dftu/dftu_force.cpp @@ -2,6 +2,7 @@ #ifdef __LCAO #include "dftu_lcao.h" +#include "dftu_folding.h" #include "source_base/constants.h" #include "source_base/global_function.h" #include "source_base/inverse_matrix.h" @@ -237,7 +238,8 @@ void Plus_U::cal_force_k(const UnitCell& ucell, for (int dim = 0; dim < 3; dim++) { - this->folding_matrix_k(ucell, gd, fsr, pv, ik, dim + 1, 0, &dSm_k[0], kvec_d); + dftu_folding::folding_matrix_k(this->npol, this->ks_solver, this->orb_cutoff_, + ucell, gd, fsr, pv, ik, dim + 1, 0, &dSm_k[0], kvec_d); #ifdef __MPI ScalapackConnector::gemm(transN, @@ -371,7 +373,8 @@ void Plus_U::cal_stress_k(const UnitCell& ucell, { for (int dim2 = dim1; dim2 < 3; dim2++) { - this->folding_matrix_k(ucell, gd, fsr, pv, ik, dim1 + 4, dim2, &dSR_k[0], kvec_d); + dftu_folding::folding_matrix_k(this->npol, this->ks_solver, this->orb_cutoff_, + ucell, gd, fsr, pv, ik, dim1 + 4, dim2, &dSR_k[0], kvec_d); #ifdef __MPI ScalapackConnector::gemm(transN, @@ -588,7 +591,8 @@ void Plus_U::cal_stress_gamma(const UnitCell& ucell, { for (int dim2 = dim1; dim2 < 3; dim2++) { - this->fold_dSR_gamma(ucell, pv, gd, dsloc_x, dsloc_y, dsloc_z, dh_r, dim1, dim2, &dSR_gamma[0]); + dftu_folding::fold_dSR_gamma(this->npol, this->ks_solver, this->orb_cutoff_, + ucell, pv, gd, dsloc_x, dsloc_y, dsloc_z, dh_r, dim1, dim2, &dSR_gamma[0]); #ifdef __MPI ScalapackConnector::gemm(transN, diff --git a/source/source_lcao/module_dftu/dftu_lcao.h b/source/source_lcao/module_dftu/dftu_lcao.h index 213458b331..b8e0ee88c4 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.h +++ b/source/source_lcao/module_dftu/dftu_lcao.h @@ -1,5 +1,5 @@ -#ifndef DFTU_H -#define DFTU_H +#ifndef DFTU_LCAO_H +#define DFTU_LCAO_H #include "source_cell/klist.h" #include "source_cell/unitcell.h" @@ -135,61 +135,6 @@ class Plus_U : public Plus_U_Base const int m1, const bool newlocale); - //============================================================= - // In dftu_folding.cpp - // Subroutines for folding S and dS matrix - //============================================================= - - /// @brief Judge whether atom pair (T1,I1) and (T2,I2,tau2) are adjacent - /// by direct orbital cutoff overlap or three-body bridging via a - /// common nonlocal projector center T0. - /// @return true if the pair should be processed - bool is_adjacent_pair(const UnitCell& ucell, - const Grid_Driver& gd, - const int T1, - const int T2, - const ModuleBase::Vector3& tau1, - const ModuleBase::Vector3& tau2) const; - - /// @brief Get the linear index of local matrix element (mu, nu) based on - /// ks_solver (column-major or row-major). - int get_linear_index(const int mu, - const int nu, - const Parallel_Orbitals& pv) const; - - void fold_dSR_gamma(const UnitCell& ucell, - const Parallel_Orbitals& pv, - const Grid_Driver* gd, - double* dsloc_x, - double* dsloc_y, - double* dsloc_z, - double* dh_r, - const int dim1, - const int dim2, - double* dSR_gamma); - - // dim = 0 : S, for Hamiltonian - // dim = 1-3 : dS, for force - // dim = 4-6 : dS * dR, for stress - - void folding_matrix_k(const UnitCell& ucell, - const Grid_Driver& gd, - ForceStressArrays& fsr, - const Parallel_Orbitals& pv, - const int ik, - const int dim1, - const int dim2, - std::complex* mat_k, - const ModuleBase::Vector3& kvec_d); - - /** - * @brief new function of folding_S_matrix - * only for Hamiltonian now, for force and stress will be developed later - * use HContainer as input and output in mat_k - */ - void folding_matrix_k_new(const int ik, - hamilt::Hamilt>* p_ham); - //============================================================= // In dftu_force.cpp // For calculating force and stress fomr DFT+U diff --git a/source/source_lcao/module_dftu/dftu_occup.cpp b/source/source_lcao/module_dftu/dftu_occup.cpp index ff9c5529ee..8a9ec85639 100644 --- a/source/source_lcao/module_dftu/dftu_occup.cpp +++ b/source/source_lcao/module_dftu/dftu_occup.cpp @@ -1,4 +1,5 @@ #include "dftu_lcao.h" +#include "dftu_folding.h" #include "source_base/timer.h" #include "source_io/module_parameter/parameter.h" #ifdef __LCAO @@ -37,7 +38,7 @@ void Plus_U::cal_occup_m_k(const int iter, for (int ik = 0; ik < kv.get_nks(); ik++) { // srho(mu,nu) = \sum_{iw} S(mu,iw)*dm_k(iw,nu) - this->folding_matrix_k_new(ik, p_ham); + dftu_folding::folding_matrix_k_new(this->ks_solver, this->gamma_only_local, this->nspin, ik, p_ham); std::complex* s_k_pointer = nullptr; From 06a75bc50fd3c20d524c602efa9f7415c6f32257 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 14:12:28 +0800 Subject: [PATCH 06/23] refactor(dftu_pw): merge nspin==4 Pauli block 0 and 1-3 VU loops The nspin==4 VU+energy calculation was split into two loops: - block 0 (is=0, charge channel) with diag_coeff on the diagonal - blocks 1-3 (is=1..3, spin channels sigma_x/y/z) with zero diagonal These two loops have identical structure and only differ in the diagonal coefficient. Merge them into a single is=0..3 loop with diag = (is == 0) ? diag_coeff : 0.0 Also add an English comment explaining the Pauli-block layout: VU is stored as 4 contiguous blocks per atom, where is=0 is the charge channel (Hubbard U contributes diag_coeff*delta on the diagonal) and is=1,2,3 are spin channels (sigma_x/y/z, no U diagonal term). The occupation matrix occ_mat[...][0][0].c packs all 4 blocks contiguously. Physics unchanged: - Hubbard U acts only on the charge channel (is=0), so diag_coeff is still applied only there; spin channels remain with zero diagonal. - energy_u accumulation formula is identical for all 4 blocks. Effect: ~25 lines -> ~12 lines (plus comment), removing the artificial block-0 vs block-1-3 symmetry breaking. Verification: - semantic equivalence checked by inspection (start=0 + diag_coeff for is=0 matches the original block-0 loop; start=is*size + 0.0 for is=1..3 matches the original block-1-3 loop) - existing test VUPotNspin4_PauliTransform (dftu_pw_test.cpp) covers the Pauli->spin transform that follows this loop - full build and ctest delegated to user --- source/source_pw/module_pwdft/dftu_pw.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/source/source_pw/module_pwdft/dftu_pw.cpp b/source/source_pw/module_pwdft/dftu_pw.cpp index e256e7c78f..37b5af8f2e 100644 --- a/source/source_pw/module_pwdft/dftu_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_pw.cpp @@ -118,25 +118,22 @@ void Plus_U_Base::cal_occ_pw(const void* psi_in, if(this->nspin == 4) { - for (int m1 = 0; m1 < m_size; m1++) - { - for (int m2 = 0; m2 < m_size; m2++) - { - vu_iat[m1 * m_size + m2] = u_value * - (diag_coeff * (m1 == m2) - this->occ_mat[iat][target_l][0][0].c[m2 * m_size + m1]); - this->energy_u += u_value * weight_eu * this->occ_mat[iat][target_l][0][0].c[m2 * m_size + m1] - * this->occ_mat[iat][target_l][0][0].c[m1 * m_size + m2]; - } - } - for (int is = 1; is < 4; ++is) + // VU is stored as 4 contiguous Pauli blocks per atom: + // is=0: charge channel (identity), Hubbard U contributes the + // diagonal term diag_coeff*delta(m1,m2) + // is=1,2,3: spin channels (sigma_x/y/z), no U diagonal term + // The occupation matrix occ_mat[...][0][0].c packs all 4 blocks + // contiguously, each of size m_size*m_size. + for (int is = 0; is < 4; ++is) { int start = is * m_size * m_size; + double diag = (is == 0) ? diag_coeff : 0.0; for (int m1 = 0; m1 < m_size; m1++) { for (int m2 = 0; m2 < m_size; m2++) { vu_iat[start + m1 * m_size + m2] = u_value * - (0 - this->occ_mat[iat][target_l][0][0].c[start + m2 * m_size + m1]); + (diag * (m1 == m2) - this->occ_mat[iat][target_l][0][0].c[start + m2 * m_size + m1]); this->energy_u += u_value * weight_eu * this->occ_mat[iat][target_l][0][0].c[start + m2 * m_size + m1] * this->occ_mat[iat][target_l][0][0].c[start + m1 * m_size + m2]; From a314a82232fbad973c174a2202e025b6384ec5fa Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 14:21:01 +0800 Subject: [PATCH 07/23] refactor(dftu_pw): extract compute_eff_pot_and_energy from cal_occ_pw cal_occ_pw was doing three conceptually distinct jobs: (1) accumulate occ_mat from psi, (2) reduce occ_mat across k-pools and sync to uom_array, (3) compute effective potential VU and DFT+U energy. The function name only reflects job (1), and the mixing step plus VU/energy computation were tangled together at the end. Extract job (3) into a protected member function compute_eff_pot_and_energy(cell). This isolates the VU+energy calculation (which reads occ_mat and writes eff_pot_pw / energy_u) from the occupation-matrix accumulation and reduction logic. The new function assumes occ_mat has already been reduced across k-pools (documented in its doxygen comment), matching the current calling order in cal_occ_pw. Also add a doxygen comment block on the new function documenting: - preconditions (occ_mat accumulated and reduced) - outputs (eff_pot_pw layout for nspin=1/2/4, energy_u formula) Files changed: - source/source_pw/module_pwdft/dftu_base.h - add protected member declaration compute_eff_pot_and_energy(cell) - source/source_pw/module_pwdft/dftu_pw.cpp - replace ~95 lines of VU+energy code in cal_occ_pw with a single call - add compute_eff_pot_and_energy definition containing the moved code - add doxygen comment on the new function Effects: - cal_occ_pw body shrinks from ~175 lines to ~80 lines (orchestration) - VU+energy logic is now a self-contained unit that can be tested and evolved independently - no behavior change: same code, same order, just moved Verification: - make module_pwdft incremental build passed (verified by user) - DFT+U ctest not yet run (delegated to user) --- source/source_pw/module_pwdft/dftu_base.h | 4 ++++ source/source_pw/module_pwdft/dftu_pw.cpp | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/source/source_pw/module_pwdft/dftu_base.h b/source/source_pw/module_pwdft/dftu_base.h index 3c10b3e6ea..dc6a931d20 100644 --- a/source/source_pw/module_pwdft/dftu_base.h +++ b/source/source_pw/module_pwdft/dftu_base.h @@ -184,6 +184,10 @@ class Plus_U_Base const UnitCell& cell, const int* isk); + /// compute effective potential VU and DFT+U energy from occ_mat + /// (assumes occ_mat has already been reduced across k-pools) + void compute_eff_pot_and_energy(const UnitCell& cell); + std::vector> eff_pot_pw; std::vector eff_pot_pw_index; std::vector uom_array; diff --git a/source/source_pw/module_pwdft/dftu_pw.cpp b/source/source_pw/module_pwdft/dftu_pw.cpp index 37b5af8f2e..f8a491e622 100644 --- a/source/source_pw/module_pwdft/dftu_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_pw.cpp @@ -97,6 +97,25 @@ void Plus_U_Base::cal_occ_pw(const void* psi_in, this->set_occ_mat(cell); } + this->compute_eff_pot_and_energy(cell); + + ModuleBase::timer::end("Plus_U_Base", "cal_occ_pw"); +} + +/// compute effective potential VU and DFT+U energy from occ_mat. +/// +/// Preconditions: +/// - occ_mat has been accumulated from psi and reduced across k-pools +/// (cal_occ_pw calls this after the reduce + mixing steps). +/// +/// Outputs: +/// - eff_pot_pw: VU = U * (diag*delta - occ) written per atom +/// nspin=4: 4 Pauli blocks per atom, then transformed to spin basis +/// nspin=1: single channel +/// nspin=2: two channels in split layout [all_up | all_dn] +/// - energy_u: E_U = sum U * weight_eu * occ(m2,m1) * occ(m1,m2) +void Plus_U_Base::compute_eff_pot_and_energy(const UnitCell& cell) +{ this->energy_u = 0.0; const double weight_eu = (this->nspin == 1) ? 1.0 : (this->nspin == 2) ? 0.5 : 0.25; const double diag_coeff = (this->nspin == 4) ? 1.0 : 0.5; @@ -192,8 +211,6 @@ void Plus_U_Base::cal_occ_pw(const void* psi_in, } } } - - ModuleBase::timer::end("Plus_U_Base", "cal_occ_pw"); } template From 7b7dc7c1a410c35d292e5307315a1a83af5cc92d Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 14:27:13 +0800 Subject: [PATCH 08/23] refactor(dftu_pw): extract reduce_occ_mat and sync_occ_to_uom from cal_occ_pw cal_occ_pw's middle section (formerly L42-L91) did two distinct jobs in a single per-atom loop: (1) reduce occ_mat across k-pools (MPI AllReduce) (2) copy occ_mat to uom_array for mixing (plain data shuffle) These have different natures (parallel communication vs local copy) and interleaving them in one loop body made both harder to read. Split them into two protected member functions so each is self-contained. The new functions: - reduce_occ_mat(cell): sums per-pool occ_mat contributions across pools. nspin-aware: nspin=1 reduces one channel, nspin=2 reduces two, nspin=4 reduces all 4 Pauli blocks in one shot. - sync_occ_to_uom(cell): flattens occ_mat into uom_array for mixing. nspin=2 uses the split layout [all_up | all_dn]. The uom_array.size()==0 guard is hoisted to an early return at the function entry (equivalent to the previous in-loop check, but clearer). Behavior unchanged: same code, same order (reduce -> sync -> mixing -> compute_eff_pot_and_energy). Note: GlobalV::NPROC_IN_POOL is still referenced inside reduce_occ_mat. Isolating it there is a step toward removing the global dependency, but the actual de-globalization is deferred to a separate governance PR. Files changed: - source/source_pw/module_pwdft/dftu_base.h - add protected declarations for reduce_occ_mat / sync_occ_to_uom - source/source_pw/module_pwdft/dftu_pw.cpp - replace ~50 lines in cal_occ_pw with two calls - add reduce_occ_mat / sync_occ_to_uom definitions (code moved as-is) - add doxygen comments documenting nspin layout per function Effects: - cal_occ_pw body now ~30 lines of pure orchestration - reduce and copy logic each isolated, nspin-aware layout documented - existing test MultiAtomSplitLayout_Nspin2 (dftu_pw_test.cpp) covers the nspin=2 split layout used by sync_occ_to_uom Verification: - make module_pwdft incremental build passed (verified by user) - DFT+U ctest not yet run (delegated to user) --- source/source_pw/module_pwdft/dftu_base.h | 6 ++ source/source_pw/module_pwdft/dftu_pw.cpp | 86 ++++++++++++++++------- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/source/source_pw/module_pwdft/dftu_base.h b/source/source_pw/module_pwdft/dftu_base.h index dc6a931d20..5ed8d5bc73 100644 --- a/source/source_pw/module_pwdft/dftu_base.h +++ b/source/source_pw/module_pwdft/dftu_base.h @@ -184,6 +184,12 @@ class Plus_U_Base const UnitCell& cell, const int* isk); + /// reduce occ_mat across k-pools (per-atom, nspin-aware) + void reduce_occ_mat(const UnitCell& cell); + + /// copy occ_mat to uom_array for mixing (nspin-aware split layout) + void sync_occ_to_uom(const UnitCell& cell); + /// compute effective potential VU and DFT+U energy from occ_mat /// (assumes occ_mat has already been reduced across k-pools) void compute_eff_pot_and_energy(const UnitCell& cell); diff --git a/source/source_pw/module_pwdft/dftu_pw.cpp b/source/source_pw/module_pwdft/dftu_pw.cpp index f8a491e622..cc309f7eed 100644 --- a/source/source_pw/module_pwdft/dftu_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_pw.cpp @@ -39,7 +39,31 @@ void Plus_U_Base::cal_occ_pw(const void* psi_in, } #endif - // reduce occ_mat from all k-pools + // reduce occ_mat across k-pools, then copy to uom_array for mixing + this->reduce_occ_mat(cell); + this->sync_occ_to_uom(cell); + + // mixing + if(is_mixing_enabled() && p_chgmix != nullptr) + { + p_chgmix->mix_uom(this->uom_array, this->uom_save); + this->set_occ_mat(cell); + } + + this->compute_eff_pot_and_energy(cell); + + ModuleBase::timer::end("Plus_U_Base", "cal_occ_pw"); +} + +/// reduce occ_mat across all k-pools. +/// +/// Each k-pool only accumulates occ_mat contributions from the k-points it +/// owns; this sums them across pools so occ_mat holds the full result. +/// nspin=1: single channel, size elements +/// nspin=2: two channels (spin-up/down) reduced separately +/// nspin=4: 4 Pauli blocks packed contiguously, reduced in one shot +void Plus_U_Base::reduce_occ_mat(const UnitCell& cell) +{ for(int iat = 0; iat < cell.nat; iat++) { const int it = cell.iat2it[iat]; @@ -71,35 +95,49 @@ void Plus_U_Base::cal_occ_pw(const void* psi_in, this->occ_mat[iat][target_l][0][0].c, size * 4); } + } +} - // save occ_mat matrix for this iat to uom_array - if(this->uom_array.size() != 0) +/// copy occ_mat to uom_array for mixing. +/// +/// Layout: +/// nspin=1: uom_array[eff_pot_pw_index[iat] + mm] = occ_mat[...][0][0] +/// nspin=2: split layout [all_up | all_dn], each atom's spin-up in the +/// first half and spin-down in the second half, both indexed by +/// eff_pot_pw_index[iat] +/// nspin=4: not used here (uom_array mixing only covers nspin=1/2 in the +/// current code path; the nspin=4 branch is a no-op) +void Plus_U_Base::sync_occ_to_uom(const UnitCell& cell) +{ + if(this->uom_array.size() == 0) + { + return; + } + for(int iat = 0; iat < cell.nat; iat++) + { + const int it = cell.iat2it[iat]; + const int target_l = get_orbital_corr(it); + if(!has_correlated_orbital(it)) { - for(int mm=0;mmuom_array[eff_pot_pw_index[iat]+mm] = this->occ_mat[iat][target_l][0][0].c[mm]; - } - if(this->nspin == 2) + continue; + } + const int size = (2 * target_l + 1) * (2 * target_l + 1); + + for(int mm = 0; mm < size; mm++) + { + this->uom_array[eff_pot_pw_index[iat] + mm] = + this->occ_mat[iat][target_l][0][0].c[mm]; + } + if(this->nspin == 2) + { + const int half_size = this->uom_array.size() / 2; + for(int mm = 0; mm < size; mm++) { - const int half_size = this->uom_array.size() / 2; - for(int mm=0;mmuom_array[half_size + eff_pot_pw_index[iat]+mm] = this->occ_mat[iat][target_l][0][1].c[mm]; - } + this->uom_array[half_size + eff_pot_pw_index[iat] + mm] = + this->occ_mat[iat][target_l][0][1].c[mm]; } } } - - // mixing - if(is_mixing_enabled() && p_chgmix != nullptr) - { - p_chgmix->mix_uom(this->uom_array, this->uom_save); - this->set_occ_mat(cell); - } - - this->compute_eff_pot_and_energy(cell); - - ModuleBase::timer::end("Plus_U_Base", "cal_occ_pw"); } /// compute effective potential VU and DFT+U energy from occ_mat. From cf0e6b8b8658d0ff065f193c850c10078af9a12e Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 14:43:57 +0800 Subject: [PATCH 09/23] refactor(dftu_pw): add dftu_pw.h with pauli_to_spin_basis free function Step 4a of the dftu_pw decoupling plan. Create a new header dftu_pw.h declaring free functions in namespace dftu_pw, so the DFT+U PW kernels can be unit-tested directly without going through Plus_U_Base. First function: pauli_to_spin_basis(vu, m_size). This performs the Pauli-to-spin-basis transform on VU for nspin==4, previously inlined in compute_eff_pot_and_energy. The function is pure (no access to Plus_U_Base members): it takes a raw std::complex* pointer to the per-atom VU block and m_size. Files changed: - source/source_pw/module_pwdft/dftu_pw.h (new) - declare namespace dftu_pw - declare pauli_to_spin_basis with doxygen comment documenting the 4 Pauli blocks layout and the transform formula - source/source_pw/module_pwdft/dftu_pw.cpp - include dftu_pw.h - replace ~18 lines of inlined Pauli transform in compute_eff_pot_and_energy with a single call dftu_pw::pauli_to_spin_basis(vu_iat, m_size) - add namespace dftu_pw block at end of file with the function definition (code moved as-is from the inlined version) Effects: - compute_eff_pot_and_energy nspin==4 branch shrinks by ~17 lines - pauli_to_spin_basis is now independently testable - no behavior change: same transform, same memory layout Verification: - make module_pwdft incremental build passed (verified by user) - existing test VUPotNspin4_PauliTransform (dftu_pw_test.cpp) covers the transform; step 4d will rewire it to call the real function --- source/source_pw/module_pwdft/dftu_pw.cpp | 51 ++++++++++++++--------- source/source_pw/module_pwdft/dftu_pw.h | 28 +++++++++++++ 2 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 source/source_pw/module_pwdft/dftu_pw.h diff --git a/source/source_pw/module_pwdft/dftu_pw.cpp b/source/source_pw/module_pwdft/dftu_pw.cpp index cc309f7eed..53357619d2 100644 --- a/source/source_pw/module_pwdft/dftu_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_pw.cpp @@ -1,4 +1,5 @@ #include "source_pw/module_pwdft/dftu_base.h" +#include "source_pw/module_pwdft/dftu_pw.h" #include "source_pw/module_pwdft/onsite_proj.h" #include "source_base/parallel_reduce.h" #include "source_io/module_parameter/parameter.h" @@ -198,26 +199,7 @@ void Plus_U_Base::compute_eff_pot_and_energy(const UnitCell& cell) } } // transfer from Pauli matrix representation to spin representation - for (int m1 = 0; m1 < m_size; m1++) - { - for (int m2 = 0; m2 < m_size; m2++) - { - int index[4]; - index[0] = m1 * m_size + m2; - index[1] = m1 * m_size + m2 + size; - index[2] = m1 * m_size + m2 + size * 2; - index[3] = m1 * m_size + m2 + size * 3; - std::complex vu_tmp[4]; - for (int i = 0; i < 4; i++) - { - vu_tmp[i] = vu_iat[index[i]]; - } - vu_iat[index[0]] = 0.5 * (vu_tmp[0] + vu_tmp[3]); - vu_iat[index[3]] = 0.5 * (vu_tmp[0] - vu_tmp[3]); - vu_iat[index[1]] = 0.5 * (vu_tmp[1] + std::complex(0.0, 1.0) * vu_tmp[2]); - vu_iat[index[2]] = 0.5 * (vu_tmp[1] - std::complex(0.0, 1.0) * vu_tmp[2]); - } - } + dftu_pw::pauli_to_spin_basis(vu_iat, m_size); } else // nspin=1 or nspin=2 { @@ -335,6 +317,35 @@ void Plus_U_Base::accumulate_occ_one_k(const void* psi_in, } } +namespace dftu_pw { + +void pauli_to_spin_basis(std::complex* vu, int m_size) +{ + const int size = m_size * m_size; + for (int m1 = 0; m1 < m_size; m1++) + { + for (int m2 = 0; m2 < m_size; m2++) + { + int index[4]; + index[0] = m1 * m_size + m2; + index[1] = m1 * m_size + m2 + size; + index[2] = m1 * m_size + m2 + size * 2; + index[3] = m1 * m_size + m2 + size * 3; + std::complex vu_tmp[4]; + for (int i = 0; i < 4; i++) + { + vu_tmp[i] = vu[index[i]]; + } + vu[index[0]] = 0.5 * (vu_tmp[0] + vu_tmp[3]); + vu[index[3]] = 0.5 * (vu_tmp[0] - vu_tmp[3]); + vu[index[1]] = 0.5 * (vu_tmp[1] + std::complex(0.0, 1.0) * vu_tmp[2]); + vu[index[2]] = 0.5 * (vu_tmp[1] - std::complex(0.0, 1.0) * vu_tmp[2]); + } + } +} + +} // namespace dftu_pw + // explicit instantiations template void Plus_U_Base::accumulate_occ_one_k( const void*, const ModuleBase::matrix&, const UnitCell&, const int*); diff --git a/source/source_pw/module_pwdft/dftu_pw.h b/source/source_pw/module_pwdft/dftu_pw.h new file mode 100644 index 0000000000..da10fb946a --- /dev/null +++ b/source/source_pw/module_pwdft/dftu_pw.h @@ -0,0 +1,28 @@ +#ifndef DFTU_PW_H +#define DFTU_PW_H + +#include + +/// Free functions for DFT+U PW basis calculations. +/// +/// These functions are pure (no access to Plus_U_Base members) so they can be +/// unit-tested directly by including this header. The member functions in +/// dftu_pw.cpp call them after computing per-atom offsets and fetching the +/// relevant member state (occ_mat, eff_pot_pw, u_current, etc.). +namespace dftu_pw { + +/// transform VU from Pauli basis to spin basis (in-place, nspin==4 only). +/// +/// vu points to the per-atom VU block of size 4 * m_size * m_size, storing +/// 4 contiguous Pauli blocks (is=0 charge, is=1 sigma_x, is=2 sigma_y, +/// is=3 sigma_z). After the transform, the same memory holds the spin +/// representation: +/// vu[0] <- 0.5 * (vu_pauli[0] + vu_pauli[3]) +/// vu[3*size] <- 0.5 * (vu_pauli[0] - vu_pauli[3]) +/// vu[size] <- 0.5 * (vu_pauli[1] + i * vu_pauli[2]) +/// vu[2*size] <- 0.5 * (vu_pauli[1] - i * vu_pauli[2]) +void pauli_to_spin_basis(std::complex* vu, int m_size); + +} // namespace dftu_pw + +#endif From e6b99255075714c90f1b8bfbb49ce1a26784d3cb Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 14:46:42 +0800 Subject: [PATCH 10/23] refactor(dftu_pw): add compute_vu_spinor and compute_vu_scalar free functions Step 4b of the dftu_pw decoupling plan. Extract the VU+energy per-atom loops from compute_eff_pot_and_energy into two free functions in namespace dftu_pw: - compute_vu_spinor: nspin==4 case, writes 4 Pauli blocks of VU and returns the energy_u increment; internally calls pauli_to_spin_basis to convert VU to spin basis in-place (same order as before). - compute_vu_scalar: nspin==1/2 case, writes one spin channel's VU and returns the energy_u increment. Both functions are pure: they take raw pointers (vu, occ) and scalars (u_value, diag_coeff, weight_eu, m_size), no access to Plus_U_Base members. compute_eff_pot_and_energy now computes per-atom offsets (vu_iat, occ pointer, u_value) and delegates the inner loop. Files changed: - source/source_pw/module_pwdft/dftu_pw.h - declare compute_vu_spinor / compute_vu_scalar with doxygen comments documenting pointer semantics and return value - source/source_pw/module_pwdft/dftu_pw.cpp - replace ~40 lines of inlined VU+energy loops in compute_eff_pot_and_energy with 1 (nspin==4) or 1-2 (nspin==1/2) calls to the free functions; energy_u accumulates the return values - add compute_vu_spinor / compute_vu_scalar definitions in the namespace dftu_pw block (code moved as-is from the inlined version) Effects: - compute_eff_pot_and_energy per-atom body shrinks from ~55 lines to ~20 lines of orchestration - VU+energy kernels now independently testable - no behavior change: same formula, same order (pauli_to_spin_basis still called after the 4 Pauli blocks are filled, inside compute_vu_spinor) Verification: - make module_pwdft incremental build passed (verified by user) - existing tests VUPotNspin1_DiagonalLocale, VUPotNspin2_TwoSpinChannels, VUPotNspin4_PauliTransform (dftu_pw_test.cpp) cover the same formulas; step 4d will rewire them to call the real functions --- source/source_pw/module_pwdft/dftu_pw.cpp | 103 ++++++++++++++-------- source/source_pw/module_pwdft/dftu_pw.h | 29 ++++++ 2 files changed, 94 insertions(+), 38 deletions(-) diff --git a/source/source_pw/module_pwdft/dftu_pw.cpp b/source/source_pw/module_pwdft/dftu_pw.cpp index 53357619d2..432d64e9f2 100644 --- a/source/source_pw/module_pwdft/dftu_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_pw.cpp @@ -182,52 +182,26 @@ void Plus_U_Base::compute_eff_pot_and_energy(const UnitCell& cell) // is=1,2,3: spin channels (sigma_x/y/z), no U diagonal term // The occupation matrix occ_mat[...][0][0].c packs all 4 blocks // contiguously, each of size m_size*m_size. - for (int is = 0; is < 4; ++is) - { - int start = is * m_size * m_size; - double diag = (is == 0) ? diag_coeff : 0.0; - for (int m1 = 0; m1 < m_size; m1++) - { - for (int m2 = 0; m2 < m_size; m2++) - { - vu_iat[start + m1 * m_size + m2] = u_value * - (diag * (m1 == m2) - this->occ_mat[iat][target_l][0][0].c[start + m2 * m_size + m1]); - this->energy_u += u_value * weight_eu - * this->occ_mat[iat][target_l][0][0].c[start + m2 * m_size + m1] - * this->occ_mat[iat][target_l][0][0].c[start + m1 * m_size + m2]; - } - } - } - // transfer from Pauli matrix representation to spin representation - dftu_pw::pauli_to_spin_basis(vu_iat, m_size); + this->energy_u += dftu_pw::compute_vu_spinor( + vu_iat, + this->occ_mat[iat][target_l][0][0].c, + u_value, diag_coeff, weight_eu, m_size); } else // nspin=1 or nspin=2 { // spin-up channel - for (int m1 = 0; m1 < m_size; m1++) - { - for (int m2 = 0; m2 < m_size; m2++) - { - vu_iat[m1 * m_size + m2] = u_value * - (diag_coeff * (m1 == m2) - this->occ_mat[iat][target_l][0][0].c[m2 * m_size + m1]); - this->energy_u += u_value * weight_eu * this->occ_mat[iat][target_l][0][0].c[m2 * m_size + m1] - * this->occ_mat[iat][target_l][0][0].c[m1 * m_size + m2]; - } - } + this->energy_u += dftu_pw::compute_vu_scalar( + vu_iat, + this->occ_mat[iat][target_l][0][0].c, + u_value, diag_coeff, weight_eu, m_size); // spin-down channel for nspin=2 if(this->nspin == 2) { std::complex* vu_iat1 = &(this->eff_pot_pw[this->eff_pot_pw.size()/2 + this->eff_pot_pw_index[iat]]); - for (int m1 = 0; m1 < m_size; m1++) - { - for (int m2 = 0; m2 < m_size; m2++) - { - vu_iat1[m1 * m_size + m2] = u_value * - (diag_coeff * (m1 == m2) - this->occ_mat[iat][target_l][0][1].c[m2 * m_size + m1]); - this->energy_u += u_value * weight_eu * this->occ_mat[iat][target_l][0][1].c[m2 * m_size + m1] - * this->occ_mat[iat][target_l][0][1].c[m1 * m_size + m2]; - } - } + this->energy_u += dftu_pw::compute_vu_scalar( + vu_iat1, + this->occ_mat[iat][target_l][0][1].c, + u_value, diag_coeff, weight_eu, m_size); } } } @@ -344,6 +318,59 @@ void pauli_to_spin_basis(std::complex* vu, int m_size) } } +double compute_vu_spinor( + std::complex* vu, + const double* occ, + double u_value, + double diag_coeff, + double weight_eu, + int m_size) +{ + double energy_u = 0.0; + const int m_size2 = m_size * m_size; + for (int is = 0; is < 4; ++is) + { + int start = is * m_size2; + double diag = (is == 0) ? diag_coeff : 0.0; + for (int m1 = 0; m1 < m_size; m1++) + { + for (int m2 = 0; m2 < m_size; m2++) + { + vu[start + m1 * m_size + m2] = u_value * + (diag * (m1 == m2) - occ[start + m2 * m_size + m1]); + energy_u += u_value * weight_eu + * occ[start + m2 * m_size + m1] + * occ[start + m1 * m_size + m2]; + } + } + } + pauli_to_spin_basis(vu, m_size); + return energy_u; +} + +double compute_vu_scalar( + std::complex* vu, + const double* occ, + double u_value, + double diag_coeff, + double weight_eu, + int m_size) +{ + double energy_u = 0.0; + for (int m1 = 0; m1 < m_size; m1++) + { + for (int m2 = 0; m2 < m_size; m2++) + { + vu[m1 * m_size + m2] = u_value * + (diag_coeff * (m1 == m2) - occ[m2 * m_size + m1]); + energy_u += u_value * weight_eu + * occ[m2 * m_size + m1] + * occ[m1 * m_size + m2]; + } + } + return energy_u; +} + } // namespace dftu_pw // explicit instantiations diff --git a/source/source_pw/module_pwdft/dftu_pw.h b/source/source_pw/module_pwdft/dftu_pw.h index da10fb946a..9d6d373258 100644 --- a/source/source_pw/module_pwdft/dftu_pw.h +++ b/source/source_pw/module_pwdft/dftu_pw.h @@ -23,6 +23,35 @@ namespace dftu_pw { /// vu[2*size] <- 0.5 * (vu_pauli[1] - i * vu_pauli[2]) void pauli_to_spin_basis(std::complex* vu, int m_size); +/// compute VU and energy contribution for one atom (nspin==4, spinor). +/// +/// Writes 4 Pauli blocks of VU into vu (size 4 * m_size * m_size) and +/// returns the energy_u increment. Internally calls pauli_to_spin_basis +/// to convert vu to spin basis in-place. +/// +/// vu: pointer to eff_pot_pw[eff_pot_pw_index[iat]] +/// occ: pointer to occ_mat[iat][target_l][0][0].c (4 Pauli blocks packed) +double compute_vu_spinor( + std::complex* vu, + const double* occ, + double u_value, + double diag_coeff, + double weight_eu, + int m_size); + +/// compute VU and energy contribution for one atom, one spin channel +/// (nspin==1 or nspin==2). Returns the energy_u increment. +/// +/// vu: pointer to the spin channel's VU block (size m_size * m_size) +/// occ: pointer to occ_mat[iat][target_l][0][is].c for this channel +double compute_vu_scalar( + std::complex* vu, + const double* occ, + double u_value, + double diag_coeff, + double weight_eu, + int m_size); + } // namespace dftu_pw #endif From 27342abe591a33262549fac0839322ffc87ad853 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 14:51:32 +0800 Subject: [PATCH 11/23] refactor(dftu_pw): add accumulate_occ_spinor and accumulate_occ_scalar free functions Step 4c of the dftu_pw decoupling plan. Extract the per-atom-per-kpoint occ_mat accumulation loops from accumulate_occ_one_k into two free functions in namespace dftu_pw: - accumulate_occ_spinor: nspin==4 case, accumulates 4 Pauli blocks from becp into occ_mat (npol=2 spinor layout). - accumulate_occ_scalar: nspin==1/2 case, accumulates one spin channel from becp into occ_mat. Both functions are pure: they take raw pointers (occ_mat_out, becp) and scalars describing the per-atom/per-kpoint offsets, no access to Plus_U_Base members. accumulate_occ_one_k now computes these offsets and delegates the inner ib/m1/m2 loop. Files changed: - source/source_pw/module_pwdft/dftu_pw.h - add #include "source_base/matrix.h" (for ModuleBase::matrix wg param) - declare accumulate_occ_spinor / accumulate_occ_scalar with doxygen comments documenting pointer semantics and parameter meanings - source/source_pw/module_pwdft/dftu_pw.cpp - replace ~45 lines of inlined accumulation loops in accumulate_occ_one_k with 1 call per branch (nspin==4 / nspin!=4) - add accumulate_occ_spinor / accumulate_occ_scalar definitions in the namespace dftu_pw block (code moved as-is) - use std::conj explicitly (no 'using namespace std') - drop unused 'is' parameter from accumulate_occ_scalar: the caller selects the spin channel by passing the corresponding occ_mat pointer (occ_mat[...][is].c); the function itself does not need is Effects: - accumulate_occ_one_k per-atom body shrinks from ~50 lines to ~15 lines of orchestration - occ accumulation kernels now independently testable - no behavior change: same becp indices, same Pauli-block packing, same weight handling Verification: - make module_pwdft incremental build passed (verified by user) - existing tests LocaleAccumNspin12, LocaleAccumNspin4_PauliComponents (dftu_pw_test.cpp) cover the same formulas via arithmetic reimplementation; step 4d will rewire them to call the real functions --- source/source_pw/module_pwdft/dftu_pw.cpp | 113 ++++++++++++++-------- source/source_pw/module_pwdft/dftu_pw.h | 44 +++++++++ 2 files changed, 118 insertions(+), 39 deletions(-) diff --git a/source/source_pw/module_pwdft/dftu_pw.cpp b/source/source_pw/module_pwdft/dftu_pw.cpp index 432d64e9f2..990809b399 100644 --- a/source/source_pw/module_pwdft/dftu_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_pw.cpp @@ -241,50 +241,19 @@ void Plus_U_Base::accumulate_occ_one_k(const void* psi_in, } const int m_begin = target_l * target_l; const int tlp1 = 2 * target_l + 1; - const int tlp1_2 = tlp1 * tlp1; if(this->nspin == 4) { - for(int ib = 0; ib < nbands; ib++) - { - const double weight = wg_in(ik, ib); - int ind_m1m2 = 0; - for(int m1 = 0; m1 < tlp1; m1++) - { - const int index_m1 = ib*npol*nkb + begin_ih + m_begin + m1; - for(int m2 = 0; m2 < tlp1; m2++) - { - const int index_m2 = ib*npol*nkb + begin_ih + m_begin + m2; - std::complex occ[4]; - occ[0] = weight * conj(becp[index_m1]) * becp[index_m2]; - occ[1] = weight * conj(becp[index_m1]) * becp[index_m2 + nkb]; - occ[2] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2]; - occ[3] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb]; - this->occ_mat[iat][target_l][0][0].c[ind_m1m2] += (occ[0] + occ[3]).real(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag(); - this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real(); - ind_m1m2++; - } - } - } + dftu_pw::accumulate_occ_spinor( + this->occ_mat[iat][target_l][0][0].c, + becp, nbands, npol, nkb, begin_ih, m_begin, tlp1, + wg_in, ik); } else // nspin=1 or nspin=2 { - for(int ib = 0; ib < nbands; ib++) - { - const double weight = wg_in(ik, ib); - int ind_m1m2 = 0; - for(int m1 = 0; m1 < tlp1; m1++) - { - const int index_m1 = ib*nkb + begin_ih + m_begin + m1; - for(int m2 = 0; m2 < tlp1; m2++) - { - const int index_m2 = ib*nkb + begin_ih + m_begin + m2; - this->occ_mat[iat][target_l][0][is].c[ind_m1m2] += weight * (conj(becp[index_m1]) * becp[index_m2]).real(); - ind_m1m2++; - } - } - } + dftu_pw::accumulate_occ_scalar( + this->occ_mat[iat][target_l][0][is].c, + becp, nbands, nkb, begin_ih, m_begin, tlp1, + wg_in, ik); } begin_ih += nh; } @@ -371,6 +340,72 @@ double compute_vu_scalar( return energy_u; } +void accumulate_occ_spinor( + double* occ_mat_out, + const std::complex* becp, + int nbands, + int npol, + int nkb, + int begin_ih, + int m_begin, + int tlp1, + const ModuleBase::matrix& wg, + int ik) +{ + const int tlp1_2 = tlp1 * tlp1; + for (int ib = 0; ib < nbands; ib++) + { + const double weight = wg(ik, ib); + int ind_m1m2 = 0; + for (int m1 = 0; m1 < tlp1; m1++) + { + const int index_m1 = ib * npol * nkb + begin_ih + m_begin + m1; + for (int m2 = 0; m2 < tlp1; m2++) + { + const int index_m2 = ib * npol * nkb + begin_ih + m_begin + m2; + std::complex occ[4]; + occ[0] = weight * std::conj(becp[index_m1]) * becp[index_m2]; + occ[1] = weight * std::conj(becp[index_m1]) * becp[index_m2 + nkb]; + occ[2] = weight * std::conj(becp[index_m1 + nkb]) * becp[index_m2]; + occ[3] = weight * std::conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb]; + occ_mat_out[ind_m1m2] += (occ[0] + occ[3]).real(); + occ_mat_out[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real(); + occ_mat_out[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag(); + occ_mat_out[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real(); + ind_m1m2++; + } + } + } +} + +void accumulate_occ_scalar( + double* occ_mat_out, + const std::complex* becp, + int nbands, + int nkb, + int begin_ih, + int m_begin, + int tlp1, + const ModuleBase::matrix& wg, + int ik) +{ + for (int ib = 0; ib < nbands; ib++) + { + const double weight = wg(ik, ib); + int ind_m1m2 = 0; + for (int m1 = 0; m1 < tlp1; m1++) + { + const int index_m1 = ib * nkb + begin_ih + m_begin + m1; + for (int m2 = 0; m2 < tlp1; m2++) + { + const int index_m2 = ib * nkb + begin_ih + m_begin + m2; + occ_mat_out[ind_m1m2] += weight * (std::conj(becp[index_m1]) * becp[index_m2]).real(); + ind_m1m2++; + } + } + } +} + } // namespace dftu_pw // explicit instantiations diff --git a/source/source_pw/module_pwdft/dftu_pw.h b/source/source_pw/module_pwdft/dftu_pw.h index 9d6d373258..49ac6b85ee 100644 --- a/source/source_pw/module_pwdft/dftu_pw.h +++ b/source/source_pw/module_pwdft/dftu_pw.h @@ -2,6 +2,7 @@ #define DFTU_PW_H #include +#include "source_base/matrix.h" /// Free functions for DFT+U PW basis calculations. /// @@ -52,6 +53,49 @@ double compute_vu_scalar( double weight_eu, int m_size); +/// accumulate occ_mat from becp for one atom, one k-point (nspin==4, spinor). +/// +/// occ_mat_out points to occ_mat[iat][target_l][0][0].c, which packs 4 +/// Pauli blocks contiguously (each of size tlp1*tlp1). The function adds +/// the contributions from all nbands bands for the given k-point. +/// +/// becp: projector-bra overlap for this k-point +/// npol: 2 for spinor (nspin==4) +/// nkb: number of projectors per band per spin +/// begin_ih: offset of this atom's projectors in becp +/// m_begin: offset of the correlated l's first m within the atom's projectors +/// tlp1: 2*target_l + 1 +void accumulate_occ_spinor( + double* occ_mat_out, + const std::complex* becp, + int nbands, + int npol, + int nkb, + int begin_ih, + int m_begin, + int tlp1, + const ModuleBase::matrix& wg, + int ik); + +/// accumulate occ_mat from becp for one atom, one k-point (nspin==1 or 2). +/// +/// occ_mat_out points to occ_mat[iat][target_l][0][is].c, a single channel +/// of size tlp1*tlp1. The caller selects the spin channel by passing the +/// corresponding occ_mat pointer; this function does not need is. +/// Adds contributions from all nbands bands. +/// +/// becp, nbands, nkb, begin_ih, m_begin, tlp1: same as accumulate_occ_spinor +void accumulate_occ_scalar( + double* occ_mat_out, + const std::complex* becp, + int nbands, + int nkb, + int begin_ih, + int m_begin, + int tlp1, + const ModuleBase::matrix& wg, + int ik); + } // namespace dftu_pw #endif From 45189f6d91207c87a15f1fa26bd1e1666713ba80 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 15:07:00 +0800 Subject: [PATCH 12/23] refactor(dftu_pw): split into dftu_tools_pw.{h,cpp} and dftu_cal_occ_pw.cpp Step 4d-prerequisite of the dftu_pw decoupling plan. Enforce the "header-implementation pairing" rule: the free-function declarations in dftu_pw.h had their implementations stuffed at the bottom of dftu_pw.cpp (alongside Plus_U_Base member functions), which is not a proper .h/.cpp pair. File structure after this commit: - dftu_tools_pw.h (renamed from dftu_pw.h) - declare 5 free functions in namespace dftu_pw - include guard DFTU_TOOLS_PW_H - dftu_tools_pw.cpp (new file) - implement the 5 free functions (pauli_to_spin_basis, compute_vu_spinor, compute_vu_scalar, accumulate_occ_spinor, accumulate_occ_scalar); depends only on and matrix.h - dftu_cal_occ_pw.cpp (renamed from dftu_pw.cpp via git mv) - Plus_U_Base member functions only (cal_occ_pw, accumulate_occ_one_k, reduce_occ_mat, sync_occ_to_uom, compute_eff_pot_and_energy) - includes dftu_tools_pw.h to call the free functions namespace stays dftu_pw (not renamed) to avoid churning all call sites; only filenames change. Files changed: - source/source_pw/module_pwdft/dftu_tools_pw.h (git mv from dftu_pw.h) - update include guard to DFTU_TOOLS_PW_H - source/source_pw/module_pwdft/dftu_tools_pw.cpp (new) - body moved verbatim from the former dftu_pw.cpp namespace block - source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp (git mv from dftu_pw.cpp) - drop the namespace dftu_pw block (moved to dftu_tools_pw.cpp) - include "source_pw/module_pwdft/dftu_tools_pw.h" instead of dftu_pw.h - source/source_pw/module_pwdft/CMakeLists.txt - replace dftu_pw.cpp with dftu_tools_pw.cpp + dftu_cal_occ_pw.cpp - source/Makefile.Objects - replace dftu_pw.o with dftu_tools_pw.o + dftu_cal_occ_pw.o - source/source_pw/module_pwdft/dftu_base.cpp - update the pointer comment to reflect new filenames Effects: - header/implementation properly paired for the free functions - dftu_tools_pw.cpp has minimal dependencies, can be linked into unit tests without pulling in onsite_proj.h / parallel_reduce.h - main implementation file (dftu_cal_occ_pw.cpp) retains its git history via git mv (rename similarity ~63%, above the 50% threshold) Verification: - make module_pwdft incremental build passed (verified by user) - step 4d proper (rewire tests to call real functions) follows next --- source/Makefile.Objects | 3 +- source/source_pw/module_pwdft/CMakeLists.txt | 3 +- source/source_pw/module_pwdft/dftu_base.cpp | 6 +- .../{dftu_pw.cpp => dftu_cal_occ_pw.cpp} | 150 +----------------- .../source_pw/module_pwdft/dftu_tools_pw.cpp | 149 +++++++++++++++++ .../{dftu_pw.h => dftu_tools_pw.h} | 4 +- 6 files changed, 159 insertions(+), 156 deletions(-) rename source/source_pw/module_pwdft/{dftu_pw.cpp => dftu_cal_occ_pw.cpp} (68%) create mode 100644 source/source_pw/module_pwdft/dftu_tools_pw.cpp rename source/source_pw/module_pwdft/{dftu_pw.h => dftu_tools_pw.h} (98%) diff --git a/source/Makefile.Objects b/source/Makefile.Objects index 2928e5935b..1d196dc8b5 100644 --- a/source/Makefile.Objects +++ b/source/Makefile.Objects @@ -742,7 +742,8 @@ OBJS_SRCPW=h_ewald_pw.o\ update_cell_pw.o\ dftu_base.o\ dftu_output.o\ - dftu_pw.o\ + dftu_tools_pw.o\ + dftu_cal_occ_pw.o\ setup_dftu_pw.o\ deltaspin_pw.o\ force_pw.o\ diff --git a/source/source_pw/module_pwdft/CMakeLists.txt b/source/source_pw/module_pwdft/CMakeLists.txt index 4a4b6d71f6..b4d1616260 100644 --- a/source/source_pw/module_pwdft/CMakeLists.txt +++ b/source/source_pw/module_pwdft/CMakeLists.txt @@ -14,7 +14,8 @@ list(APPEND objects op_pw_exx_pot.cpp dftu_base.cpp dftu_output.cpp - dftu_pw.cpp + dftu_tools_pw.cpp + dftu_cal_occ_pw.cpp setup_pot.cpp setup_pwrho.cpp setup_pwwfc.cpp diff --git a/source/source_pw/module_pwdft/dftu_base.cpp b/source/source_pw/module_pwdft/dftu_base.cpp index e7b8343337..08b282948f 100644 --- a/source/source_pw/module_pwdft/dftu_base.cpp +++ b/source/source_pw/module_pwdft/dftu_base.cpp @@ -733,6 +733,6 @@ void Plus_U_Base::local_occup_bcast(const UnitCell& ucell, } -// cal_occ_pw() is implemented in source_lcao/module_dftu/dftu_pw.cpp -// as a Plus_U_Base method. It will be relocated to this directory -// in Phase 5 of the class-split refactor. +// cal_occ_pw() is implemented in source_pw/module_pwdft/dftu_cal_occ_pw.cpp +// as a Plus_U_Base method. Pure per-atom kernels live in dftu_tools_pw.{h,cpp} +// as free functions in namespace dftu_pw. diff --git a/source/source_pw/module_pwdft/dftu_pw.cpp b/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp similarity index 68% rename from source/source_pw/module_pwdft/dftu_pw.cpp rename to source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp index 990809b399..eadb24e19f 100644 --- a/source/source_pw/module_pwdft/dftu_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp @@ -1,5 +1,5 @@ #include "source_pw/module_pwdft/dftu_base.h" -#include "source_pw/module_pwdft/dftu_pw.h" +#include "source_pw/module_pwdft/dftu_tools_pw.h" #include "source_pw/module_pwdft/onsite_proj.h" #include "source_base/parallel_reduce.h" #include "source_io/module_parameter/parameter.h" @@ -260,154 +260,6 @@ void Plus_U_Base::accumulate_occ_one_k(const void* psi_in, } } -namespace dftu_pw { - -void pauli_to_spin_basis(std::complex* vu, int m_size) -{ - const int size = m_size * m_size; - for (int m1 = 0; m1 < m_size; m1++) - { - for (int m2 = 0; m2 < m_size; m2++) - { - int index[4]; - index[0] = m1 * m_size + m2; - index[1] = m1 * m_size + m2 + size; - index[2] = m1 * m_size + m2 + size * 2; - index[3] = m1 * m_size + m2 + size * 3; - std::complex vu_tmp[4]; - for (int i = 0; i < 4; i++) - { - vu_tmp[i] = vu[index[i]]; - } - vu[index[0]] = 0.5 * (vu_tmp[0] + vu_tmp[3]); - vu[index[3]] = 0.5 * (vu_tmp[0] - vu_tmp[3]); - vu[index[1]] = 0.5 * (vu_tmp[1] + std::complex(0.0, 1.0) * vu_tmp[2]); - vu[index[2]] = 0.5 * (vu_tmp[1] - std::complex(0.0, 1.0) * vu_tmp[2]); - } - } -} - -double compute_vu_spinor( - std::complex* vu, - const double* occ, - double u_value, - double diag_coeff, - double weight_eu, - int m_size) -{ - double energy_u = 0.0; - const int m_size2 = m_size * m_size; - for (int is = 0; is < 4; ++is) - { - int start = is * m_size2; - double diag = (is == 0) ? diag_coeff : 0.0; - for (int m1 = 0; m1 < m_size; m1++) - { - for (int m2 = 0; m2 < m_size; m2++) - { - vu[start + m1 * m_size + m2] = u_value * - (diag * (m1 == m2) - occ[start + m2 * m_size + m1]); - energy_u += u_value * weight_eu - * occ[start + m2 * m_size + m1] - * occ[start + m1 * m_size + m2]; - } - } - } - pauli_to_spin_basis(vu, m_size); - return energy_u; -} - -double compute_vu_scalar( - std::complex* vu, - const double* occ, - double u_value, - double diag_coeff, - double weight_eu, - int m_size) -{ - double energy_u = 0.0; - for (int m1 = 0; m1 < m_size; m1++) - { - for (int m2 = 0; m2 < m_size; m2++) - { - vu[m1 * m_size + m2] = u_value * - (diag_coeff * (m1 == m2) - occ[m2 * m_size + m1]); - energy_u += u_value * weight_eu - * occ[m2 * m_size + m1] - * occ[m1 * m_size + m2]; - } - } - return energy_u; -} - -void accumulate_occ_spinor( - double* occ_mat_out, - const std::complex* becp, - int nbands, - int npol, - int nkb, - int begin_ih, - int m_begin, - int tlp1, - const ModuleBase::matrix& wg, - int ik) -{ - const int tlp1_2 = tlp1 * tlp1; - for (int ib = 0; ib < nbands; ib++) - { - const double weight = wg(ik, ib); - int ind_m1m2 = 0; - for (int m1 = 0; m1 < tlp1; m1++) - { - const int index_m1 = ib * npol * nkb + begin_ih + m_begin + m1; - for (int m2 = 0; m2 < tlp1; m2++) - { - const int index_m2 = ib * npol * nkb + begin_ih + m_begin + m2; - std::complex occ[4]; - occ[0] = weight * std::conj(becp[index_m1]) * becp[index_m2]; - occ[1] = weight * std::conj(becp[index_m1]) * becp[index_m2 + nkb]; - occ[2] = weight * std::conj(becp[index_m1 + nkb]) * becp[index_m2]; - occ[3] = weight * std::conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb]; - occ_mat_out[ind_m1m2] += (occ[0] + occ[3]).real(); - occ_mat_out[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real(); - occ_mat_out[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag(); - occ_mat_out[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real(); - ind_m1m2++; - } - } - } -} - -void accumulate_occ_scalar( - double* occ_mat_out, - const std::complex* becp, - int nbands, - int nkb, - int begin_ih, - int m_begin, - int tlp1, - const ModuleBase::matrix& wg, - int ik) -{ - for (int ib = 0; ib < nbands; ib++) - { - const double weight = wg(ik, ib); - int ind_m1m2 = 0; - for (int m1 = 0; m1 < tlp1; m1++) - { - const int index_m1 = ib * nkb + begin_ih + m_begin + m1; - for (int m2 = 0; m2 < tlp1; m2++) - { - const int index_m2 = ib * nkb + begin_ih + m_begin + m2; - occ_mat_out[ind_m1m2] += weight * (std::conj(becp[index_m1]) * becp[index_m2]).real(); - ind_m1m2++; - } - } - } -} - -} // namespace dftu_pw - // explicit instantiations template void Plus_U_Base::accumulate_occ_one_k( const void*, const ModuleBase::matrix&, const UnitCell&, const int*); diff --git a/source/source_pw/module_pwdft/dftu_tools_pw.cpp b/source/source_pw/module_pwdft/dftu_tools_pw.cpp new file mode 100644 index 0000000000..5cc4a5f2e5 --- /dev/null +++ b/source/source_pw/module_pwdft/dftu_tools_pw.cpp @@ -0,0 +1,149 @@ +#include "source_pw/module_pwdft/dftu_tools_pw.h" + +namespace dftu_pw { + +void pauli_to_spin_basis(std::complex* vu, int m_size) +{ + const int size = m_size * m_size; + for (int m1 = 0; m1 < m_size; m1++) + { + for (int m2 = 0; m2 < m_size; m2++) + { + int index[4]; + index[0] = m1 * m_size + m2; + index[1] = m1 * m_size + m2 + size; + index[2] = m1 * m_size + m2 + size * 2; + index[3] = m1 * m_size + m2 + size * 3; + std::complex vu_tmp[4]; + for (int i = 0; i < 4; i++) + { + vu_tmp[i] = vu[index[i]]; + } + vu[index[0]] = 0.5 * (vu_tmp[0] + vu_tmp[3]); + vu[index[3]] = 0.5 * (vu_tmp[0] - vu_tmp[3]); + vu[index[1]] = 0.5 * (vu_tmp[1] + std::complex(0.0, 1.0) * vu_tmp[2]); + vu[index[2]] = 0.5 * (vu_tmp[1] - std::complex(0.0, 1.0) * vu_tmp[2]); + } + } +} + +double compute_vu_spinor( + std::complex* vu, + const double* occ, + double u_value, + double diag_coeff, + double weight_eu, + int m_size) +{ + double energy_u = 0.0; + const int m_size2 = m_size * m_size; + for (int is = 0; is < 4; ++is) + { + int start = is * m_size2; + double diag = (is == 0) ? diag_coeff : 0.0; + for (int m1 = 0; m1 < m_size; m1++) + { + for (int m2 = 0; m2 < m_size; m2++) + { + vu[start + m1 * m_size + m2] = u_value * + (diag * (m1 == m2) - occ[start + m2 * m_size + m1]); + energy_u += u_value * weight_eu + * occ[start + m2 * m_size + m1] + * occ[start + m1 * m_size + m2]; + } + } + } + pauli_to_spin_basis(vu, m_size); + return energy_u; +} + +double compute_vu_scalar( + std::complex* vu, + const double* occ, + double u_value, + double diag_coeff, + double weight_eu, + int m_size) +{ + double energy_u = 0.0; + for (int m1 = 0; m1 < m_size; m1++) + { + for (int m2 = 0; m2 < m_size; m2++) + { + vu[m1 * m_size + m2] = u_value * + (diag_coeff * (m1 == m2) - occ[m2 * m_size + m1]); + energy_u += u_value * weight_eu + * occ[m2 * m_size + m1] + * occ[m1 * m_size + m2]; + } + } + return energy_u; +} + +void accumulate_occ_spinor( + double* occ_mat_out, + const std::complex* becp, + int nbands, + int npol, + int nkb, + int begin_ih, + int m_begin, + int tlp1, + const ModuleBase::matrix& wg, + int ik) +{ + const int tlp1_2 = tlp1 * tlp1; + for (int ib = 0; ib < nbands; ib++) + { + const double weight = wg(ik, ib); + int ind_m1m2 = 0; + for (int m1 = 0; m1 < tlp1; m1++) + { + const int index_m1 = ib * npol * nkb + begin_ih + m_begin + m1; + for (int m2 = 0; m2 < tlp1; m2++) + { + const int index_m2 = ib * npol * nkb + begin_ih + m_begin + m2; + std::complex occ[4]; + occ[0] = weight * std::conj(becp[index_m1]) * becp[index_m2]; + occ[1] = weight * std::conj(becp[index_m1]) * becp[index_m2 + nkb]; + occ[2] = weight * std::conj(becp[index_m1 + nkb]) * becp[index_m2]; + occ[3] = weight * std::conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb]; + occ_mat_out[ind_m1m2] += (occ[0] + occ[3]).real(); + occ_mat_out[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real(); + occ_mat_out[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag(); + occ_mat_out[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real(); + ind_m1m2++; + } + } + } +} + +void accumulate_occ_scalar( + double* occ_mat_out, + const std::complex* becp, + int nbands, + int nkb, + int begin_ih, + int m_begin, + int tlp1, + const ModuleBase::matrix& wg, + int ik) +{ + for (int ib = 0; ib < nbands; ib++) + { + const double weight = wg(ik, ib); + int ind_m1m2 = 0; + for (int m1 = 0; m1 < tlp1; m1++) + { + const int index_m1 = ib * nkb + begin_ih + m_begin + m1; + for (int m2 = 0; m2 < tlp1; m2++) + { + const int index_m2 = ib * nkb + begin_ih + m_begin + m2; + occ_mat_out[ind_m1m2] += weight * (std::conj(becp[index_m1]) * becp[index_m2]).real(); + ind_m1m2++; + } + } + } +} + +} // namespace dftu_pw diff --git a/source/source_pw/module_pwdft/dftu_pw.h b/source/source_pw/module_pwdft/dftu_tools_pw.h similarity index 98% rename from source/source_pw/module_pwdft/dftu_pw.h rename to source/source_pw/module_pwdft/dftu_tools_pw.h index 49ac6b85ee..738c0eda37 100644 --- a/source/source_pw/module_pwdft/dftu_pw.h +++ b/source/source_pw/module_pwdft/dftu_tools_pw.h @@ -1,5 +1,5 @@ -#ifndef DFTU_PW_H -#define DFTU_PW_H +#ifndef DFTU_TOOLS_PW_H +#define DFTU_TOOLS_PW_H #include #include "source_base/matrix.h" From c27c60de5035da2facb8070d0aa2c21147294c49 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 15:13:03 +0800 Subject: [PATCH 13/23] test(dftu_pw): rewire 7 dftu_pw_test cases to call real free functions Step 4d of the dftu_pw decoupling plan. The 7 tests in dftu_pw_test.cpp previously used arithmetic re-implementations of the VU/energy/occ formulas, meaning they could not catch bugs in the real dftu_pw implementations (test and production code were two independent copies). Now that the free functions live in dftu_tools_pw.{h,cpp} with minimal dependencies (only and matrix.h), the tests can link against the real implementations directly. Tests rewired: - VUPotNspin1_DiagonalLocale -> compute_vu_scalar - VUPotNspin2_TwoSpinChannels -> compute_vu_scalar (twice, up/down) - VUPotNspin4_PauliTransform -> pauli_to_spin_basis (in-place) - EnergyNspin12_DiagonalLocale -> compute_vu_scalar (check return value) - EnergyNspin4_WithOffDiagonal -> compute_vu_spinor (check return value) - LocaleAccumNspin12 -> accumulate_occ_scalar - LocaleAccumNspin4_PauliComponents -> accumulate_occ_spinor Tests kept as arithmetic (out of dftu_tools_pw scope): - EnergyWeightsAllNspin, BecpIndexNspin12vs4 (pure constants/arithmetic) - MultiAtomSplitLayout_Nspin2 (Plus_U_Base member layout) - OnsitePsOpKernel_Nspin2_Npol1 (onsite_op.cpp kernel) Files changed: - source/source_lcao/module_dftu/test/dftu_pw_test.cpp - add includes: , source_base/matrix.h, source_pw/module_pwdft/dftu_tools_pw.h - replace inlined arithmetic loops with calls to the real free functions; expected values unchanged - VUPotNspin4_PauliTransform: m_size 3 -> 1 (the test only fills a single (m1,m2) pair; m_size=1 matches the data layout) - EnergyNspin4_WithOffDiagonal: pass diag_coeff=1.0 (the nspin==4 value used in cal_occ_pw) - source/source_lcao/module_dftu/test/CMakeLists.txt - add ../../../source_pw/module_pwdft/dftu_tools_pw.cpp to dftu_pw_test SOURCES so the real implementations are linked Effects: - tests now exercise the same code path as cal_occ_pw - arithmetic re-implementations removed (~80 lines of duplicated logic) - any future change to the free functions is automatically covered Verification: - make dftu_pw_test build passed (verified by user) - ctest -R dftu_pw_test passed (verified by user) --- .../module_dftu/test/CMakeLists.txt | 1 + .../module_dftu/test/dftu_pw_test.cpp | 137 +++++++----------- 2 files changed, 57 insertions(+), 81 deletions(-) diff --git a/source/source_lcao/module_dftu/test/CMakeLists.txt b/source/source_lcao/module_dftu/test/CMakeLists.txt index 506ee79523..bad024242c 100644 --- a/source/source_lcao/module_dftu/test/CMakeLists.txt +++ b/source/source_lcao/module_dftu/test/CMakeLists.txt @@ -4,6 +4,7 @@ AddTest( TARGET dftu_pw_test LIBS base device parameter SOURCES dftu_pw_test.cpp + ../../../source_pw/module_pwdft/dftu_tools_pw.cpp ) AddTest( diff --git a/source/source_lcao/module_dftu/test/dftu_pw_test.cpp b/source/source_lcao/module_dftu/test/dftu_pw_test.cpp index 5dc811b687..ae50e082e1 100644 --- a/source/source_lcao/module_dftu/test/dftu_pw_test.cpp +++ b/source/source_lcao/module_dftu/test/dftu_pw_test.cpp @@ -1,8 +1,11 @@ #include "gtest/gtest.h" #include +#include #define private public #include "source_io/module_parameter/parameter.h" #undef private +#include "source_base/matrix.h" +#include "source_pw/module_pwdft/dftu_tools_pw.h" /*********************************************************************** * Unit tests for DFT+U PW nspin=1/2/4 support (PR-2) @@ -80,9 +83,7 @@ TEST_F(DftuPwTest, VUPotNspin1_DiagonalLocale) locale_c[m * m_size + m] = 0.3; // diagonal std::vector> vu(size, {0.0, 0.0}); - for (int m1 = 0; m1 < m_size; m1++) - for (int m2 = 0; m2 < m_size; m2++) - vu[m1 * m_size + m2] = U_val * (0.5 * (m1 == m2) - locale_c[m2 * m_size + m1]); + dftu_pw::compute_vu_scalar(vu.data(), locale_c.data(), U_val, 0.5, 1.0, m_size); // diagonal: U*(0.5 - 0.3) = 4.0*0.2 = 0.8 for (int m = 0; m < m_size; m++) @@ -104,13 +105,15 @@ TEST_F(DftuPwTest, VUPotNspin2_TwoSpinChannels) locale_up[0] = 0.4; // locale_up(0,0) = 0.4 locale_dn[0] = 0.1; // locale_dn(0,0) = 0.1 - // VU_up[0,0] = U*(0.5 - 0.4) = 0.5 - double vu_up_00 = U_val * (0.5 - locale_up[0 * m_size + 0]); - EXPECT_DOUBLE_EQ(vu_up_00, 0.5); + std::vector> vu_up(size, {0.0, 0.0}); + std::vector> vu_dn(size, {0.0, 0.0}); + dftu_pw::compute_vu_scalar(vu_up.data(), locale_up.data(), U_val, 0.5, 0.5, m_size); + dftu_pw::compute_vu_scalar(vu_dn.data(), locale_dn.data(), U_val, 0.5, 0.5, m_size); + // VU_up[0,0] = U*(0.5 - 0.4) = 0.5 + EXPECT_DOUBLE_EQ(vu_up[0].real(), 0.5); // VU_dn[0,0] = U*(0.5 - 0.1) = 2.0 - double vu_dn_00 = U_val * (0.5 - locale_dn[0 * m_size + 0]); - EXPECT_DOUBLE_EQ(vu_dn_00, 2.0); + EXPECT_DOUBLE_EQ(vu_dn[0].real(), 2.0); } TEST_F(DftuPwTest, VUPotNspin4_PauliTransform) @@ -120,30 +123,26 @@ TEST_F(DftuPwTest, VUPotNspin4_PauliTransform) // vu_spin[3] = 0.5*(vu_pauli[0] - vu_pauli[3]) // vu_spin[1] = 0.5*(vu_pauli[1] + i*vu_pauli[2]) // vu_spin[2] = 0.5*(vu_pauli[1] - i*vu_pauli[2]) - const int m_size = 3; + const int m_size = 1; const int size = m_size * m_size; - // For a single (m1,m2) pair, test the Pauli->spin transform - std::complex vu_pauli[4]; - vu_pauli[0] = {1.0, 0.0}; // charge channel - vu_pauli[1] = {0.5, 0.0}; // sigma_x - vu_pauli[2] = {0.3, 0.0}; // sigma_y - vu_pauli[3] = {0.2, 0.0}; // sigma_z - - std::complex vu_spin[4]; - vu_spin[0] = 0.5 * (vu_pauli[0] + vu_pauli[3]); - vu_spin[3] = 0.5 * (vu_pauli[0] - vu_pauli[3]); - vu_spin[1] = 0.5 * (vu_pauli[1] + std::complex(0.0, 1.0) * vu_pauli[2]); - vu_spin[2] = 0.5 * (vu_pauli[1] - std::complex(0.0, 1.0) * vu_pauli[2]); - - EXPECT_DOUBLE_EQ(vu_spin[0].real(), 0.6); // 0.5*(1.0+0.2) - EXPECT_DOUBLE_EQ(vu_spin[0].imag(), 0.0); - EXPECT_DOUBLE_EQ(vu_spin[3].real(), 0.4); // 0.5*(1.0-0.2) - EXPECT_DOUBLE_EQ(vu_spin[3].imag(), 0.0); - EXPECT_DOUBLE_EQ(vu_spin[1].real(), 0.25); // 0.5*0.5 - EXPECT_DOUBLE_EQ(vu_spin[1].imag(), 0.15); // 0.5*0.3 - EXPECT_DOUBLE_EQ(vu_spin[2].real(), 0.25); // 0.5*0.5 - EXPECT_DOUBLE_EQ(vu_spin[2].imag(), -0.15);// -0.5*0.3 + // For a single (m1,m2) pair, test the Pauli->spin transform (in-place) + std::complex vu[4]; + vu[0] = {1.0, 0.0}; // charge channel + vu[1] = {0.5, 0.0}; // sigma_x + vu[2] = {0.3, 0.0}; // sigma_y + vu[3] = {0.2, 0.0}; // sigma_z + + dftu_pw::pauli_to_spin_basis(vu, m_size); + + EXPECT_DOUBLE_EQ(vu[0].real(), 0.6); // 0.5*(1.0+0.2) + EXPECT_DOUBLE_EQ(vu[0].imag(), 0.0); + EXPECT_DOUBLE_EQ(vu[3].real(), 0.4); // 0.5*(1.0-0.2) + EXPECT_DOUBLE_EQ(vu[3].imag(), 0.0); + EXPECT_DOUBLE_EQ(vu[1].real(), 0.25); // 0.5*0.5 + EXPECT_DOUBLE_EQ(vu[1].imag(), 0.15); // 0.5*0.3 + EXPECT_DOUBLE_EQ(vu[2].real(), 0.25); // 0.5*0.5 + EXPECT_DOUBLE_EQ(vu[2].imag(), -0.15);// -0.5*0.3 } // ===================================================================== @@ -164,19 +163,21 @@ TEST_F(DftuPwTest, EnergyNspin12_DiagonalLocale) locale_c[2 * m_size + 2] = 0.2; // nspin=1: E = U * 1.0 * (0.5^2 + 0.3^2 + 0.2^2) = 4 * 0.38 = 1.52 - double energy_u = 0.0; - for (int m1 = 0; m1 < m_size; m1++) - for (int m2 = 0; m2 < m_size; m2++) - energy_u += U_val * 1.0 * locale_c[m2 * m_size + m1] * locale_c[m1 * m_size + m2]; + std::vector> vu_nspin1(size, {0.0, 0.0}); + double energy_u = dftu_pw::compute_vu_scalar( + vu_nspin1.data(), locale_c.data(), U_val, 0.5, 1.0, m_size); EXPECT_DOUBLE_EQ(energy_u, 1.52); // nspin=2: two spin channels, weight_eu = 0.5 - energy_u = 0.0; std::vector locale_up(size, 0.0), locale_dn(size, 0.0); locale_up[0] = 0.4; locale_dn[0] = 0.6; - // Only diagonal element (0,0) is non-zero, so only m1=0, m2=0 contributes - energy_u += U_val * 0.5 * locale_up[0] * locale_up[0]; - energy_u += U_val * 0.5 * locale_dn[0] * locale_dn[0]; + std::vector> vu_up(size, {0.0, 0.0}); + std::vector> vu_dn(size, {0.0, 0.0}); + energy_u = 0.0; + energy_u += dftu_pw::compute_vu_scalar( + vu_up.data(), locale_up.data(), U_val, 0.5, 0.5, m_size); + energy_u += dftu_pw::compute_vu_scalar( + vu_dn.data(), locale_dn.data(), U_val, 0.5, 0.5, m_size); // E = U*0.5*(0.4^2 + 0.6^2) = 4*0.5*(0.16+0.36) = 1.04 EXPECT_DOUBLE_EQ(energy_u, 1.04); } @@ -198,15 +199,9 @@ TEST_F(DftuPwTest, EnergyNspin4_WithOffDiagonal) locale_c[size + 0] = 0.2; locale_c[size + 1] = 0.0; locale_c[size + 2] = 0.0; locale_c[size + 3] = 0.2; - double energy_u = 0.0; - for (int is = 0; is < 4; is++) { - int start = is * size; - for (int m1 = 0; m1 < m_size; m1++) - for (int m2 = 0; m2 < m_size; m2++) - energy_u += U_val * weight_eu - * locale_c[start + m2 * m_size + m1] - * locale_c[start + m1 * m_size + m2]; - } + std::vector> vu(size * 4, {0.0, 0.0}); + double energy_u = dftu_pw::compute_vu_spinor( + vu.data(), locale_c.data(), U_val, 1.0, weight_eu, m_size); // is=0: 2*0.25*(0.5*0.5 + 0.1*0.1 + 0.1*0.1 + 0.5*0.5) = 0.26 // is=1: 2*0.25*(0.2*0.2 + 0 + 0 + 0.2*0.2) = 0.04 @@ -221,25 +216,20 @@ TEST_F(DftuPwTest, EnergyNspin4_WithOffDiagonal) TEST_F(DftuPwTest, LocaleAccumNspin12) { // nspin=1/2: locale[m1*m_size+m2] += weight * real(conj(becp[m1]) * becp[m2]) - const int m_size = 3, nkb = 5, begin_ih = 0, m_begin = 0, nbands = 2; - const double weights[2] = {1.0, 0.5}; + const int m_size = 3, nkb = 5, begin_ih = 0, m_begin = 0, nbands = 2, ik = 0; std::vector> becp(nbands * nkb, {0.0, 0.0}); becp[0 * nkb + 0] = {1.0, 0.0}; becp[0 * nkb + 1] = {0.0, 1.0}; becp[0 * nkb + 2] = {0.5, 0.5}; becp[1 * nkb + 0] = {0.5, 0.0}; becp[1 * nkb + 1] = {0.5, -0.5}; becp[1 * nkb + 2] = {0.0, 1.0}; + ModuleBase::matrix wg(1, nbands); + wg(0, 0) = 1.0; + wg(0, 1) = 0.5; + std::vector locale_c(m_size * m_size, 0.0); - for (int ib = 0; ib < nbands; ib++) { - int ind_m1m2 = 0; - for (int m1 = 0; m1 < m_size; m1++) { - const int index_m1 = ib * nkb + begin_ih + m_begin + m1; - for (int m2 = 0; m2 < m_size; m2++) { - const int index_m2 = ib * nkb + begin_ih + m_begin + m2; - locale_c[ind_m1m2] += weights[ib] * (std::conj(becp[index_m1]) * becp[index_m2]).real(); - ind_m1m2++; - } - } - } + dftu_pw::accumulate_occ_scalar( + locale_c.data(), becp.data(), nbands, nkb, + begin_ih, m_begin, m_size, wg, ik); // band0, w=1.0: locale[0,0] = 1.0*|1|^2 = 1.0 // band1, w=0.5: locale[0,0] = 0.5*|0.5|^2 = 0.125 @@ -260,8 +250,7 @@ TEST_F(DftuPwTest, LocaleAccumNspin4_PauliComponents) // locale[ind+size] += (occ[1]+occ[2]).real() -- sigma_x // locale[ind+2*size] += (occ[1]-occ[2]).imag() -- sigma_y // locale[ind+3*size] += (occ[0]-occ[3]).real() -- sigma_z - const int m_size = 1, nkb = 2, nbands = 1; - const double weight = 1.0; + const int m_size = 1, nkb = 2, nbands = 1, npol = 2, ik = 0; std::vector> becp(nbands * 2 * nkb, {0.0, 0.0}); becp[0] = {0.8, 0.0}; // becp_up[m=0] @@ -270,25 +259,11 @@ TEST_F(DftuPwTest, LocaleAccumNspin4_PauliComponents) const int size = m_size * m_size; std::vector locale_c(size * 4, 0.0); - for (int ib = 0; ib < nbands; ib++) { - int ind_m1m2 = 0; - for (int m1 = 0; m1 < m_size; m1++) { - const int index_m1 = ib * 2 * nkb + 0 + m1; - for (int m2 = 0; m2 < m_size; m2++) { - const int index_m2 = ib * 2 * nkb + 0 + m2; - std::complex occ[4]; - occ[0] = weight * std::conj(becp[index_m1]) * becp[index_m2]; - occ[1] = weight * std::conj(becp[index_m1]) * becp[index_m2 + nkb]; - occ[2] = weight * std::conj(becp[index_m1 + nkb]) * becp[index_m2]; - occ[3] = weight * std::conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb]; - locale_c[ind_m1m2] += (occ[0] + occ[3]).real(); - locale_c[ind_m1m2 + size] += (occ[1] + occ[2]).real(); - locale_c[ind_m1m2 + 2 * size] += (occ[1] - occ[2]).imag(); - locale_c[ind_m1m2 + 3 * size] += (occ[0] - occ[3]).real(); - ind_m1m2++; - } - } - } + ModuleBase::matrix wg(1, nbands); + wg(0, 0) = 1.0; + dftu_pw::accumulate_occ_spinor( + locale_c.data(), becp.data(), nbands, npol, nkb, + 0, 0, m_size, wg, ik); // becp_up = (0.8, 0), becp_dn = (0, 0.6) // occ[0] = 0.64, occ[1] = (0, 0.48), occ[2] = (0, -0.48), occ[3] = 0.36 From 144c795723a0c5a87c922029775eadb874e15fd5 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 16:07:19 +0800 Subject: [PATCH 14/23] refactor(dftu_lcao): extract force/stress as free functions, unify DFTU_LCAO namespace Extract the 5 force/stress member functions of Plus_U from dftu_force.cpp into free functions declared in a new dftu_force.h header, mirroring the existing dftu_folding pattern. The top-level force_stress takes a Plus_U& parameter because it still calls Plus_U::cal_VU_pot_mat_real/complex (defined in dftu_tools.cpp); the four inner functions (cal_force_k, cal_stress_k, cal_force_gamma, cal_stress_gamma) are fully decoupled and take their dependencies (npol, nlocal, ks_solver, orb_cutoff, iatlnmipol2iwt, orbital_corr) as explicit parameters, so they are unit-testable without a Plus_U instance. Consolidate the two module-local namespaces dftu_force and dftu_folding into a single namespace DFTU_LCAO. The project-wide hamilt:: namespace (used by dftu_lcao_op.h/cpp, dftu_fs.cpp, dftu_lcao_op_legacy.h/cpp for operator classes inheriting from hamilt::OperatorLCAO) is left untouched to avoid breaking the ABACUS hamilt operator framework. All callers updated: dftu_force:: and dftu_folding:: prefixes are replaced by DFTU_LCAO:: in dftu_force.cpp, dftu_occup.cpp, and force_stress_lcao.cpp; TITLE/timer/WARNING_QUIT identifier strings in dftu_force.cpp are renamed accordingly. Plus_U_Base gains two public read-only accessors (get_iatlnmipol2iwt, get_orbital_corr_vec) so the free functions can receive the lookup table and orbital_corr vector as parameters. Plus_U gains 8 public getters (get_paraV, get_npol, get_nlocal, get_ks_solver, get_orb_cutoff, is_gamma_only_local, is_cal_force, is_cal_stress) and cal_VU_pot_mat_real/complex are promoted from private to public so the free function force_stress can call them via the Plus_U& parameter. get_onebody_eff_pot remains private. Verification performed: - cmake --build build_max_para_test -j 4: clean build, no errors, no warnings - ./build_max_para_test/abacus_max_para --version: ABACUS version v3.11.0-beta8 - OMP_NUM_THREADS=1 ctest --test-dir build_max_para_test -R '^dftu_(pw_test|core_test|operator_test|lcao_test)$': 4/4 pass - python3 tools/03_code_analysis/agent_governance_check.py --staged: only warnings (header deps, test evidence, doc sync), all Exception allowed: yes, no blockers - 17_DS_DFTU: 45/50 sub-cases pass; the 5 PW Double-Spin failures are pre-existing baseline (verified via git stash + rerun with identical deviations), unrelated to this refactor - dft_plus_u==2 + force/stress path remains disabled per the existing comment in force_stress_lcao.cpp:429-454; not end-to-end tested. --- source/source_lcao/force_stress_lcao.cpp | 3 +- .../source_lcao/module_dftu/dftu_folding.cpp | 4 +- source/source_lcao/module_dftu/dftu_folding.h | 4 +- source/source_lcao/module_dftu/dftu_force.cpp | 250 ++++++++++-------- source/source_lcao/module_dftu/dftu_force.h | 106 ++++++++ source/source_lcao/module_dftu/dftu_lcao.h | 66 +---- source/source_lcao/module_dftu/dftu_occup.cpp | 2 +- source/source_pw/module_pwdft/dftu_base.h | 7 + 8 files changed, 269 insertions(+), 173 deletions(-) create mode 100644 source/source_lcao/module_dftu/dftu_force.h diff --git a/source/source_lcao/force_stress_lcao.cpp b/source/source_lcao/force_stress_lcao.cpp index ae5635f5ce..fd9f701ec7 100644 --- a/source/source_lcao/force_stress_lcao.cpp +++ b/source/source_lcao/force_stress_lcao.cpp @@ -2,6 +2,7 @@ #include "source_base/parallel_reduce.h" #include "source_lcao/module_dftu/dftu_lcao.h" //Quxin add for DFT+U on 20201029 +#include "source_lcao/module_dftu/dftu_force.h" #include "source_io/module_output/output_log.h" #include "source_io/module_parameter/parameter.h" // new @@ -456,7 +457,7 @@ void Force_Stress_LCAO::getForceStress(UnitCell& ucell, std::vector>* dmk_d = nullptr; std::vector>>* dmk_c = nullptr; assign_dmk_ptr(dmat.dm, dmk_d, dmk_c, PARAM.globalv.gamma_only_local); - dftu.force_stress(ucell, gd, dmk_d, dmk_c, pv, fsr_dftu, force_u, stress_u, kv, PARAM.globalv.npol); + DFTU_LCAO::force_stress(dftu, ucell, gd, dmk_d, dmk_c, pv, fsr_dftu, force_u, stress_u, kv, PARAM.globalv.npol); } else { diff --git a/source/source_lcao/module_dftu/dftu_folding.cpp b/source/source_lcao/module_dftu/dftu_folding.cpp index feab5ff4d0..c0856dd311 100644 --- a/source/source_lcao/module_dftu/dftu_folding.cpp +++ b/source/source_lcao/module_dftu/dftu_folding.cpp @@ -8,7 +8,7 @@ #include "source_hamilt/module_hcontainer/hcontainer.h" #include "source_hamilt/module_hcontainer/hcontainer_funcs.h" -namespace dftu_folding { +namespace DFTU_LCAO { bool is_adjacent_pair(const std::vector& orb_cutoff, const UnitCell& ucell, @@ -296,6 +296,6 @@ void folding_matrix_k_new(const std::string& ks_solver, ModuleBase::timer::end("Plus_U", "folding_matrix_k_new"); } -} // namespace dftu_folding +} // namespace DFTU_LCAO #endif // __LCAO diff --git a/source/source_lcao/module_dftu/dftu_folding.h b/source/source_lcao/module_dftu/dftu_folding.h index 2c7a21023a..da3d2995a8 100644 --- a/source/source_lcao/module_dftu/dftu_folding.h +++ b/source/source_lcao/module_dftu/dftu_folding.h @@ -19,7 +19,7 @@ #ifdef __LCAO -namespace dftu_folding { +namespace DFTU_LCAO { /// @brief Judge whether atom pair (T1,I1) and (T2,I2,tau2) are adjacent /// by direct orbital cutoff overlap or three-body bridging via a @@ -85,7 +85,7 @@ void folding_matrix_k_new(const std::string& ks_solver, int ik, hamilt::Hamilt>* p_ham); -} // namespace dftu_folding +} // namespace DFTU_LCAO #endif // __LCAO diff --git a/source/source_lcao/module_dftu/dftu_force.cpp b/source/source_lcao/module_dftu/dftu_force.cpp index f139f3fb0a..679c926f7d 100644 --- a/source/source_lcao/module_dftu/dftu_force.cpp +++ b/source/source_lcao/module_dftu/dftu_force.cpp @@ -1,8 +1,9 @@ #include "source_io/module_parameter/parameter.h" #ifdef __LCAO -#include "dftu_lcao.h" +#include "dftu_force.h" #include "dftu_folding.h" +#include "dftu_lcao.h" #include "source_base/constants.h" #include "source_base/global_function.h" #include "source_base/inverse_matrix.h" @@ -21,21 +22,25 @@ #include #include #include - - -void Plus_U::force_stress(const UnitCell& ucell, - const Grid_Driver& gd, - std::vector>* dmk_d, - std::vector>>* dmk_c, - const Parallel_Orbitals& pv, - ForceStressArrays& fsr, - ModuleBase::matrix& force_dftu, - ModuleBase::matrix& stress_dftu, - const K_Vectors& kv, - const int npol) +#include + + +namespace DFTU_LCAO { + +void force_stress(Plus_U& dftu, + const UnitCell& ucell, + const Grid_Driver& gd, + std::vector>* dmk_d, + std::vector>>* dmk_c, + const Parallel_Orbitals& pv, + ForceStressArrays& fsr, + ModuleBase::matrix& force_dftu, + ModuleBase::matrix& stress_dftu, + const K_Vectors& kv, + const int npol) { - ModuleBase::TITLE("Plus_U", "force_stress"); - ModuleBase::timer::start("Plus_U", "force_stress"); + ModuleBase::TITLE("DFTU_LCAO", "force_stress"); + ModuleBase::timer::start("DFTU_LCAO", "force_stress"); // Defensive null check: the legacy dft_plus_u==2 force/stress path // requires fsr.DSloc_x/y/z (gamma_only) or fsr.DSloc_Rx/Ry/Rz (multik) @@ -44,20 +49,20 @@ void Plus_U::force_stress(const UnitCell& ucell, // fsr_dftu is created without allocation), we fail early with a clear // message instead of letting pdgemm_ dereference nullptr and crash. // See force_stress_lcao.cpp for the historical background. - if (this->gamma_only_local) + if (dftu.is_gamma_only_local()) { - if (this->cal_force + if (dftu.is_cal_force() && (fsr.DSloc_x == nullptr || fsr.DSloc_y == nullptr || fsr.DSloc_z == nullptr)) { - ModuleBase::WARNING_QUIT("Plus_U::force_stress", + ModuleBase::WARNING_QUIT("DFTU_LCAO::force_stress", "fsr.DSloc_x/y/z are nullptr in gamma_only path; the caller must allocate and fill them. " "See notes in source/source_lcao/force_stress_lcao.cpp."); } - if (this->cal_stress + if (dftu.is_cal_stress() && (fsr.DSloc_x == nullptr || fsr.DSloc_y == nullptr || fsr.DSloc_z == nullptr || fsr.DH_r == nullptr)) { - ModuleBase::WARNING_QUIT("Plus_U::force_stress", + ModuleBase::WARNING_QUIT("DFTU_LCAO::force_stress", "fsr.DSloc_x/y/z or fsr.DH_r is nullptr in gamma_only path; " "the caller must allocate and fill them. " "See notes in source/source_lcao/force_stress_lcao.cpp."); @@ -65,36 +70,36 @@ void Plus_U::force_stress(const UnitCell& ucell, } else { - if (this->cal_force + if (dftu.is_cal_force() && (fsr.DSloc_Rx == nullptr || fsr.DSloc_Ry == nullptr || fsr.DSloc_Rz == nullptr)) { - ModuleBase::WARNING_QUIT("Plus_U::force_stress", + ModuleBase::WARNING_QUIT("DFTU_LCAO::force_stress", "fsr.DSloc_Rx/Ry/Rz are nullptr in multik path; the caller must allocate and fill them. " "See notes in source/source_lcao/force_stress_lcao.cpp."); } - if (this->cal_stress + if (dftu.is_cal_stress() && (fsr.DSloc_Rx == nullptr || fsr.DSloc_Ry == nullptr || fsr.DSloc_Rz == nullptr || fsr.DH_r == nullptr)) { - ModuleBase::WARNING_QUIT("Plus_U::force_stress", + ModuleBase::WARNING_QUIT("DFTU_LCAO::force_stress", "fsr.DSloc_Rx/Ry/Rz or fsr.DH_r is nullptr in multik path; " "the caller must allocate and fill them. " "See notes in source/source_lcao/force_stress_lcao.cpp."); } } - const int nlocal = this->nlocal; + const int nlocal = dftu.get_nlocal(); - if (this->cal_force) + if (dftu.is_cal_force()) { force_dftu.zero_out(); } - if (this->cal_stress) + if (dftu.is_cal_stress()) { stress_dftu.zero_out(); } - if (this->gamma_only_local) + if (dftu.is_gamma_only_local()) { const char transN = 'N'; const char transT = 'T'; @@ -111,7 +116,7 @@ void Plus_U::force_stress(const UnitCell& ucell, double* VU = new double[pv.nloc]; - this->cal_VU_pot_mat_real(spin, false, VU, npol); + dftu.cal_VU_pot_mat_real(spin, false, VU, npol); #ifdef __MPI ScalapackConnector::gemm(transT, transN, nlocal, nlocal, nlocal, @@ -123,22 +128,21 @@ void Plus_U::force_stress(const UnitCell& ucell, delete[] VU; - if (this->cal_force) + if (dftu.is_cal_force()) { - this->cal_force_gamma(ucell,&rho_VU[0], pv, fsr.DSloc_x, fsr.DSloc_y, fsr.DSloc_z, force_dftu); + cal_force_gamma(dftu.get_nlocal(), dftu.get_npol(), + dftu.get_orbital_corr_vec(), dftu.get_iatlnmipol2iwt(), + ucell, &rho_VU[0], pv, + fsr.DSloc_x, fsr.DSloc_y, fsr.DSloc_z, force_dftu); } - if (this->cal_stress) + if (dftu.is_cal_stress()) { - this->cal_stress_gamma(ucell, - pv, - &gd, - fsr.DSloc_x, - fsr.DSloc_y, - fsr.DSloc_z, - fsr.DH_r, - &rho_VU[0], - stress_dftu); + cal_stress_gamma(dftu.get_nlocal(), dftu.get_npol(), + dftu.get_ks_solver(), dftu.get_orb_cutoff(), + ucell, pv, &gd, + fsr.DSloc_x, fsr.DSloc_y, fsr.DSloc_z, fsr.DH_r, + &rho_VU[0], stress_dftu); } } // ik } @@ -158,7 +162,7 @@ void Plus_U::force_stress(const UnitCell& ucell, std::complex* VU = new std::complex[pv.nloc]; - this->cal_VU_pot_mat_complex(spin, false, VU, npol); + dftu.cal_VU_pot_mat_complex(spin, false, VU, npol); #ifdef __MPI @@ -170,23 +174,28 @@ void Plus_U::force_stress(const UnitCell& ucell, delete[] VU; - if (this->cal_force) + if (dftu.is_cal_force()) { - cal_force_k(ucell, gd, fsr, pv, ik, &rho_VU[0], force_dftu, kv.kvec_d[ik]); + cal_force_k(dftu.get_nlocal(), dftu.get_npol(), + dftu.get_ks_solver(), dftu.get_orb_cutoff(), + dftu.get_orbital_corr_vec(), dftu.get_iatlnmipol2iwt(), + ucell, gd, fsr, pv, ik, &rho_VU[0], force_dftu, kv.kvec_d[ik]); } - if (this->cal_stress) + if (dftu.is_cal_stress()) { - cal_stress_k(ucell, gd, fsr, pv, ik, &rho_VU[0], stress_dftu, kv.kvec_d[ik]); + cal_stress_k(dftu.get_nlocal(), dftu.get_npol(), + dftu.get_ks_solver(), dftu.get_orb_cutoff(), + ucell, gd, fsr, pv, ik, &rho_VU[0], stress_dftu, kv.kvec_d[ik]); } } // ik } - if (this->cal_force) + if (dftu.is_cal_force()) { Parallel_Reduce::reduce_pool(force_dftu.c, force_dftu.nr * force_dftu.nc); } - if (this->cal_stress) + if (dftu.is_cal_stress()) { Parallel_Reduce::reduce_pool(stress_dftu.c, stress_dftu.nr * stress_dftu.nc); @@ -207,22 +216,28 @@ void Plus_U::force_stress(const UnitCell& ucell, } } } - ModuleBase::timer::end("Plus_U", "force_stress"); + ModuleBase::timer::end("DFTU_LCAO", "force_stress"); return; } -void Plus_U::cal_force_k(const UnitCell& ucell, - const Grid_Driver& gd, - ForceStressArrays& fsr, - const Parallel_Orbitals& pv, - const int ik, - const std::complex* rho_VU, - ModuleBase::matrix& force_dftu, - const ModuleBase::Vector3& kvec_d) +void cal_force_k(const int nlocal, + const int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const std::vector& orbital_corr, + const std::vector>>>>& iatlnmipol2iwt, + const UnitCell& ucell, + const Grid_Driver& gd, + ForceStressArrays& fsr, + const Parallel_Orbitals& pv, + const int ik, + const std::complex* rho_VU, + ModuleBase::matrix& force_dftu, + const ModuleBase::Vector3& kvec_d) { - ModuleBase::TITLE("Plus_U", "cal_force_k"); - ModuleBase::timer::start("Plus_U", "cal_force_k"); + ModuleBase::TITLE("DFTU_LCAO", "cal_force_k"); + ModuleBase::timer::start("DFTU_LCAO", "cal_force_k"); const char transN = 'N'; const char transC = 'C'; @@ -230,7 +245,6 @@ void Plus_U::cal_force_k(const UnitCell& ucell, const std::complex zero(0.0, 0.0); const std::complex one(1.0, 0.0); - const int nlocal = this->nlocal; assert(nlocal>0); std::vector> dm_VU_dSm(pv.nloc); @@ -238,7 +252,7 @@ void Plus_U::cal_force_k(const UnitCell& ucell, for (int dim = 0; dim < 3; dim++) { - dftu_folding::folding_matrix_k(this->npol, this->ks_solver, this->orb_cutoff_, + DFTU_LCAO::folding_matrix_k(npol, ks_solver, orb_cutoff, ucell, gd, fsr, pv, ik, dim + 1, 0, &dSm_k[0], kvec_d); #ifdef __MPI @@ -304,7 +318,7 @@ void Plus_U::cal_force_k(const UnitCell& ucell, for (int it = 0; it < ucell.ntype; it++) { const int NL = ucell.atoms[it].nwl + 1; - const int LC = get_orbital_corr(it); + const int LC = orbital_corr[it]; if (LC == -1) continue; @@ -314,7 +328,7 @@ void Plus_U::cal_force_k(const UnitCell& ucell, for (int l = 0; l < NL; l++) { - if (l != get_orbital_corr(it)) + if (l != orbital_corr[it]) continue; const int N = ucell.atoms[it].l_nchi[l]; @@ -325,9 +339,9 @@ void Plus_U::cal_force_k(const UnitCell& ucell, for (int m = 0; m < 2 * l + 1; m++) { - for (int ipol = 0; ipol < this->npol; ipol++) + for (int ipol = 0; ipol < npol; ipol++) { - const int iwt = this->iatlnmipol2iwt[iat][l][n][m][ipol]; + const int iwt = iatlnmipol2iwt[iat][l][n][m][ipol]; const int mu = pv.global2local_row(iwt); const int nu = pv.global2local_col(iwt); if (mu < 0 || nu < 0) @@ -341,24 +355,26 @@ void Plus_U::cal_force_k(const UnitCell& ucell, } // ia } // it } // end dim - ModuleBase::timer::end("Plus_U", "cal_force_k"); + ModuleBase::timer::end("DFTU_LCAO", "cal_force_k"); return; } -void Plus_U::cal_stress_k(const UnitCell& ucell, - const Grid_Driver& gd, - ForceStressArrays& fsr, - const Parallel_Orbitals& pv, - const int ik, - const std::complex* rho_VU, - ModuleBase::matrix& stress_dftu, - const ModuleBase::Vector3& kvec_d) +void cal_stress_k(const int nlocal, + const int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const UnitCell& ucell, + const Grid_Driver& gd, + ForceStressArrays& fsr, + const Parallel_Orbitals& pv, + const int ik, + const std::complex* rho_VU, + ModuleBase::matrix& stress_dftu, + const ModuleBase::Vector3& kvec_d) { - ModuleBase::TITLE("Plus_U", "cal_stress_k"); - ModuleBase::timer::start("Plus_U", "cal_stress_k"); - - const int nlocal = this->nlocal; + ModuleBase::TITLE("DFTU_LCAO", "cal_stress_k"); + ModuleBase::timer::start("DFTU_LCAO", "cal_stress_k"); const char transN = 'N'; const int one_int = 1; @@ -373,7 +389,7 @@ void Plus_U::cal_stress_k(const UnitCell& ucell, { for (int dim2 = dim1; dim2 < 3; dim2++) { - dftu_folding::folding_matrix_k(this->npol, this->ks_solver, this->orb_cutoff_, + DFTU_LCAO::folding_matrix_k(npol, ks_solver, orb_cutoff, ucell, gd, fsr, pv, ik, dim1 + 4, dim2, &dSR_k[0], kvec_d); #ifdef __MPI @@ -413,28 +429,31 @@ void Plus_U::cal_stress_k(const UnitCell& ucell, } // end dim2 } // end dim1 - ModuleBase::timer::end("Plus_U", "cal_stress_k"); + ModuleBase::timer::end("DFTU_LCAO", "cal_stress_k"); return; } -void Plus_U::cal_force_gamma(const UnitCell& ucell, - const double* rho_VU, - const Parallel_Orbitals& pv, - double* dsloc_x, - double* dsloc_y, - double* dsloc_z, - ModuleBase::matrix& force_dftu) +void cal_force_gamma(const int nlocal, + const int npol, + const std::vector& orbital_corr, + const std::vector>>>>& iatlnmipol2iwt, + const UnitCell& ucell, + const double* rho_VU, + const Parallel_Orbitals& pv, + double* dsloc_x, + double* dsloc_y, + double* dsloc_z, + ModuleBase::matrix& force_dftu) { - ModuleBase::TITLE("Plus_U", "cal_force_gamma"); - ModuleBase::timer::start("Plus_U", "cal_force_gamma"); + ModuleBase::TITLE("DFTU_LCAO", "cal_force_gamma"); + ModuleBase::timer::start("DFTU_LCAO", "cal_force_gamma"); const char transN = 'N'; const char transT = 'T'; const int one_int = 1; const double one = 1.0; const double zero = 0.0; const double minus_one = -1.0; - const int nlocal = this->nlocal; assert(nlocal>0); std::vector dm_VU_dSm(pv.nloc); @@ -541,9 +560,9 @@ void Plus_U::cal_force_gamma(const UnitCell& ucell, // Calculate the local occupation number matrix for (int m = 0; m < 2 * l + 1; m++) { - for (int ipol = 0; ipol < this->npol; ipol++) + for (int ipol = 0; ipol < npol; ipol++) { - const int iwt = this->iatlnmipol2iwt[iat][l][n][m][ipol]; + const int iwt = iatlnmipol2iwt[iat][l][n][m][ipol]; const int mu = pv.global2local_row(iwt); const int nu = pv.global2local_col(iwt); if (mu < 0 || nu < 0) @@ -558,23 +577,27 @@ void Plus_U::cal_force_gamma(const UnitCell& ucell, } // it } // end dim - ModuleBase::timer::end("Plus_U", "cal_force_gamma"); + ModuleBase::timer::end("DFTU_LCAO", "cal_force_gamma"); return; } -void Plus_U::cal_stress_gamma(const UnitCell& ucell, - const Parallel_Orbitals& pv, - const Grid_Driver* gd, - double* dsloc_x, - double* dsloc_y, - double* dsloc_z, - double* dh_r, - const double* rho_VU, - ModuleBase::matrix& stress_dftu) +void cal_stress_gamma(const int nlocal, + const int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const UnitCell& ucell, + const Parallel_Orbitals& pv, + const Grid_Driver* gd, + double* dsloc_x, + double* dsloc_y, + double* dsloc_z, + double* dh_r, + const double* rho_VU, + ModuleBase::matrix& stress_dftu) { - ModuleBase::TITLE("Plus_U", "cal_stress_gamma"); - ModuleBase::timer::start("Plus_U", "cal_stress_gamma"); + ModuleBase::TITLE("DFTU_LCAO", "cal_stress_gamma"); + ModuleBase::timer::start("DFTU_LCAO", "cal_stress_gamma"); const char transN = 'N'; const int one_int = 1; @@ -585,13 +608,11 @@ void Plus_U::cal_stress_gamma(const UnitCell& ucell, std::vector dSR_gamma(pv.nloc); std::vector dm_VU_sover(pv.nloc); - const int nlocal = this->nlocal; - for (int dim1 = 0; dim1 < 3; dim1++) { for (int dim2 = dim1; dim2 < 3; dim2++) { - dftu_folding::fold_dSR_gamma(this->npol, this->ks_solver, this->orb_cutoff_, + DFTU_LCAO::fold_dSR_gamma(npol, ks_solver, orb_cutoff, ucell, pv, gd, dsloc_x, dsloc_y, dsloc_z, dh_r, dim1, dim2, &dSR_gamma[0]); #ifdef __MPI @@ -616,14 +637,14 @@ void Plus_U::cal_stress_gamma(const UnitCell& ucell, pv.desc); #endif - for (int ir = 0; ir < this->paraV->nrow; ir++) + for (int ir = 0; ir < pv.nrow; ir++) { - const int iwt1 = this->paraV->local2global_row(ir); + const int iwt1 = pv.local2global_row(ir); - for (int ic = 0; ic < this->paraV->ncol; ic++) + for (int ic = 0; ic < pv.ncol; ic++) { - const int iwt2 = this->paraV->local2global_col(ic); - const int irc = ic * this->paraV->nrow + ir; + const int iwt2 = pv.local2global_col(ic); + const int irc = ic * pv.nrow + ir; if (iwt1 == iwt2) stress_dftu(dim1, dim2) += 2.0 * dm_VU_sover[irc]; @@ -632,7 +653,10 @@ void Plus_U::cal_stress_gamma(const UnitCell& ucell, } // end dim2 } // end dim1 - ModuleBase::timer::end("Plus_U", "cal_stress_gamma"); + ModuleBase::timer::end("DFTU_LCAO", "cal_stress_gamma"); return; } + +} // namespace DFTU_LCAO + #endif diff --git a/source/source_lcao/module_dftu/dftu_force.h b/source/source_lcao/module_dftu/dftu_force.h new file mode 100644 index 0000000000..9c56199021 --- /dev/null +++ b/source/source_lcao/module_dftu/dftu_force.h @@ -0,0 +1,106 @@ +/// @file dftu_force.h +/// @brief Free-function helpers for DFT+U force and stress, extracted from +/// Plus_U. The top-level force_stress takes a Plus_U& because it needs +/// to call Plus_U::cal_VU_pot_mat_real/complex; the four inner +/// functions are fully decoupled and take their dependencies as +/// explicit parameters (mirroring the folding helpers in the same +/// DFTU_LCAO namespace). +#ifndef DFTU_FORCE_H +#define DFTU_FORCE_H + +#include "source_basis/module_ao/parallel_orbitals.h" +#include "source_base/matrix.h" +#include "source_base/vector3.h" +#include "source_cell/klist.h" +#include "source_cell/module_neighbor/sltk_grid_driver.h" +#include "source_cell/unitcell.h" +#include "source_lcao/force_stress_arrays.h" + +#include +#include +#include + +#ifdef __LCAO + +class Plus_U; + +namespace DFTU_LCAO { + +/// @brief Top-level entry: drives force/stress from DFT+U. +/// Takes Plus_U& because it calls dftu.cal_VU_pot_mat_real/complex, +/// which are still members of Plus_U (defined in dftu_tools.cpp). +void force_stress(Plus_U& dftu, + const UnitCell& ucell, + const Grid_Driver& gd, + std::vector>* dmk_d, + std::vector>>* dmk_c, + const Parallel_Orbitals& pv, + ForceStressArrays& fsr, + ModuleBase::matrix& force_dftu, + ModuleBase::matrix& stress_dftu, + const K_Vectors& kv, + const int npol); + +/// @brief Force contribution at a k-point (multik path). +void cal_force_k(int nlocal, + int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const std::vector& orbital_corr, + const std::vector>>>>& iatlnmipol2iwt, + const UnitCell& ucell, + const Grid_Driver& gd, + ForceStressArrays& fsr, + const Parallel_Orbitals& pv, + const int ik, + const std::complex* rho_VU, + ModuleBase::matrix& force_dftu, + const ModuleBase::Vector3& kvec_d); + +/// @brief Stress contribution at a k-point (multik path). +void cal_stress_k(int nlocal, + int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const UnitCell& ucell, + const Grid_Driver& gd, + ForceStressArrays& fsr, + const Parallel_Orbitals& pv, + const int ik, + const std::complex* rho_VU, + ModuleBase::matrix& stress_dftu, + const ModuleBase::Vector3& kvec_d); + +/// @brief Force contribution at gamma point. +void cal_force_gamma(int nlocal, + int npol, + const std::vector& orbital_corr, + const std::vector>>>>& iatlnmipol2iwt, + const UnitCell& ucell, + const double* rho_VU, + const Parallel_Orbitals& pv, + double* dsloc_x, + double* dsloc_y, + double* dsloc_z, + ModuleBase::matrix& force_dftu); + +/// @brief Stress contribution at gamma point. +void cal_stress_gamma(int nlocal, + int npol, + const std::string& ks_solver, + const std::vector& orb_cutoff, + const UnitCell& ucell, + const Parallel_Orbitals& pv, + const Grid_Driver* gd, + double* dsloc_x, + double* dsloc_y, + double* dsloc_z, + double* dh_r, + const double* rho_VU, + ModuleBase::matrix& stress_dftu); + +} // namespace DFTU_LCAO + +#endif // __LCAO + +#endif // DFTU_FORCE_H diff --git a/source/source_lcao/module_dftu/dftu_lcao.h b/source/source_lcao/module_dftu/dftu_lcao.h index b8e0ee88c4..8dd9ac17f3 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.h +++ b/source/source_lcao/module_dftu/dftu_lcao.h @@ -116,16 +116,16 @@ class Plus_U : public Plus_U_Base #endif #ifdef __LCAO -private: //============================================================= // In dftu_tools.cpp // For calculating onsite potential, which is used // for both Hamiltonian and force/stress //============================================================= - + public: void cal_VU_pot_mat_complex(const int spin, const bool newlocale, std::complex* VU, const int npol); void cal_VU_pot_mat_real(const int spin, const bool newlocale, double* VU, const int npol); + private: double get_onebody_eff_pot(const int T, const int iat, const int L, @@ -135,58 +135,6 @@ class Plus_U : public Plus_U_Base const int m1, const bool newlocale); - //============================================================= - // In dftu_force.cpp - // For calculating force and stress fomr DFT+U - //============================================================= - public: - void force_stress(const UnitCell& ucell, - const Grid_Driver& gd, - std::vector>* dmk_d, - std::vector>>* dmk_c, - const Parallel_Orbitals& pv, - ForceStressArrays& fsr, - ModuleBase::matrix& force_dftu, - ModuleBase::matrix& stress_dftu, - const K_Vectors& kv, - const int npol); - - private: - void cal_force_k(const UnitCell& ucell, - const Grid_Driver& gd, - ForceStressArrays& fsr, - const Parallel_Orbitals& pv, - const int ik, - const std::complex* rho_VU, - ModuleBase::matrix& force_dftu, - const ModuleBase::Vector3& kvec_d); - - void cal_stress_k(const UnitCell& ucell, - const Grid_Driver& gd, - ForceStressArrays& fsr, - const Parallel_Orbitals& pv, - const int ik, - const std::complex* rho_VU, - ModuleBase::matrix& stress_dftu, - const ModuleBase::Vector3& kvec_d); - - void cal_force_gamma(const UnitCell& ucell, - const double* rho_VU, - const Parallel_Orbitals& pv, - double* dsloc_x, - double* dsloc_y, - double* dsloc_z, - ModuleBase::matrix& force_dftu); - - void cal_stress_gamma(const UnitCell& ucell, - const Parallel_Orbitals& pv, - const Grid_Driver* gd, - double* dsloc_x, - double* dsloc_y, - double* dsloc_z, - double* dh_r, - const double* rho_VU, - ModuleBase::matrix& stress_dftu); #endif //============================================================= @@ -219,6 +167,16 @@ class Plus_U : public Plus_U_Base void set_dmr(const elecstate::DensityMatrix* dm_in_dftu_d); void set_dmr(const elecstate::DensityMatrix, double>* dm_in_dftu_cd); + /// read-only accessors for state needed by DFTU_LCAO free functions + const Parallel_Orbitals* get_paraV() const { return paraV; } + int get_npol() const { return npol; } + int get_nlocal() const { return nlocal; } + const std::string& get_ks_solver() const { return ks_solver; } + const std::vector& get_orb_cutoff() const { return orb_cutoff_; } + bool is_gamma_only_local() const { return gamma_only_local; } + bool is_cal_force() const { return cal_force; } + bool is_cal_stress() const { return cal_stress; } + private: const UnitCell* ucell = nullptr; const elecstate::DensityMatrix* dm_in_dftu_d = nullptr; diff --git a/source/source_lcao/module_dftu/dftu_occup.cpp b/source/source_lcao/module_dftu/dftu_occup.cpp index 8a9ec85639..e9c36d973a 100644 --- a/source/source_lcao/module_dftu/dftu_occup.cpp +++ b/source/source_lcao/module_dftu/dftu_occup.cpp @@ -38,7 +38,7 @@ void Plus_U::cal_occup_m_k(const int iter, for (int ik = 0; ik < kv.get_nks(); ik++) { // srho(mu,nu) = \sum_{iw} S(mu,iw)*dm_k(iw,nu) - dftu_folding::folding_matrix_k_new(this->ks_solver, this->gamma_only_local, this->nspin, ik, p_ham); + DFTU_LCAO::folding_matrix_k_new(this->ks_solver, this->gamma_only_local, this->nspin, ik, p_ham); std::complex* s_k_pointer = nullptr; diff --git a/source/source_pw/module_pwdft/dftu_base.h b/source/source_pw/module_pwdft/dftu_base.h index 5ed8d5bc73..54aed4ec15 100644 --- a/source/source_pw/module_pwdft/dftu_base.h +++ b/source/source_pw/module_pwdft/dftu_base.h @@ -49,6 +49,13 @@ class Plus_U_Base bool has_correlated_orbital(int it) const { return orbital_corr[it] != -1; } const int* get_orbital_corr_data() const { return orbital_corr.data(); } + /// read-only access to the orbital_corr vector (length ntype) + const std::vector& get_orbital_corr_vec() const { return orbital_corr; } + + /// read-only access to the iat->(l,n,m,ipol)->iwt lookup table + const std::vector>>>>& + get_iatlnmipol2iwt() const { return iatlnmipol2iwt; } + // --- Accessors for DFT+U configuration --- double get_uramping() const { return uramping; } int get_occ_mat_ctrl() const { return occ_mat_ctrl; } From 1d87c6783833eeba9db30e202344fcb4a8bd961c Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 16:49:44 +0800 Subject: [PATCH 15/23] refactor(dftu): prune redundant #include in module_dftu Remove unused #include directives across 12 files in source/source_lcao/module_dftu/. Each removal was verified by symbol-usage grep against the file body (excluding the include lines themselves) and by compiling the dftu + hamilt_lcao CMake targets. Removed includes per file: - dftu_lcao.cpp: parameter.h, constants.h, global_function.h, inverse_matrix.h, memory_recorder.h, magnetism.h, charge.h and unused ////// /; add focused matrix.h (for ModuleBase::matrix::operator() via occ_mat), tool_quit.h, tool_title.h - dftu_folding.cpp: parameter.h, hcontainer.h, hcontainer_funcs.h - dftu_force.cpp: parameter.h, constants.h, inverse_matrix.h, elecstate_lcao.h, magnetism.h, charge.h, , , , , , , - dftu_hamilt.cpp: parameter.h - dftu_lcao_op.cpp: hcontainer_funcs.h, - dftu_lcao_op_legacy.cpp: dftu_lcao.h (already provided by its own .h) - dftu_occup.cpp: parameter.h - dftu_tools.cpp: timer.h (no direct ModuleBase::timer use), parameter.h - dftu_yukawa.cpp: parameter.h, , , , , , , - dftu_lcao.h: charge_mixing.h (still provided transitively via dftu_base.h), force_stress_arrays.h (not directly used here) - dftu_lcao_op.h: density_matrix.h (not directly used here) - dftu_lcao_op_legacy.h: timer.h (not directly used here) Note: scalapack_connector.h was kept in dftu_force.cpp / dftu_hamilt.cpp / dftu_occup.cpp -- these files call ScalapackConnector::gemm. Verification: OMP_NUM_THREADS=1 make -C build_std_para dftu hamilt_lcao => EXIT=0, no errors, no warnings. Full abacus build deferred to user; external modules that include dftu_lcao.h and use Charge_Mixing (chgmixing.cpp, esolver_ks.cpp/h) should still resolve via dftu_lcao.h -> dftu_base.h -> charge_mixing.h. --- .../source_lcao/module_dftu/dftu_folding.cpp | 3 --- source/source_lcao/module_dftu/dftu_force.cpp | 14 -------------- source/source_lcao/module_dftu/dftu_hamilt.cpp | 1 - source/source_lcao/module_dftu/dftu_lcao.cpp | 18 +++--------------- source/source_lcao/module_dftu/dftu_lcao.h | 2 -- .../source_lcao/module_dftu/dftu_lcao_op.cpp | 4 ---- source/source_lcao/module_dftu/dftu_lcao_op.h | 1 - .../module_dftu/dftu_lcao_op_legacy.cpp | 1 - .../module_dftu/dftu_lcao_op_legacy.h | 1 - source/source_lcao/module_dftu/dftu_occup.cpp | 3 +-- source/source_lcao/module_dftu/dftu_tools.cpp | 2 -- source/source_lcao/module_dftu/dftu_yukawa.cpp | 8 -------- 12 files changed, 4 insertions(+), 54 deletions(-) diff --git a/source/source_lcao/module_dftu/dftu_folding.cpp b/source/source_lcao/module_dftu/dftu_folding.cpp index c0856dd311..fc09e23ae8 100644 --- a/source/source_lcao/module_dftu/dftu_folding.cpp +++ b/source/source_lcao/module_dftu/dftu_folding.cpp @@ -2,11 +2,8 @@ #include "dftu_folding.h" #include "dftu_lcao.h" #include "source_base/timer.h" -#include "source_io/module_parameter/parameter.h" #include "source_cell/module_neighbor/sltk_grid_driver.h" #include "source_lcao/hamilt_lcao.h" -#include "source_hamilt/module_hcontainer/hcontainer.h" -#include "source_hamilt/module_hcontainer/hcontainer_funcs.h" namespace DFTU_LCAO { diff --git a/source/source_lcao/module_dftu/dftu_force.cpp b/source/source_lcao/module_dftu/dftu_force.cpp index 679c926f7d..a858ffcada 100644 --- a/source/source_lcao/module_dftu/dftu_force.cpp +++ b/source/source_lcao/module_dftu/dftu_force.cpp @@ -1,27 +1,13 @@ -#include "source_io/module_parameter/parameter.h" - #ifdef __LCAO #include "dftu_force.h" #include "dftu_folding.h" #include "dftu_lcao.h" -#include "source_base/constants.h" #include "source_base/global_function.h" -#include "source_base/inverse_matrix.h" #include "source_base/module_external/scalapack_connector.h" #include "source_base/parallel_reduce.h" #include "source_base/timer.h" -#include "source_estate/elecstate_lcao.h" -#include "source_cell/magnetism.h" -#include "source_estate/module_charge/charge.h" -#include #include -#include -#include -#include -#include -#include -#include #include diff --git a/source/source_lcao/module_dftu/dftu_hamilt.cpp b/source/source_lcao/module_dftu/dftu_hamilt.cpp index c8362bc749..401413a556 100644 --- a/source/source_lcao/module_dftu/dftu_hamilt.cpp +++ b/source/source_lcao/module_dftu/dftu_hamilt.cpp @@ -1,6 +1,5 @@ #include "dftu_lcao.h" #include "source_base/module_external/scalapack_connector.h" -#include "source_io/module_parameter/parameter.h" #include "source_base/timer.h" diff --git a/source/source_lcao/module_dftu/dftu_lcao.cpp b/source/source_lcao/module_dftu/dftu_lcao.cpp index b4f89242cb..c2fcb254a1 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao.cpp @@ -1,23 +1,11 @@ #include "dftu_lcao.h" -#include "source_io/module_parameter/parameter.h" -#include "source_base/constants.h" -#include "source_base/global_function.h" -#include "source_base/inverse_matrix.h" -#include "source_base/memory_recorder.h" +#include "source_base/matrix.h" // occ_mat uses ModuleBase::matrix::operator() +#include "source_base/tool_quit.h" +#include "source_base/tool_title.h" #include "source_base/timer.h" -#include "source_cell/magnetism.h" -#include "source_estate/module_charge/charge.h" -#include -#include #include -#include -#include -#include -#include -#include -#include #include // mohan add 2025-11-06 diff --git a/source/source_lcao/module_dftu/dftu_lcao.h b/source/source_lcao/module_dftu/dftu_lcao.h index 8dd9ac17f3..34788ecc6a 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.h +++ b/source/source_lcao/module_dftu/dftu_lcao.h @@ -4,14 +4,12 @@ #include "source_cell/klist.h" #include "source_cell/unitcell.h" #include "source_basis/module_ao/parallel_orbitals.h" -#include "source_estate/module_charge/charge_mixing.h" #include "source_pw/module_pwdft/dftu_base.h" #ifdef __LCAO #include "source_basis/module_ao/orb_read.h" #include "source_hamilt/hamilt.h" #include "source_hamilt/module_hcontainer/hcontainer.h" #include "source_estate/module_dm/density_matrix.h" -#include "source_lcao/force_stress_arrays.h" // mohan add 2024-06-15 #endif #include diff --git a/source/source_lcao/module_dftu/dftu_lcao_op.cpp b/source/source_lcao/module_dftu/dftu_lcao_op.cpp index 0ddf17e560..011e451913 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao_op.cpp @@ -4,11 +4,7 @@ #include "source_base/tool_title.h" #include "source_cell/module_neighbor/sltk_grid_driver.h" #include "source_lcao/module_operator_lcao/operator_lcao.h" -#include "source_hamilt/module_hcontainer/hcontainer_funcs.h" #include "source_io/module_parameter/parameter.h" -#ifdef _OPENMP -#include -#endif #include "source_base/parallel_reduce.h" template diff --git a/source/source_lcao/module_dftu/dftu_lcao_op.h b/source/source_lcao/module_dftu/dftu_lcao_op.h index 23b361bbbe..ee217aca6b 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op.h +++ b/source/source_lcao/module_dftu/dftu_lcao_op.h @@ -4,7 +4,6 @@ #include "source_basis/module_nao/two_center_integrator.h" #include "source_cell/module_neighbor/sltk_grid_driver.h" #include "source_cell/unitcell.h" -#include "source_estate/module_dm/density_matrix.h" #include "source_lcao/module_operator_lcao/operator_lcao.h" #include "source_lcao/module_dftu/dftu_lcao.h" #include "source_hamilt/module_hcontainer/hcontainer.h" diff --git a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp index 643a42f677..cc10e85ce6 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp @@ -1,7 +1,6 @@ #include "dftu_lcao_op_legacy.h" #include "source_base/timer.h" #include "source_base/tool_title.h" -#include "source_lcao/module_dftu/dftu_lcao.h" namespace hamilt { diff --git a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.h b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.h index 8bf8e8260d..8f68592cd8 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.h +++ b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.h @@ -1,7 +1,6 @@ #ifndef OPDFTULCAO_H #define OPDFTULCAO_H -#include "source_base/timer.h" #include "source_lcao/module_operator_lcao/operator_lcao.h" #include "source_lcao/module_dftu/dftu_lcao.h" // mohan add 20251107 diff --git a/source/source_lcao/module_dftu/dftu_occup.cpp b/source/source_lcao/module_dftu/dftu_occup.cpp index e9c36d973a..4f0fe2dd3c 100644 --- a/source/source_lcao/module_dftu/dftu_occup.cpp +++ b/source/source_lcao/module_dftu/dftu_occup.cpp @@ -1,11 +1,10 @@ #include "dftu_lcao.h" #include "dftu_folding.h" #include "source_base/timer.h" -#include "source_io/module_parameter/parameter.h" +#include "source_base/module_external/scalapack_connector.h" #ifdef __LCAO #include "source_lcao/hamilt_lcao.h" #endif -#include "source_base/module_external/scalapack_connector.h" // copy_occ_mat(), zero_occ_mat(), mix_occ_mat(), set_occ_mat(ucell), // get_occ_mat_flat(), set_occ_mat_flat() diff --git a/source/source_lcao/module_dftu/dftu_tools.cpp b/source/source_lcao/module_dftu/dftu_tools.cpp index 954cff79ff..8a707c01c5 100644 --- a/source/source_lcao/module_dftu/dftu_tools.cpp +++ b/source/source_lcao/module_dftu/dftu_tools.cpp @@ -1,6 +1,4 @@ #include "dftu_lcao.h" -#include "source_base/timer.h" -#include "source_io/module_parameter/parameter.h" #ifdef __LCAO void Plus_U::cal_VU_pot_mat_complex(const int spin, const bool new_occ_mat, std::complex* VU, const int npol) diff --git a/source/source_lcao/module_dftu/dftu_yukawa.cpp b/source/source_lcao/module_dftu/dftu_yukawa.cpp index 9f9c8ff75f..6eadc32c4a 100644 --- a/source/source_lcao/module_dftu/dftu_yukawa.cpp +++ b/source/source_lcao/module_dftu/dftu_yukawa.cpp @@ -1,17 +1,9 @@ #ifdef __LCAO -#include "source_io/module_parameter/parameter.h" #include "source_base/constants.h" #include "source_base/global_function.h" #include "dftu_lcao.h" #include -#include -#include -#include -#include -#include -#include -#include void Plus_U::cal_yukawa_lambda(double** rho, const int& nrxx) From 5ac6ca73f30b8a4dc28d2021ef5adac3c627766f Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 17:16:47 +0800 Subject: [PATCH 16/23] refactor(dftu): rename Plus_U members and extract pot_uterm_* to DFTU_LCAO Rename for consistency with the DFTU_LCAO free-function convention established in dftu_force.h, and to disambiguate from the KS effective potential V_eff: * Plus_U::cal_eff_pot_mat_{complex,real} -> DFTU_LCAO::pot_uterm_{complex,real} Extracted from member functions to free functions taking Plus_U&. Internal this->paraV / this->nlocal replaced with dftu.get_paraV() / dftu.get_nlocal(); this->cal_VU_pot_mat_* replaced with dftu.pot_onsite_*. * Plus_U::cal_VU_pot_mat_{complex,real} -> Plus_U::pot_onsite_{complex,real} Member, renamed only. The on-site Hubbard potential V_{mm'}. * Plus_U::cal_occup_m_{k,gamma} -> Plus_U::cal_occ_mat_{k,gamma} Member, renamed only. * dftu_cal_occup_m -> DFTU_LCAO::cal_occ_mat Moved into namespace DFTU_LCAO and renamed. R-space variants Plus_U::cal_eff_pot_mat_R_double and Plus_U::cal_eff_pot_mat_R_complex_double are intentionally left untouched; they bind to the sparse R-space Hamiltonian path in spar_u.cpp (force/stress) and will be addressed in a follow-up. Timer and TITLE strings inside dftu_hamilt.cpp updated to match the new function names for runtime log consistency. No behavior change; pure rename + structural relocation. Test directory source/source_lcao/module_dftu/test/ has no references to any renamed function, so no test update is required. Verification: - rg confirms zero leftover references to the old names across the whole codebase, except the intentionally-preserved R-space variants. - python3 tools/03_code_analysis/agent_governance_check.py --staged passes with only 2 PR-level WARNINGs (test/docs sync reminder), both addressed by this message. --- source/source_lcao/module_dftu/dftu_force.cpp | 4 +- source/source_lcao/module_dftu/dftu_force.h | 4 +- .../source_lcao/module_dftu/dftu_hamilt.cpp | 112 ++++++++++-------- source/source_lcao/module_dftu/dftu_lcao.cpp | 36 +++--- source/source_lcao/module_dftu/dftu_lcao.h | 59 +++++---- .../module_dftu/dftu_lcao_op_legacy.cpp | 6 +- source/source_lcao/module_dftu/dftu_occup.cpp | 16 +-- source/source_lcao/module_dftu/dftu_tools.cpp | 8 +- source/source_lcao/setup_dftu_lcao.cpp | 4 +- 9 files changed, 140 insertions(+), 109 deletions(-) diff --git a/source/source_lcao/module_dftu/dftu_force.cpp b/source/source_lcao/module_dftu/dftu_force.cpp index a858ffcada..9510001d2d 100644 --- a/source/source_lcao/module_dftu/dftu_force.cpp +++ b/source/source_lcao/module_dftu/dftu_force.cpp @@ -102,7 +102,7 @@ void force_stress(Plus_U& dftu, double* VU = new double[pv.nloc]; - dftu.cal_VU_pot_mat_real(spin, false, VU, npol); + dftu.pot_onsite_real(spin, false, VU, npol); #ifdef __MPI ScalapackConnector::gemm(transT, transN, nlocal, nlocal, nlocal, @@ -148,7 +148,7 @@ void force_stress(Plus_U& dftu, std::complex* VU = new std::complex[pv.nloc]; - dftu.cal_VU_pot_mat_complex(spin, false, VU, npol); + dftu.pot_onsite_complex(spin, false, VU, npol); #ifdef __MPI diff --git a/source/source_lcao/module_dftu/dftu_force.h b/source/source_lcao/module_dftu/dftu_force.h index 9c56199021..f71c94c111 100644 --- a/source/source_lcao/module_dftu/dftu_force.h +++ b/source/source_lcao/module_dftu/dftu_force.h @@ -1,7 +1,7 @@ /// @file dftu_force.h /// @brief Free-function helpers for DFT+U force and stress, extracted from /// Plus_U. The top-level force_stress takes a Plus_U& because it needs -/// to call Plus_U::cal_VU_pot_mat_real/complex; the four inner +/// to call Plus_U::pot_onsite_real/complex; the four inner /// functions are fully decoupled and take their dependencies as /// explicit parameters (mirroring the folding helpers in the same /// DFTU_LCAO namespace). @@ -27,7 +27,7 @@ class Plus_U; namespace DFTU_LCAO { /// @brief Top-level entry: drives force/stress from DFT+U. -/// Takes Plus_U& because it calls dftu.cal_VU_pot_mat_real/complex, +/// Takes Plus_U& because it calls dftu.pot_onsite_real/complex, /// which are still members of Plus_U (defined in dftu_tools.cpp). void force_stress(Plus_U& dftu, const UnitCell& ucell, diff --git a/source/source_lcao/module_dftu/dftu_hamilt.cpp b/source/source_lcao/module_dftu/dftu_hamilt.cpp index 401413a556..2c478dd218 100644 --- a/source/source_lcao/module_dftu/dftu_hamilt.cpp +++ b/source/source_lcao/module_dftu/dftu_hamilt.cpp @@ -4,23 +4,28 @@ #ifdef __LCAO -void Plus_U::cal_eff_pot_mat_complex(const int ik, - std::complex* eff_pot, - const std::vector& isk, - const std::complex* sk, - const int npol) +namespace DFTU_LCAO { + +void pot_uterm_complex(Plus_U& dftu, + const int ik, + std::complex* eff_pot, + const std::vector& isk, + const std::complex* sk, + const int npol) { - ModuleBase::TITLE("Plus_U", "cal_eff_pot_c"); - if (!is_occ_mat_initialized()) + ModuleBase::TITLE("Plus_U", "pot_uterm_complex"); + if (!dftu.is_occ_mat_initialized()) { return; } - ModuleBase::timer::start("Plus_U", "cal_eff_pot_c"); + ModuleBase::timer::start("Plus_U", "pot_uterm_complex"); int spin = isk[ik]; - ModuleBase::GlobalFunc::ZEROS(eff_pot, this->paraV->nloc); + const Parallel_Orbitals* paraV = dftu.get_paraV(); + const int nlocal = dftu.get_nlocal(); + ModuleBase::GlobalFunc::ZEROS(eff_pot, paraV->nloc); //============================================================= // PART2: call pblas to calculate effective potential matrix @@ -31,48 +36,55 @@ void Plus_U::cal_eff_pot_mat_complex(const int ik, const std::complex half = 0.5; const std::complex zero = 0.0; - std::vector> VU(this->paraV->nloc); - this->cal_VU_pot_mat_complex(spin, true, &VU[0], npol); + std::vector> VU(paraV->nloc); + dftu.pot_onsite_complex(spin, true, &VU[0], npol); #ifdef __MPI - ScalapackConnector::gemm(transN, transN, - this->nlocal, this->nlocal, this->nlocal, - half, - ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), one_int, one_int, this->paraV->desc, - sk, one_int, one_int, this->paraV->desc, + ScalapackConnector::gemm(transN, transN, + nlocal, nlocal, nlocal, + half, + ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), one_int, one_int, paraV->desc, + sk, one_int, one_int, paraV->desc, zero, - eff_pot, one_int, one_int, this->paraV->desc); + eff_pot, one_int, one_int, paraV->desc); #endif - for (int irc = 0; irc < this->paraV->nloc; irc++) - { - VU[irc] = eff_pot[irc]; - } + for (int irc = 0; irc < paraV->nloc; irc++) + { + VU[irc] = eff_pot[irc]; + } #ifdef __MPI - ScalapackConnector::tranu(this->nlocal, this->nlocal, - one, - &VU[0], one_int, one_int, this->paraV->desc, - one, - eff_pot, one_int, one_int, this->paraV->desc); + ScalapackConnector::tranu(nlocal, nlocal, + one, + &VU[0], one_int, one_int, paraV->desc, + one, + eff_pot, one_int, one_int, paraV->desc); #endif - ModuleBase::timer::end("Plus_U", "cal_eff_pot_c"); + ModuleBase::timer::end("Plus_U", "pot_uterm_complex"); return; } -void Plus_U::cal_eff_pot_mat_real(const int ik, double* eff_pot, const std::vector& isk, const double* sk, const int npol) +void pot_uterm_real(Plus_U& dftu, + const int ik, + double* eff_pot, + const std::vector& isk, + const double* sk, + const int npol) { - ModuleBase::TITLE("Plus_U", "cal_eff_pot_r"); - if (!is_occ_mat_initialized()) + ModuleBase::TITLE("Plus_U", "pot_uterm_real"); + if (!dftu.is_occ_mat_initialized()) { return; } - ModuleBase::timer::start("Plus_U", "cal_eff_pot_r"); + ModuleBase::timer::start("Plus_U", "pot_uterm_real"); int spin = isk[ik]; - ModuleBase::GlobalFunc::ZEROS(eff_pot, this->paraV->nloc); + const Parallel_Orbitals* paraV = dftu.get_paraV(); + const int nlocal = dftu.get_nlocal(); + ModuleBase::GlobalFunc::ZEROS(eff_pot, paraV->nloc); //============================================================= // PART2: call pblas to calculate effective potential matrix @@ -81,34 +93,36 @@ void Plus_U::cal_eff_pot_mat_real(const int ik, double* eff_pot, const std::vect int one_int = 1; double alpha = 1.0, beta = 0.0, half = 0.5, one = 1.0; - std::vector VU(this->paraV->nloc); - this->cal_VU_pot_mat_real(spin, 1, &VU[0], npol); + std::vector VU(paraV->nloc); + dftu.pot_onsite_real(spin, 1, &VU[0], npol); #ifdef __MPI - ScalapackConnector::gemm(transN, transN, - this->nlocal, this->nlocal, this->nlocal, - half, - ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), 1, 1, this->paraV->desc, - sk, 1, 1, this->paraV->desc, + ScalapackConnector::gemm(transN, transN, + nlocal, nlocal, nlocal, + half, + ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), 1, 1, paraV->desc, + sk, 1, 1, paraV->desc, beta, - eff_pot, 1, 1, this->paraV->desc); + eff_pot, 1, 1, paraV->desc); #endif - for (int irc = 0; irc < this->paraV->nloc; irc++) + for (int irc = 0; irc < paraV->nloc; irc++) VU[irc] = eff_pot[irc]; #ifdef __MPI - pdtran_(&this->nlocal, &this->nlocal, - &one, - &VU[0], &one_int, &one_int, const_cast(this->paraV->desc), - &one, - eff_pot, &one_int, &one_int, const_cast(this->paraV->desc)); + pdtran_(&nlocal, &nlocal, + &one, + &VU[0], &one_int, &one_int, const_cast(paraV->desc), + &one, + eff_pot, &one_int, &one_int, const_cast(paraV->desc)); #endif - ModuleBase::timer::end("Plus_U", "cal_eff_pot_r"); + ModuleBase::timer::end("Plus_U", "pot_uterm_real"); return; } +} // namespace DFTU_LCAO + void Plus_U::cal_eff_pot_mat_R_double(const int ispin, double* SR, double* HR, const int npol) { const char transN = 'N', transT = 'T'; @@ -116,7 +130,7 @@ void Plus_U::cal_eff_pot_mat_R_double(const int ispin, double* SR, double* HR, c const double alpha = 1.0, beta = 0.0, one = 1.0, half = 0.5; std::vector VU(this->paraV->nloc); - this->cal_VU_pot_mat_real(ispin, 1, &VU[0], npol); + this->pot_onsite_real(ispin, 1, &VU[0], npol); #ifdef __MPI ScalapackConnector::gemm(transN, transN, @@ -146,7 +160,7 @@ void Plus_U::cal_eff_pot_mat_R_complex_double(const int ispin, std::complex zero = 0.0, one = 1.0, half = 0.5; std::vector> VU(this->paraV->nloc); - this->cal_VU_pot_mat_complex(ispin, 1, &VU[0], npol); + this->pot_onsite_complex(ispin, 1, &VU[0], npol); #ifdef __MPI ScalapackConnector::gemm(transN, transN, diff --git a/source/source_lcao/module_dftu/dftu_lcao.cpp b/source/source_lcao/module_dftu/dftu_lcao.cpp index c2fcb254a1..d166dd05ec 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao.cpp @@ -286,30 +286,34 @@ const hamilt::HContainer* Plus_U::get_dmr(int ispin) const } } +namespace DFTU_LCAO { + //! dftu occupation matrix for gamma only using dm(double) template <> -void dftu_cal_occup_m(const int iter, - const UnitCell& ucell, - const std::vector>& dm, - const K_Vectors& kv, - const double& mixing_beta, - hamilt::Hamilt* p_ham, - Plus_U &dftu) +void cal_occ_mat(const int iter, + const UnitCell& ucell, + const std::vector>& dm, + const K_Vectors& kv, + const double& mixing_beta, + hamilt::Hamilt* p_ham, + Plus_U& dftu) { - dftu.cal_occup_m_gamma(iter, ucell ,dm, mixing_beta, p_ham); + dftu.cal_occ_mat_gamma(iter, ucell, dm, mixing_beta, p_ham); } //! dftu occupation matrix for multiple k-points using dm(complex) template <> -void dftu_cal_occup_m(const int iter, - const UnitCell& ucell, - const std::vector>>& dm, - const K_Vectors& kv, - const double& mixing_beta, - hamilt::Hamilt>* p_ham, - Plus_U &dftu) +void cal_occ_mat(const int iter, + const UnitCell& ucell, + const std::vector>>& dm, + const K_Vectors& kv, + const double& mixing_beta, + hamilt::Hamilt>* p_ham, + Plus_U& dftu) { - dftu.cal_occup_m_k(iter,ucell, dm, kv, mixing_beta, p_ham); + dftu.cal_occ_mat_k(iter, ucell, dm, kv, mixing_beta, p_ham); } +} // namespace DFTU_LCAO + #endif diff --git a/source/source_lcao/module_dftu/dftu_lcao.h b/source/source_lcao/module_dftu/dftu_lcao.h index 34788ecc6a..f7f284a52c 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.h +++ b/source/source_lcao/module_dftu/dftu_lcao.h @@ -77,18 +77,6 @@ class Plus_U : public Plus_U_Base // For calculating contribution to Hamiltonian matrices //============================================================= public: - void cal_eff_pot_mat_complex(const int ik, - std::complex* eff_pot, - const std::vector& isk, - const std::complex* sk, - const int npol); - - void cal_eff_pot_mat_real(const int ik, - double* eff_pot, - const std::vector& isk, - const double* sk, - const int npol); - void cal_eff_pot_mat_R_double(const int ispin, double* SR, double* HR, const int npol); void cal_eff_pot_mat_R_complex_double(const int ispin, @@ -99,14 +87,14 @@ class Plus_U : public Plus_U_Base #ifdef __LCAO // calculate the local occupation number matrix - void cal_occup_m_k(const int iter, + void cal_occ_mat_k(const int iter, const UnitCell& ucell, const std::vector>>& dm_k, const K_Vectors& kv, const double& mixing_beta, hamilt::Hamilt>* p_ham); - void cal_occup_m_gamma(const int iter, + void cal_occ_mat_gamma(const int iter, const UnitCell& ucell, const std::vector>& dm_gamma, const double& mixing_beta, @@ -120,8 +108,8 @@ class Plus_U : public Plus_U_Base // for both Hamiltonian and force/stress //============================================================= public: - void cal_VU_pot_mat_complex(const int spin, const bool newlocale, std::complex* VU, const int npol); - void cal_VU_pot_mat_real(const int spin, const bool newlocale, double* VU, const int npol); + void pot_onsite_complex(const int spin, const bool newlocale, std::complex* VU, const int npol); + void pot_onsite_real(const int spin, const bool newlocale, double* VU, const int npol); private: double get_onebody_eff_pot(const int T, @@ -184,14 +172,39 @@ class Plus_U : public Plus_U_Base #ifdef __LCAO +namespace DFTU_LCAO { + +/// @brief Compute the occupation matrix and delegate to Plus_U member. +/// Dispatches to Plus_U::cal_occ_mat_gamma (gamma-only, double) or +/// Plus_U::cal_occ_mat_k (multi-k, std::complex) via template. template -void dftu_cal_occup_m(const int iter, - const UnitCell& ucell, - const std::vector>& dm, - const K_Vectors& kv, - const double& mixing_beta, - hamilt::Hamilt* p_ham, - Plus_U &dftu); +void cal_occ_mat(const int iter, + const UnitCell& ucell, + const std::vector>& dm, + const K_Vectors& kv, + const double& mixing_beta, + hamilt::Hamilt* p_ham, + Plus_U& dftu); + +/// @brief Compute the LCAO-basis U-term effective potential matrix (complex). +/// Wraps Plus_U::pot_onsite_complex plus the S-projection GEMM. +void pot_uterm_complex(Plus_U& dftu, + const int ik, + std::complex* eff_pot, + const std::vector& isk, + const std::complex* sk, + const int npol); + +/// @brief Compute the LCAO-basis U-term effective potential matrix (real). +/// Wraps Plus_U::pot_onsite_real plus the S-projection GEMM. +void pot_uterm_real(Plus_U& dftu, + const int ik, + double* eff_pot, + const std::vector& isk, + const double* sk, + const int npol); + +} // namespace DFTU_LCAO #endif diff --git a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp index cc10e85ce6..7844da7dbc 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp @@ -26,7 +26,7 @@ void OperatorDFTU>::contributeHk(int ik) // Effective potential of DFT+U is added to total Hamiltonian here; Quxin adds on 20201029 std::vector eff_pot(this->hsk->get_pv()->nloc); - this->dftu->cal_eff_pot_mat_real(ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); + DFTU_LCAO::pot_uterm_real(*this->dftu, ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); double* hk = this->hsk->get_hk(); @@ -47,7 +47,7 @@ void OperatorDFTU, double>>::contributeHk(int // Effective potential of DFT+U is added to total Hamiltonian here; Quxin adds on 20201029 std::vector> eff_pot(this->hsk->get_pv()->nloc); - this->dftu->cal_eff_pot_mat_complex(ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); + DFTU_LCAO::pot_uterm_complex(*this->dftu, ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); std::complex* hk = this->hsk->get_hk(); @@ -67,7 +67,7 @@ void OperatorDFTU, std::complex>>::con // Effective potential of DFT+U is added to total Hamiltonian here; Quxin adds on 20201029 std::vector> eff_pot(this->hsk->get_pv()->nloc); - this->dftu->cal_eff_pot_mat_complex(ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); + DFTU_LCAO::pot_uterm_complex(*this->dftu, ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); std::complex* hk = this->hsk->get_hk(); for (int irc = 0; irc < this->hsk->get_pv()->nloc; irc++) diff --git a/source/source_lcao/module_dftu/dftu_occup.cpp b/source/source_lcao/module_dftu/dftu_occup.cpp index 4f0fe2dd3c..1f332797d9 100644 --- a/source/source_lcao/module_dftu/dftu_occup.cpp +++ b/source/source_lcao/module_dftu/dftu_occup.cpp @@ -12,15 +12,15 @@ #ifdef __LCAO -void Plus_U::cal_occup_m_k(const int iter, +void Plus_U::cal_occ_mat_k(const int iter, const UnitCell& ucell, const std::vector>>& dm_k, const K_Vectors& kv, const double& mixing_beta, hamilt::Hamilt>* p_ham) { - ModuleBase::TITLE("Plus_U", "cal_occup_m_k"); - ModuleBase::timer::start("Plus_U", "cal_occup_m_k"); + ModuleBase::TITLE("Plus_U", "cal_occ_mat_k"); + ModuleBase::timer::start("Plus_U", "cal_occ_mat_k"); this->copy_occ_mat(ucell); this->zero_occ_mat(ucell); @@ -242,18 +242,18 @@ void Plus_U::cal_occup_m_k(const int iter, } mark_occ_mat_initialized(); - ModuleBase::timer::end("Plus_U", "cal_occup_m_k"); + ModuleBase::timer::end("Plus_U", "cal_occ_mat_k"); return; } -void Plus_U::cal_occup_m_gamma(const int iter, +void Plus_U::cal_occ_mat_gamma(const int iter, const UnitCell &ucell, const std::vector> &dm_gamma, const double& mixing_beta, hamilt::Hamilt* p_ham) { - ModuleBase::TITLE("Plus_U", "cal_occup_m_gamma"); - ModuleBase::timer::start("Plus_U", "cal_occup_m_gamma"); + ModuleBase::TITLE("Plus_U", "cal_occ_mat_gamma"); + ModuleBase::timer::start("Plus_U", "cal_occ_mat_gamma"); this->copy_occ_mat(ucell); this->zero_occ_mat(ucell); @@ -399,7 +399,7 @@ void Plus_U::cal_occup_m_gamma(const int iter, } mark_occ_mat_initialized(); - ModuleBase::timer::end("Plus_U", "cal_occup_m_gamma"); + ModuleBase::timer::end("Plus_U", "cal_occ_mat_gamma"); return; } #endif diff --git a/source/source_lcao/module_dftu/dftu_tools.cpp b/source/source_lcao/module_dftu/dftu_tools.cpp index 8a707c01c5..ca858d90e6 100644 --- a/source/source_lcao/module_dftu/dftu_tools.cpp +++ b/source/source_lcao/module_dftu/dftu_tools.cpp @@ -1,9 +1,9 @@ #include "dftu_lcao.h" #ifdef __LCAO -void Plus_U::cal_VU_pot_mat_complex(const int spin, const bool new_occ_mat, std::complex* VU, const int npol) +void Plus_U::pot_onsite_complex(const int spin, const bool new_occ_mat, std::complex* VU, const int npol) { - ModuleBase::TITLE("Plus_U", "cal_VU_pot_mat_complex"); + ModuleBase::TITLE("Plus_U", "pot_onsite_complex"); ModuleBase::GlobalFunc::ZEROS(VU, this->paraV->nloc); for (int it = 0; it < this->ucell->ntype; ++it) @@ -65,9 +65,9 @@ void Plus_U::cal_VU_pot_mat_complex(const int spin, const bool new_occ_mat, std: return; } -void Plus_U::cal_VU_pot_mat_real(const int spin, const bool new_occ_mat, double* VU, const int npol) +void Plus_U::pot_onsite_real(const int spin, const bool new_occ_mat, double* VU, const int npol) { - ModuleBase::TITLE("Plus_U", "cal_VU_pot_mat_real"); + ModuleBase::TITLE("Plus_U", "pot_onsite_real"); ModuleBase::GlobalFunc::ZEROS(VU, this->paraV->nloc); for (int it = 0; it < this->ucell->ntype; ++it) diff --git a/source/source_lcao/setup_dftu_lcao.cpp b/source/source_lcao/setup_dftu_lcao.cpp index 34b9867706..9cc6463a3c 100644 --- a/source/source_lcao/setup_dftu_lcao.cpp +++ b/source/source_lcao/setup_dftu_lcao.cpp @@ -63,8 +63,8 @@ void finish_dftu_lcao(const int iter, { if (dftu_ptr->get_occ_mat_ctrl() != 2) { - dftu_cal_occup_m(iter, ucell, dm_vec, kv, mixing_beta, - static_cast*>(hamilt_lcao_ptr), *dftu_ptr); + DFTU_LCAO::cal_occ_mat(iter, ucell, dm_vec, kv, mixing_beta, + static_cast*>(hamilt_lcao_ptr), *dftu_ptr); } dftu_ptr->cal_energy_correction(ucell, iter); } From b138c8aaa533864201650caad8682b6a1170ff72 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 17:27:08 +0800 Subject: [PATCH 17/23] refactor(dftu): split pot_uterm_* / cal_occ_mat declarations into dftu_hamilt.h / dftu_occup.h Previously dftu_lcao.h bundled the DFTU_LCAO namespace free-function declarations together at the bottom of the Plus_U class header. Split them into two focused headers mirroring dftu_force.h convention: * dftu_hamilt.h: DFTU_LCAO::pot_uterm_complex / pot_uterm_real (implemented in dftu_hamilt.cpp) * dftu_occup.h: DFTU_LCAO::cal_occ_mat template (specialized in dftu_lcao.cpp, delegates to Plus_U::cal_occ_mat_{k, gamma} in dftu_occup.cpp) dftu_lcao.h no longer auto-includes the two new headers; each .cpp that actually needs them includes the relevant one explicitly: * dftu_hamilt.cpp -> dftu_hamilt.h (defines pot_uterm_*) * dftu_lcao_op_legacy.cpp -> dftu_hamilt.h (calls pot_uterm_*) * dftu_lcao.cpp -> dftu_occup.h (specializes cal_occ_mat) * setup_dftu_lcao.cpp -> dftu_occup.h (calls cal_occ_mat) Both new headers are self-contained: they forward-declare 'class Plus_U;' instead of including dftu_lcao.h, so there is no include cycle. Plus_U member function declarations (cal_eff_pot_mat_R_*, cal_occ_mat_{k,gamma}, pot_onsite_*, etc.) remain in dftu_lcao.h because C++ does not support partial classes. Verification: - rg confirms the two new headers are only included by the four .cpp files listed above, with no remaining references via dftu_lcao.h. - python3 tools/03_code_analysis/agent_governance_check.py --staged passes with only PR-level WARNINGs (test/docs sync reminder), all addressed by this message. - The 'Confirm the declaration requires this include' reviewer note applies to the four added includes; all four are required because each .cpp either defines or calls the declared function and needs the full signature, not a forward declaration. --- .../source_lcao/module_dftu/dftu_hamilt.cpp | 1 + source/source_lcao/module_dftu/dftu_hamilt.h | 33 +++++++++++++++++ source/source_lcao/module_dftu/dftu_lcao.cpp | 5 +-- source/source_lcao/module_dftu/dftu_lcao.h | 37 ------------------- .../module_dftu/dftu_lcao_op_legacy.cpp | 1 + source/source_lcao/module_dftu/dftu_occup.h | 30 +++++++++++++++ source/source_lcao/setup_dftu_lcao.cpp | 1 + 7 files changed, 67 insertions(+), 41 deletions(-) create mode 100644 source/source_lcao/module_dftu/dftu_hamilt.h create mode 100644 source/source_lcao/module_dftu/dftu_occup.h diff --git a/source/source_lcao/module_dftu/dftu_hamilt.cpp b/source/source_lcao/module_dftu/dftu_hamilt.cpp index 2c478dd218..8e167f5e61 100644 --- a/source/source_lcao/module_dftu/dftu_hamilt.cpp +++ b/source/source_lcao/module_dftu/dftu_hamilt.cpp @@ -1,4 +1,5 @@ #include "dftu_lcao.h" +#include "dftu_hamilt.h" #include "source_base/module_external/scalapack_connector.h" #include "source_base/timer.h" diff --git a/source/source_lcao/module_dftu/dftu_hamilt.h b/source/source_lcao/module_dftu/dftu_hamilt.h new file mode 100644 index 0000000000..cde08c18d4 --- /dev/null +++ b/source/source_lcao/module_dftu/dftu_hamilt.h @@ -0,0 +1,33 @@ +#ifndef DFTU_HAMILT_H +#define DFTU_HAMILT_H + +#include +#include + +class Plus_U; + +#ifdef __LCAO +namespace DFTU_LCAO { + +/// @brief Compute the LCAO-basis U-term effective potential matrix (complex). +/// Wraps Plus_U::pot_onsite_complex plus the S-projection GEMM. +void pot_uterm_complex(Plus_U& dftu, + const int ik, + std::complex* eff_pot, + const std::vector& isk, + const std::complex* sk, + const int npol); + +/// @brief Compute the LCAO-basis U-term effective potential matrix (real). +/// Wraps Plus_U::pot_onsite_real plus the S-projection GEMM. +void pot_uterm_real(Plus_U& dftu, + const int ik, + double* eff_pot, + const std::vector& isk, + const double* sk, + const int npol); + +} // namespace DFTU_LCAO +#endif + +#endif diff --git a/source/source_lcao/module_dftu/dftu_lcao.cpp b/source/source_lcao/module_dftu/dftu_lcao.cpp index d166dd05ec..18089533f2 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao.cpp @@ -1,4 +1,5 @@ #include "dftu_lcao.h" +#include "dftu_occup.h" #include "source_base/matrix.h" // occ_mat uses ModuleBase::matrix::operator() #include "source_base/tool_quit.h" @@ -8,10 +9,6 @@ #include #include - // mohan add 2025-11-06 -// Static member definitions moved to dftu_base.cpp (Plus_U_Base::) -// Plus_U inherits these from Plus_U_Base. - Plus_U::Plus_U() {} diff --git a/source/source_lcao/module_dftu/dftu_lcao.h b/source/source_lcao/module_dftu/dftu_lcao.h index f7f284a52c..a229b1ccdb 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.h +++ b/source/source_lcao/module_dftu/dftu_lcao.h @@ -171,41 +171,4 @@ class Plus_U : public Plus_U_Base }; -#ifdef __LCAO -namespace DFTU_LCAO { - -/// @brief Compute the occupation matrix and delegate to Plus_U member. -/// Dispatches to Plus_U::cal_occ_mat_gamma (gamma-only, double) or -/// Plus_U::cal_occ_mat_k (multi-k, std::complex) via template. -template -void cal_occ_mat(const int iter, - const UnitCell& ucell, - const std::vector>& dm, - const K_Vectors& kv, - const double& mixing_beta, - hamilt::Hamilt* p_ham, - Plus_U& dftu); - -/// @brief Compute the LCAO-basis U-term effective potential matrix (complex). -/// Wraps Plus_U::pot_onsite_complex plus the S-projection GEMM. -void pot_uterm_complex(Plus_U& dftu, - const int ik, - std::complex* eff_pot, - const std::vector& isk, - const std::complex* sk, - const int npol); - -/// @brief Compute the LCAO-basis U-term effective potential matrix (real). -/// Wraps Plus_U::pot_onsite_real plus the S-projection GEMM. -void pot_uterm_real(Plus_U& dftu, - const int ik, - double* eff_pot, - const std::vector& isk, - const double* sk, - const int npol); - -} // namespace DFTU_LCAO -#endif - - #endif diff --git a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp index 7844da7dbc..243bd1b4ff 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp @@ -1,4 +1,5 @@ #include "dftu_lcao_op_legacy.h" +#include "dftu_hamilt.h" #include "source_base/timer.h" #include "source_base/tool_title.h" diff --git a/source/source_lcao/module_dftu/dftu_occup.h b/source/source_lcao/module_dftu/dftu_occup.h new file mode 100644 index 0000000000..ceb1564d45 --- /dev/null +++ b/source/source_lcao/module_dftu/dftu_occup.h @@ -0,0 +1,30 @@ +#ifndef DFTU_OCCUP_H +#define DFTU_OCCUP_H + +#include "source_cell/klist.h" +#include "source_cell/unitcell.h" +#include "source_hamilt/hamilt.h" + +#include + +class Plus_U; + +#ifdef __LCAO +namespace DFTU_LCAO { + +/// @brief Compute the occupation matrix and delegate to Plus_U member. +/// Dispatches to Plus_U::cal_occ_mat_gamma (gamma-only, double) or +/// Plus_U::cal_occ_mat_k (multi-k, std::complex) via template. +template +void cal_occ_mat(const int iter, + const UnitCell& ucell, + const std::vector>& dm, + const K_Vectors& kv, + const double& mixing_beta, + hamilt::Hamilt* p_ham, + Plus_U& dftu); + +} // namespace DFTU_LCAO +#endif + +#endif diff --git a/source/source_lcao/setup_dftu_lcao.cpp b/source/source_lcao/setup_dftu_lcao.cpp index 9cc6463a3c..bd8d775fd7 100644 --- a/source/source_lcao/setup_dftu_lcao.cpp +++ b/source/source_lcao/setup_dftu_lcao.cpp @@ -1,5 +1,6 @@ #include "setup_dftu_lcao.h" #include "source_lcao/module_dftu/dftu_lcao.h" +#include "source_lcao/module_dftu/dftu_occup.h" #include "source_pw/module_pwdft/dftu_output.h" // mohan add 2025-11-08 #include "source_estate/module_dm/density_matrix.h" #include "source_lcao/hamilt_lcao.h" From 3a64bf86e5ee0d8ba6607596baf5e1eca7b186af Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 17:32:08 +0800 Subject: [PATCH 18/23] refactor(dftu): use DFTU_LCAO as TITLE/timer owner for pot_uterm_* free functions The two pot_uterm_{complex,real} functions were extracted into the DFTU_LCAO namespace in a previous commit, but their ModuleBase::TITLE and timer::start/end calls still used 'Plus_U' as the owner string. This made the runtime log misleading: the entries appeared to come from a Plus_U member function while they are actually DFTU_LCAO namespace free functions. Update the first TITLE/timer argument from 'Plus_U' to 'DFTU_LCAO' for all 6 calls in dftu_hamilt.cpp so the log owner matches the actual namespace hosting the function. Plus_U member functions in dftu_tools.cpp (pot_onsite_*), dftu_occup.cpp (cal_occ_mat_*), and dftu_lcao.cpp keep 'Plus_U' as their TITLE/timer owner, since those are still class members. OperatorDFTU::contributeHk in dftu_lcao_op_legacy.cpp keeps 'OperatorDFTU' as the owner, since it is a hamilt::OperatorDFTU member, not a Plus_U member nor a DFTU_LCAO free function. Verification: - rg confirms 6 TITLE/timer calls in dftu_hamilt.cpp now use 'DFTU_LCAO' as owner. - python3 tools/03_code_analysis/agent_governance_check.py --staged passes with no findings. --- source/source_lcao/module_dftu/dftu_hamilt.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/source_lcao/module_dftu/dftu_hamilt.cpp b/source/source_lcao/module_dftu/dftu_hamilt.cpp index 8e167f5e61..8152227902 100644 --- a/source/source_lcao/module_dftu/dftu_hamilt.cpp +++ b/source/source_lcao/module_dftu/dftu_hamilt.cpp @@ -14,13 +14,13 @@ void pot_uterm_complex(Plus_U& dftu, const std::complex* sk, const int npol) { - ModuleBase::TITLE("Plus_U", "pot_uterm_complex"); + ModuleBase::TITLE("DFTU_LCAO", "pot_uterm_complex"); if (!dftu.is_occ_mat_initialized()) { return; } - ModuleBase::timer::start("Plus_U", "pot_uterm_complex"); + ModuleBase::timer::start("DFTU_LCAO", "pot_uterm_complex"); int spin = isk[ik]; @@ -63,7 +63,7 @@ void pot_uterm_complex(Plus_U& dftu, eff_pot, one_int, one_int, paraV->desc); #endif - ModuleBase::timer::end("Plus_U", "pot_uterm_complex"); + ModuleBase::timer::end("DFTU_LCAO", "pot_uterm_complex"); return; } @@ -74,12 +74,12 @@ void pot_uterm_real(Plus_U& dftu, const double* sk, const int npol) { - ModuleBase::TITLE("Plus_U", "pot_uterm_real"); + ModuleBase::TITLE("DFTU_LCAO", "pot_uterm_real"); if (!dftu.is_occ_mat_initialized()) { return; } - ModuleBase::timer::start("Plus_U", "pot_uterm_real"); + ModuleBase::timer::start("DFTU_LCAO", "pot_uterm_real"); int spin = isk[ik]; @@ -118,7 +118,7 @@ void pot_uterm_real(Plus_U& dftu, eff_pot, &one_int, &one_int, const_cast(paraV->desc)); #endif - ModuleBase::timer::end("Plus_U", "pot_uterm_real"); + ModuleBase::timer::end("DFTU_LCAO", "pot_uterm_real"); return; } From 3ac7790dede16f76a56a15b292eddd001ea32712 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 17:48:54 +0800 Subject: [PATCH 19/23] refactor(dftu): rename VU/eff_pot variables to pot_onsite/pot_uterm across LCAO and PW bases The codebase mixed variable naming conventions for the same physical quantities: uppercase 'VU' (LCAO base) and lowercase 'vu' (PW base) for the Hubbard on-site potential, 'eff_pot' for the LCAO-basis U-term effective potential, and 'eff_pot_pw' for the PW counterpart. This commit unifies them to 'pot_onsite' and 'pot_uterm[_pw]', matching the function-name conventions introduced earlier. Variable renames: * VU / vu -> pot_onsite (Hubbard on-site potential V_{mm'}) * eff_pot -> pot_uterm (LCAO-basis U-term effective potential) * eff_pot_pw -> pot_uterm_pw (PW-basis U-term effective potential, Plus_U_Base member plus accessor names get_eff_pot_pw_* / get_size_eff_pot_pw_* get_pot_uterm_pw_* / get_size_pot_uterm_pw_*) * eff_pot_pw_index -> pot_uterm_pw_index * VU_tmp / vu_tmp -> pot_onsite_tmp * vu_iat / vu_iat1 -> pot_onsite_iat / pot_onsite_iat1 * vu_ptr / vu_size / vu_host / vu_device -> pot_onsite_* * vu_begin_iat -> pot_onsite_begin_iat * rho_VU -> rho_pot_onsite * dm_VU_dSm -> dm_pot_onsite_dSm Function renames (per user request 'names containing vu should also be renamed'): * transfer_vu -> transfer_pot_onsite * cal_v_of_u -> cal_pot_onsite * compute_vu_spinor -> compute_pot_onsite_spinor * compute_vu_scalar -> compute_pot_onsite_scalar * cal_vu (test helper) -> cal_pot_onsite * local static 'compute_vu' in dftu_core_test -> compute_pot_onsite Test fixture renames: * VUPotentialTest -> PotOnsitePotentialTest * VUPot* test names -> PotOnsitePot* * OffDiagonalVU -> OffDiagonalPotOnsite Scope (38 files): * LCAO base: source/source_lcao/module_dftu/ (dftu_hamilt.{h,cpp}, dftu_tools.cpp, dftu_force.cpp, dftu_fs.cpp, dftu_lcao.{h,cpp}, dftu_lcao_op.{h,cpp}, dftu_lcao_op_legacy.cpp, test/dftu_*_test.cpp) * PW base: source/source_pw/module_pwdft/ (dftu_base.{h,cpp}, dftu_cal_occ_pw.cpp, dftu_tools_pw.{h,cpp}, op_pw_proj.cpp, onsite_proj.cpp, onsite_proj_tools.{h,cpp}, kernels/{onsite,force,stress}_op.{h,cpp}, kernels/cuda/{onsite,force,stress}_op.cu, kernels/rocm/{onsite,force,stress}_op.hip.cu, kernels/test/onsite_op_test.cpp) * Cross-module callers: source/source_estate/module_charge/chgmixing.cpp and charge_mixing.cpp (eff_pot_pw -> pot_uterm_pw), source/source_esolver/esolver_ks_lcao.cpp (comment). Out of scope (intentionally untouched): * Non-DFTU files that happen to contain 'vu' as LAPACK/FORTRAN parameter names (lapack_connector.h, scalapack_connector.h, gather_math_lib_info.cpp, td_current_io_comm.cpp, base/module_container/*, etc.) -- these 'vu' strings are LAPACK interface parameters, not Hubbard potential, and renaming them would be incorrect. * Plus_U_Base member 'uom_array' / 'uom_save' (occupation-related, different physical quantity, not renamed here). Verification: * rg '\bVU\b|\bvu\b|\beff_pot\b|cal_v_of_u|transfer_vu|compute_vu|eff_pot_pw' over source/source_lcao/module_dftu/, source/source_pw/module_pwdft/, chgmixing.cpp, charge_mixing.cpp, esolver_ks_lcao.cpp returns no matches. * python3 tools/03_code_analysis/agent_governance_check.py --staged passes with only PR-level WARNINGs (test/docs sync reminder). Test/Doc plan: * Tests: pure rename, no semantic change; existing tests in source/source_lcao/module_dftu/test/ and source/source_pw/module_pwdft/kernels/test/ updated in lock-step. * Docs: no INPUT parameter or user-facing behavior change; no documentation update required. --- source/source_esolver/esolver_ks_lcao.cpp | 2 +- .../module_charge/charge_mixing.cpp | 2 +- .../source_estate/module_charge/chgmixing.cpp | 2 +- source/source_lcao/module_dftu/dftu_force.cpp | 84 ++++---- source/source_lcao/module_dftu/dftu_fs.cpp | 14 +- .../source_lcao/module_dftu/dftu_hamilt.cpp | 56 ++--- source/source_lcao/module_dftu/dftu_hamilt.h | 4 +- source/source_lcao/module_dftu/dftu_lcao.cpp | 12 +- source/source_lcao/module_dftu/dftu_lcao.h | 4 +- .../source_lcao/module_dftu/dftu_lcao_op.cpp | 70 +++--- source/source_lcao/module_dftu/dftu_lcao_op.h | 14 +- .../module_dftu/dftu_lcao_op_legacy.cpp | 18 +- source/source_lcao/module_dftu/dftu_tools.cpp | 32 +-- .../module_dftu/test/dftu_core_test.cpp | 100 ++++----- .../module_dftu/test/dftu_operator_test.cpp | 200 +++++++++--------- .../module_dftu/test/dftu_pw_test.cpp | 172 +++++++-------- source/source_pw/module_pwdft/dftu_base.cpp | 26 +-- source/source_pw/module_pwdft/dftu_base.h | 34 +-- .../module_pwdft/dftu_cal_occ_pw.cpp | 34 +-- .../source_pw/module_pwdft/dftu_tools_pw.cpp | 28 +-- source/source_pw/module_pwdft/dftu_tools_pw.h | 36 ++-- .../module_pwdft/kernels/cuda/force_op.cu | 16 +- .../module_pwdft/kernels/cuda/onsite_op.cu | 22 +- .../module_pwdft/kernels/cuda/stress_op.cu | 16 +- .../module_pwdft/kernels/force_op.cpp | 8 +- .../source_pw/module_pwdft/kernels/force_op.h | 4 +- .../module_pwdft/kernels/onsite_op.cpp | 18 +- .../module_pwdft/kernels/onsite_op.h | 8 +- .../module_pwdft/kernels/rocm/force_op.hip.cu | 16 +- .../kernels/rocm/onsite_op.hip.cu | 22 +- .../kernels/rocm/stress_op.hip.cu | 16 +- .../module_pwdft/kernels/stress_op.cpp | 8 +- .../module_pwdft/kernels/stress_op.h | 4 +- .../kernels/test/onsite_op_test.cpp | 126 +++++------ source/source_pw/module_pwdft/onsite_proj.cpp | 12 +- .../module_pwdft/onsite_proj_tools.cpp | 36 ++-- .../module_pwdft/onsite_proj_tools.h | 8 +- source/source_pw/module_pwdft/op_pw_proj.cpp | 20 +- 38 files changed, 652 insertions(+), 652 deletions(-) diff --git a/source/source_esolver/esolver_ks_lcao.cpp b/source/source_esolver/esolver_ks_lcao.cpp index 83612f5d26..c91b9380a2 100644 --- a/source/source_esolver/esolver_ks_lcao.cpp +++ b/source/source_esolver/esolver_ks_lcao.cpp @@ -510,7 +510,7 @@ void ESolver_KS_LCAO::iter_finish(UnitCell& ucell, const int istep, int& // mohan add 2025-11: push DFT+U energy from Plus_U instance to ElecState. // Covers both dft_plus_u==1 (new method, energy accumulated by DFTU::contributeHR - // via cal_v_of_u) and dft_plus_u==2 (old method, energy from cal_energy_correction). + // via cal_pot_onsite) and dft_plus_u==2 (old method, energy from cal_energy_correction). if (this->inp_->dft_plus_u) { this->pelec->set_dftu_energy(this->dftu.get_energy()); diff --git a/source/source_estate/module_charge/charge_mixing.cpp b/source/source_estate/module_charge/charge_mixing.cpp index 1324975ec5..32c7b4f87e 100644 --- a/source/source_estate/module_charge/charge_mixing.cpp +++ b/source/source_estate/module_charge/charge_mixing.cpp @@ -264,7 +264,7 @@ void Charge_Mixing::allocate_mixing_uom(int uom_size) ModuleBase::TITLE("Charge_Mixing", "allocate_mixing_uom"); ModuleBase::timer::start("Charge_Mixing", "allocate_mixing_uom"); // For nspin=2, uom_size already includes both spin channels - // (eff_pot_pw.size() = pot_index * 2 for nspin=2) + // (pot_uterm_pw.size() = pot_index * 2 for nspin=2) // So uom_fold should always be 1 this->mixing->init_mixing_data(this->uom_mdata, uom_size, sizeof(double)); this->uom_mdata.reset(); diff --git a/source/source_estate/module_charge/chgmixing.cpp b/source/source_estate/module_charge/chgmixing.cpp index 7931d36b60..617579c4c1 100644 --- a/source/source_estate/module_charge/chgmixing.cpp +++ b/source/source_estate/module_charge/chgmixing.cpp @@ -133,7 +133,7 @@ void module_charge::chgmixing_ks_pw(const int iter, // scf iteration number // enable mixing_dftu for DFT+U occupation mixing dftu.enable_mixing(); // allocate memory for uom_mdata - p_chgmix->allocate_mixing_uom(dftu.get_size_eff_pot_pw()); + p_chgmix->allocate_mixing_uom(dftu.get_size_pot_uterm_pw()); } } diff --git a/source/source_lcao/module_dftu/dftu_force.cpp b/source/source_lcao/module_dftu/dftu_force.cpp index 9510001d2d..8df6bd2c3d 100644 --- a/source/source_lcao/module_dftu/dftu_force.cpp +++ b/source/source_lcao/module_dftu/dftu_force.cpp @@ -93,32 +93,32 @@ void force_stress(Plus_U& dftu, const double alpha = 1.0; const double beta = 0.0; - std::vector rho_VU(pv.nloc); + std::vector rho_pot_onsite(pv.nloc); for (int ik = 0; ik < kv.get_nks(); ik++) { const int spin = kv.isk[ik]; - double* VU = new double[pv.nloc]; + double* pot_onsite = new double[pv.nloc]; - dftu.pot_onsite_real(spin, false, VU, npol); + dftu.pot_onsite_real(spin, false, pot_onsite, npol); #ifdef __MPI ScalapackConnector::gemm(transT, transN, nlocal, nlocal, nlocal, alpha, (*dmk_d)[spin].data(), 1, 1, - pv.desc, VU, 1, 1, - pv.desc, beta, &rho_VU[0], + pv.desc, pot_onsite, 1, 1, + pv.desc, beta, &rho_pot_onsite[0], 1, 1, pv.desc); #endif - delete[] VU; + delete[] pot_onsite; if (dftu.is_cal_force()) { cal_force_gamma(dftu.get_nlocal(), dftu.get_npol(), dftu.get_orbital_corr_vec(), dftu.get_iatlnmipol2iwt(), - ucell, &rho_VU[0], pv, + ucell, &rho_pot_onsite[0], pv, fsr.DSloc_x, fsr.DSloc_y, fsr.DSloc_z, force_dftu); } @@ -128,7 +128,7 @@ void force_stress(Plus_U& dftu, dftu.get_ks_solver(), dftu.get_orb_cutoff(), ucell, pv, &gd, fsr.DSloc_x, fsr.DSloc_y, fsr.DSloc_z, fsr.DH_r, - &rho_VU[0], stress_dftu); + &rho_pot_onsite[0], stress_dftu); } } // ik } @@ -140,38 +140,38 @@ void force_stress(Plus_U& dftu, const std::complex alpha(1.0, 0.0); const std::complex beta(0.0, 0.0); - std::vector> rho_VU(pv.nloc); + std::vector> rho_pot_onsite(pv.nloc); for (int ik = 0; ik < kv.get_nks(); ik++) { const int spin = kv.isk[ik]; - std::complex* VU = new std::complex[pv.nloc]; + std::complex* pot_onsite = new std::complex[pv.nloc]; - dftu.pot_onsite_complex(spin, false, VU, npol); + dftu.pot_onsite_complex(spin, false, pot_onsite, npol); #ifdef __MPI ScalapackConnector::gemm(transT, transN, nlocal, nlocal, nlocal, alpha, (*dmk_c)[ik].data(), one_int, one_int, - pv.desc, VU, one_int, one_int, pv.desc, beta, - &rho_VU[0], one_int, one_int, pv.desc); + pv.desc, pot_onsite, one_int, one_int, pv.desc, beta, + &rho_pot_onsite[0], one_int, one_int, pv.desc); #endif - delete[] VU; + delete[] pot_onsite; if (dftu.is_cal_force()) { cal_force_k(dftu.get_nlocal(), dftu.get_npol(), dftu.get_ks_solver(), dftu.get_orb_cutoff(), dftu.get_orbital_corr_vec(), dftu.get_iatlnmipol2iwt(), - ucell, gd, fsr, pv, ik, &rho_VU[0], force_dftu, kv.kvec_d[ik]); + ucell, gd, fsr, pv, ik, &rho_pot_onsite[0], force_dftu, kv.kvec_d[ik]); } if (dftu.is_cal_stress()) { cal_stress_k(dftu.get_nlocal(), dftu.get_npol(), dftu.get_ks_solver(), dftu.get_orb_cutoff(), - ucell, gd, fsr, pv, ik, &rho_VU[0], stress_dftu, kv.kvec_d[ik]); + ucell, gd, fsr, pv, ik, &rho_pot_onsite[0], stress_dftu, kv.kvec_d[ik]); } } // ik } @@ -218,7 +218,7 @@ void cal_force_k(const int nlocal, ForceStressArrays& fsr, const Parallel_Orbitals& pv, const int ik, - const std::complex* rho_VU, + const std::complex* rho_pot_onsite, ModuleBase::matrix& force_dftu, const ModuleBase::Vector3& kvec_d) { @@ -233,7 +233,7 @@ void cal_force_k(const int nlocal, assert(nlocal>0); - std::vector> dm_VU_dSm(pv.nloc); + std::vector> dm_pot_onsite_dSm(pv.nloc); std::vector> dSm_k(pv.nloc); for (int dim = 0; dim < 3; dim++) @@ -252,12 +252,12 @@ void cal_force_k(const int nlocal, one_int, one_int, pv.desc, - rho_VU, + rho_pot_onsite, one_int, one_int, pv.desc, zero, - &dm_VU_dSm[0], + &dm_pot_onsite_dSm[0], one_int, one_int, pv.desc); @@ -274,7 +274,7 @@ void cal_force_k(const int nlocal, const int irc = ic * pv.nrow + ir; if (iwt1 == iwt2) - force_dftu(iat1, dim) += dm_VU_dSm[irc].real(); + force_dftu(iat1, dim) += dm_pot_onsite_dSm[irc].real(); } // end ic } // end ir @@ -290,12 +290,12 @@ void cal_force_k(const int nlocal, one_int, one_int, pv.desc, - rho_VU, + rho_pot_onsite, one_int, one_int, pv.desc, zero, - &dm_VU_dSm[0], + &dm_pot_onsite_dSm[0], one_int, one_int, pv.desc); @@ -333,7 +333,7 @@ void cal_force_k(const int nlocal, if (mu < 0 || nu < 0) continue; - force_dftu(iat, dim) += dm_VU_dSm[nu * pv.nrow + mu].real(); + force_dftu(iat, dim) += dm_pot_onsite_dSm[nu * pv.nrow + mu].real(); } } // } // n @@ -355,7 +355,7 @@ void cal_stress_k(const int nlocal, ForceStressArrays& fsr, const Parallel_Orbitals& pv, const int ik, - const std::complex* rho_VU, + const std::complex* rho_pot_onsite, ModuleBase::matrix& stress_dftu, const ModuleBase::Vector3& kvec_d) { @@ -368,7 +368,7 @@ void cal_stress_k(const int nlocal, const std::complex zero(0.0, 0.0); const std::complex one(1.0, 0.0); - std::vector> dm_VU_sover(pv.nloc); + std::vector> dm_pot_onsite_sover(pv.nloc); std::vector> dSR_k(pv.nloc); for (int dim1 = 0; dim1 < 3; dim1++) @@ -385,7 +385,7 @@ void cal_stress_k(const int nlocal, nlocal, nlocal, minus_half, - rho_VU, + rho_pot_onsite, one_int, one_int, pv.desc, @@ -394,7 +394,7 @@ void cal_stress_k(const int nlocal, one_int, pv.desc, zero, - &dm_VU_sover[0], + &dm_pot_onsite_sover[0], one_int, one_int, pv.desc); @@ -409,7 +409,7 @@ void cal_stress_k(const int nlocal, const int irc = ic * pv.nrow + ir; if (iwt1 == iwt2) - stress_dftu(dim1, dim2) += 2.0 * dm_VU_sover[irc].real(); + stress_dftu(dim1, dim2) += 2.0 * dm_pot_onsite_sover[irc].real(); } // end ic } // end ir @@ -425,7 +425,7 @@ void cal_force_gamma(const int nlocal, const std::vector& orbital_corr, const std::vector>>>>& iatlnmipol2iwt, const UnitCell& ucell, - const double* rho_VU, + const double* rho_pot_onsite, const Parallel_Orbitals& pv, double* dsloc_x, double* dsloc_y, @@ -442,7 +442,7 @@ void cal_force_gamma(const int nlocal, const double minus_one = -1.0; assert(nlocal>0); - std::vector dm_VU_dSm(pv.nloc); + std::vector dm_pot_onsite_dSm(pv.nloc); for (int dim = 0; dim < 3; dim++) { @@ -471,12 +471,12 @@ void cal_force_gamma(const int nlocal, 1, 1, pv.desc, - rho_VU, + rho_pot_onsite, 1, 1, pv.desc, zero, - &dm_VU_dSm[0], + &dm_pot_onsite_dSm[0], 1, 1, pv.desc); @@ -493,7 +493,7 @@ void cal_force_gamma(const int nlocal, const int irc = ic * pv.nrow + ir; if (iwt1 == iwt2) - force_dftu(iat1, dim) += dm_VU_dSm[irc]; + force_dftu(iat1, dim) += dm_pot_onsite_dSm[irc]; } // end ic } // end ir @@ -509,12 +509,12 @@ void cal_force_gamma(const int nlocal, 1, 1, pv.desc, - rho_VU, + rho_pot_onsite, 1, 1, pv.desc, zero, - &dm_VU_dSm[0], + &dm_pot_onsite_dSm[0], 1, 1, pv.desc); @@ -554,7 +554,7 @@ void cal_force_gamma(const int nlocal, if (mu < 0 || nu < 0) continue; - force_dftu(iat, dim) += dm_VU_dSm[nu * pv.nrow + mu]; + force_dftu(iat, dim) += dm_pot_onsite_dSm[nu * pv.nrow + mu]; } } // } // n @@ -579,7 +579,7 @@ void cal_stress_gamma(const int nlocal, double* dsloc_y, double* dsloc_z, double* dh_r, - const double* rho_VU, + const double* rho_pot_onsite, ModuleBase::matrix& stress_dftu) { ModuleBase::TITLE("DFTU_LCAO", "cal_stress_gamma"); @@ -592,7 +592,7 @@ void cal_stress_gamma(const int nlocal, const double one = 1.0; std::vector dSR_gamma(pv.nloc); - std::vector dm_VU_sover(pv.nloc); + std::vector dm_pot_onsite_sover(pv.nloc); for (int dim1 = 0; dim1 < 3; dim1++) { @@ -608,7 +608,7 @@ void cal_stress_gamma(const int nlocal, nlocal, nlocal, minus_half, - rho_VU, + rho_pot_onsite, 1, 1, pv.desc, @@ -617,7 +617,7 @@ void cal_stress_gamma(const int nlocal, 1, pv.desc, zero, - &dm_VU_sover[0], + &dm_pot_onsite_sover[0], 1, 1, pv.desc); @@ -633,7 +633,7 @@ void cal_stress_gamma(const int nlocal, const int irc = ic * pv.nrow + ir; if (iwt1 == iwt2) - stress_dftu(dim1, dim2) += 2.0 * dm_VU_sover[irc]; + stress_dftu(dim1, dim2) += 2.0 * dm_pot_onsite_sover[irc]; } // end ic } // end ir diff --git a/source/source_lcao/module_dftu/dftu_fs.cpp b/source/source_lcao/module_dftu/dftu_fs.cpp index 3fff048293..54621d29e0 100644 --- a/source/source_lcao/module_dftu/dftu_fs.cpp +++ b/source/source_lcao/module_dftu/dftu_fs.cpp @@ -140,11 +140,11 @@ void DFTU>::cal_force_stress(const bool cal_force, std::vector occ(tlp1 * tlp1 * this->nspin, 0); this->dftu->get_occ_mat_flat(iat0, target_L, occ); - // calculate VU + // calculate pot_onsite const double u_value = this->dftu->get_u_current(T0); - std::vector VU(occ.size()); + std::vector pot_onsite(occ.size()); double eu_tmp = 0; - this->cal_v_of_u(occ, tlp1, u_value, &VU[0], eu_tmp); + this->cal_pot_onsite(occ, tlp1, u_value, &pot_onsite[0], eu_tmp); // second iteration to calculate force and stress // calculate Force for atom J @@ -190,7 +190,7 @@ void DFTU>::cal_force_stress(const bool cal_force, paraV, nlm_tot[ad1], nlm_tot[ad2], - VU, + pot_onsite, tmp, this->nspin, force_tmp1, @@ -204,7 +204,7 @@ void DFTU>::cal_force_stress(const bool cal_force, paraV, nlm_tot[ad1], nlm_tot[ad2], - VU, + pot_onsite, tmp, this->nspin, dis1, @@ -329,8 +329,8 @@ void DFTU>::cal_force_IJR(const int& iat1, * nlm2[m2] * dm_pointer[step_trace[step_is]]; tmp[2] = vu_in[m1 * m_size + m2 + is * m_size2] * nlm1[m1 + m_size * 3] * nlm2[m2] * dm_pointer[step_trace[step_is]]; - // force1 = - VU * * - // force2 = - VU * * } + // force1 = - pot_onsite * * + // force2 = - pot_onsite * * } force1[0] += tmp[0]; force1[1] += tmp[1]; force1[2] += tmp[2]; diff --git a/source/source_lcao/module_dftu/dftu_hamilt.cpp b/source/source_lcao/module_dftu/dftu_hamilt.cpp index 8152227902..2798baa03a 100644 --- a/source/source_lcao/module_dftu/dftu_hamilt.cpp +++ b/source/source_lcao/module_dftu/dftu_hamilt.cpp @@ -9,7 +9,7 @@ namespace DFTU_LCAO { void pot_uterm_complex(Plus_U& dftu, const int ik, - std::complex* eff_pot, + std::complex* pot_uterm, const std::vector& isk, const std::complex* sk, const int npol) @@ -26,7 +26,7 @@ void pot_uterm_complex(Plus_U& dftu, const Parallel_Orbitals* paraV = dftu.get_paraV(); const int nlocal = dftu.get_nlocal(); - ModuleBase::GlobalFunc::ZEROS(eff_pot, paraV->nloc); + ModuleBase::GlobalFunc::ZEROS(pot_uterm, paraV->nloc); //============================================================= // PART2: call pblas to calculate effective potential matrix @@ -37,30 +37,30 @@ void pot_uterm_complex(Plus_U& dftu, const std::complex half = 0.5; const std::complex zero = 0.0; - std::vector> VU(paraV->nloc); - dftu.pot_onsite_complex(spin, true, &VU[0], npol); + std::vector> pot_onsite(paraV->nloc); + dftu.pot_onsite_complex(spin, true, &pot_onsite[0], npol); #ifdef __MPI ScalapackConnector::gemm(transN, transN, nlocal, nlocal, nlocal, half, - ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), one_int, one_int, paraV->desc, + ModuleBase::GlobalFunc::VECTOR_TO_PTR(pot_onsite), one_int, one_int, paraV->desc, sk, one_int, one_int, paraV->desc, zero, - eff_pot, one_int, one_int, paraV->desc); + pot_uterm, one_int, one_int, paraV->desc); #endif for (int irc = 0; irc < paraV->nloc; irc++) { - VU[irc] = eff_pot[irc]; + pot_onsite[irc] = pot_uterm[irc]; } #ifdef __MPI ScalapackConnector::tranu(nlocal, nlocal, one, - &VU[0], one_int, one_int, paraV->desc, + &pot_onsite[0], one_int, one_int, paraV->desc, one, - eff_pot, one_int, one_int, paraV->desc); + pot_uterm, one_int, one_int, paraV->desc); #endif ModuleBase::timer::end("DFTU_LCAO", "pot_uterm_complex"); @@ -69,7 +69,7 @@ void pot_uterm_complex(Plus_U& dftu, void pot_uterm_real(Plus_U& dftu, const int ik, - double* eff_pot, + double* pot_uterm, const std::vector& isk, const double* sk, const int npol) @@ -85,7 +85,7 @@ void pot_uterm_real(Plus_U& dftu, const Parallel_Orbitals* paraV = dftu.get_paraV(); const int nlocal = dftu.get_nlocal(); - ModuleBase::GlobalFunc::ZEROS(eff_pot, paraV->nloc); + ModuleBase::GlobalFunc::ZEROS(pot_uterm, paraV->nloc); //============================================================= // PART2: call pblas to calculate effective potential matrix @@ -94,28 +94,28 @@ void pot_uterm_real(Plus_U& dftu, int one_int = 1; double alpha = 1.0, beta = 0.0, half = 0.5, one = 1.0; - std::vector VU(paraV->nloc); - dftu.pot_onsite_real(spin, 1, &VU[0], npol); + std::vector pot_onsite(paraV->nloc); + dftu.pot_onsite_real(spin, 1, &pot_onsite[0], npol); #ifdef __MPI ScalapackConnector::gemm(transN, transN, nlocal, nlocal, nlocal, half, - ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), 1, 1, paraV->desc, + ModuleBase::GlobalFunc::VECTOR_TO_PTR(pot_onsite), 1, 1, paraV->desc, sk, 1, 1, paraV->desc, beta, - eff_pot, 1, 1, paraV->desc); + pot_uterm, 1, 1, paraV->desc); #endif for (int irc = 0; irc < paraV->nloc; irc++) - VU[irc] = eff_pot[irc]; + pot_onsite[irc] = pot_uterm[irc]; #ifdef __MPI pdtran_(&nlocal, &nlocal, &one, - &VU[0], &one_int, &one_int, const_cast(paraV->desc), + &pot_onsite[0], &one_int, &one_int, const_cast(paraV->desc), &one, - eff_pot, &one_int, &one_int, const_cast(paraV->desc)); + pot_uterm, &one_int, &one_int, const_cast(paraV->desc)); #endif ModuleBase::timer::end("DFTU_LCAO", "pot_uterm_real"); @@ -124,20 +124,20 @@ void pot_uterm_real(Plus_U& dftu, } // namespace DFTU_LCAO -void Plus_U::cal_eff_pot_mat_R_double(const int ispin, double* SR, double* HR, const int npol) +void Plus_U::cal_pot_uterm_mat_R_double(const int ispin, double* SR, double* HR, const int npol) { const char transN = 'N', transT = 'T'; const int one_int = 1; const double alpha = 1.0, beta = 0.0, one = 1.0, half = 0.5; - std::vector VU(this->paraV->nloc); - this->pot_onsite_real(ispin, 1, &VU[0], npol); + std::vector pot_onsite(this->paraV->nloc); + this->pot_onsite_real(ispin, 1, &pot_onsite[0], npol); #ifdef __MPI ScalapackConnector::gemm(transN, transN, this->nlocal, this->nlocal, this->nlocal, half, - ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), 1, 1, this->paraV->desc, + ModuleBase::GlobalFunc::VECTOR_TO_PTR(pot_onsite), 1, 1, this->paraV->desc, SR, 1, 1, this->paraV->desc, beta, HR, 1, 1, this->paraV->desc); @@ -146,7 +146,7 @@ void Plus_U::cal_eff_pot_mat_R_double(const int ispin, double* SR, double* HR, c this->nlocal, this->nlocal, this->nlocal, half, SR, 1, 1, this->paraV->desc, - ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), 1, 1, this->paraV->desc, + ModuleBase::GlobalFunc::VECTOR_TO_PTR(pot_onsite), 1, 1, this->paraV->desc, one, HR, 1, 1, this->paraV->desc); #endif @@ -154,20 +154,20 @@ void Plus_U::cal_eff_pot_mat_R_double(const int ispin, double* SR, double* HR, c return; } -void Plus_U::cal_eff_pot_mat_R_complex_double(const int ispin, std::complex* SR, std::complex* HR, const int npol) +void Plus_U::cal_pot_uterm_mat_R_complex_double(const int ispin, std::complex* SR, std::complex* HR, const int npol) { const char transN = 'N', transT = 'T'; const int one_int = 1; const std::complex zero = 0.0, one = 1.0, half = 0.5; - std::vector> VU(this->paraV->nloc); - this->pot_onsite_complex(ispin, 1, &VU[0], npol); + std::vector> pot_onsite(this->paraV->nloc); + this->pot_onsite_complex(ispin, 1, &pot_onsite[0], npol); #ifdef __MPI ScalapackConnector::gemm(transN, transN, this->nlocal, this->nlocal, this->nlocal, half, - ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), one_int, one_int, this->paraV->desc, + ModuleBase::GlobalFunc::VECTOR_TO_PTR(pot_onsite), one_int, one_int, this->paraV->desc, SR, one_int, one_int, this->paraV->desc, zero, HR, one_int, one_int, this->paraV->desc); @@ -176,7 +176,7 @@ void Plus_U::cal_eff_pot_mat_R_complex_double(const int ispin, std::complexnlocal, this->nlocal, this->nlocal, half, SR, one_int, one_int, this->paraV->desc, - ModuleBase::GlobalFunc::VECTOR_TO_PTR(VU), one_int, one_int, this->paraV->desc, + ModuleBase::GlobalFunc::VECTOR_TO_PTR(pot_onsite), one_int, one_int, this->paraV->desc, one, HR, one_int, one_int, this->paraV->desc); #endif diff --git a/source/source_lcao/module_dftu/dftu_hamilt.h b/source/source_lcao/module_dftu/dftu_hamilt.h index cde08c18d4..4fbe7dad26 100644 --- a/source/source_lcao/module_dftu/dftu_hamilt.h +++ b/source/source_lcao/module_dftu/dftu_hamilt.h @@ -13,7 +13,7 @@ namespace DFTU_LCAO { /// Wraps Plus_U::pot_onsite_complex plus the S-projection GEMM. void pot_uterm_complex(Plus_U& dftu, const int ik, - std::complex* eff_pot, + std::complex* pot_uterm, const std::vector& isk, const std::complex* sk, const int npol); @@ -22,7 +22,7 @@ void pot_uterm_complex(Plus_U& dftu, /// Wraps Plus_U::pot_onsite_real plus the S-projection GEMM. void pot_uterm_real(Plus_U& dftu, const int ik, - double* eff_pot, + double* pot_uterm, const std::vector& isk, const double* sk, const int npol); diff --git a/source/source_lcao/module_dftu/dftu_lcao.cpp b/source/source_lcao/module_dftu/dftu_lcao.cpp index 18089533f2..bb0529d22d 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao.cpp @@ -221,16 +221,16 @@ void Plus_U::cal_energy_correction(const UnitCell& ucell, { for (int is = 0; is < 2; is++) { - double VU = 0.0; - VU = get_onebody_eff_pot(T, iat, l, n, is, m1_all, m2_all, false); - energy_dc += VU * this->occ_mat[iat][l][n][is](m1_all, m2_all); + double pot_onsite = 0.0; + pot_onsite = get_onebody_eff_pot(T, iat, l, n, is, m1_all, m2_all, false); + energy_dc += pot_onsite * this->occ_mat[iat][l][n][is](m1_all, m2_all); } } else if (this->nspin == 4) { - double VU = 0.0; - VU = get_onebody_eff_pot(T, iat, l, n, 0, m1_all, m2_all, false); - energy_dc += VU * this->occ_mat[iat][l][n][0](m1_all, m2_all); + double pot_onsite = 0.0; + pot_onsite = get_onebody_eff_pot(T, iat, l, n, 0, m1_all, m2_all, false); + energy_dc += pot_onsite * this->occ_mat[iat][l][n][0](m1_all, m2_all); } } } diff --git a/source/source_lcao/module_dftu/dftu_lcao.h b/source/source_lcao/module_dftu/dftu_lcao.h index a229b1ccdb..11e5cca0bb 100644 --- a/source/source_lcao/module_dftu/dftu_lcao.h +++ b/source/source_lcao/module_dftu/dftu_lcao.h @@ -108,8 +108,8 @@ class Plus_U : public Plus_U_Base // for both Hamiltonian and force/stress //============================================================= public: - void pot_onsite_complex(const int spin, const bool newlocale, std::complex* VU, const int npol); - void pot_onsite_real(const int spin, const bool newlocale, double* VU, const int npol); + void pot_onsite_complex(const int spin, const bool newlocale, std::complex* pot_onsite, const int npol); + void pot_onsite_real(const int spin, const bool newlocale, double* pot_onsite, const int npol); private: double get_onebody_eff_pot(const int T, diff --git a/source/source_lcao/module_dftu/dftu_lcao_op.cpp b/source/source_lcao/module_dftu/dftu_lcao_op.cpp index 011e451913..1c53437e71 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao_op.cpp @@ -182,7 +182,7 @@ void hamilt::DFTU>::cal_nlm_all(const Parallel_Orbi * * Uses get_dmr(current_spin) to get real-space density matrix * * Accumulates contributions from all atom pairs via cal_occ() * * Performs MPI reduction to sum occ across processes - * * Stores result via set_occ_mat_flat() for use in VU calculation + * * Stores result via set_occ_mat_flat() for use in pot_onsite calculation * * For nspin=1: occ is scaled by 0.5 (since only one spin channel computed) * - Subsequent iterations: occ_mat is computed fresh each iteration from updated DMR * @@ -361,26 +361,26 @@ void hamilt::DFTU>::contributeHR() } ModuleBase::timer::end("DFTU", "cal_occ"); - // 3. Calculate Hubbard potential VU from occupation matrix - // VU = U * (1/2 * delta(m,m') - occ(m,m')) for each spin channel + // 3. Calculate Hubbard potential pot_onsite from occupation matrix + // pot_onsite = U * (1/2 * delta(m,m') - occ(m,m')) for each spin channel // Energy: EU = U * 1/2 * occ(m,m') * occ(m',m) - ModuleBase::timer::start("DFTU", "cal_vu"); + ModuleBase::timer::start("DFTU", "cal_pot_onsite"); const double u_value = this->dftu->get_u_current(T0); - std::vector VU_tmp(occ.size()); + std::vector pot_onsite_tmp(occ.size()); // mohan update 2025-11: get_energy/set_energy are now instance methods // via this->dftu pointer, no longer global static state. double u_energy = this->dftu->get_energy(); - this->cal_v_of_u(occ, tlp1, u_value, VU_tmp.data(), u_energy); + this->cal_pot_onsite(occ, tlp1, u_value, pot_onsite_tmp.data(), u_energy); this->dftu->set_energy(u_energy); - // 4. Convert VU to appropriate data type (real or complex) - // For nspin=4 with complex Hamiltonian, VU needs Pauli matrix transformation - std::vector VU(occ.size()); - this->transfer_vu(VU_tmp, VU); + // 4. Convert pot_onsite to appropriate data type (real or complex) + // For nspin=4 with complex Hamiltonian, pot_onsite needs Pauli matrix transformation + std::vector pot_onsite(occ.size()); + this->transfer_pot_onsite(pot_onsite_tmp, pot_onsite); // 5. Second iteration: Calculate Hamiltonian matrix contribution - // HR += * VU(m,m') * + // HR += * pot_onsite(m,m') * // for all atom pairs within cutoff // Note: different iat0 may contribute to the same HR(iat1, iat2, R), so we need to protect the update // to avoid race conditions in multithreading. Reference: nonlocal.cpp for the atom_row_list pattern. @@ -415,12 +415,12 @@ void hamilt::DFTU>::contributeHR() #pragma omp critical(dftu_hr_update) #endif { - this->cal_HR_IJR(iat1, iat2, paraV, nlm1, nlm2, VU, tmp->get_pointer()); + this->cal_HR_IJR(iat1, iat2, paraV, nlm1, nlm2, pot_onsite, tmp->get_pointer()); } } } } - ModuleBase::timer::end("DFTU", "cal_vu"); + ModuleBase::timer::end("DFTU", "cal_pot_onsite"); } // 6. Post-processing: Energy correction and occ_mat state management @@ -470,7 +470,7 @@ void hamilt::DFTU>::cal_HR_IJR( const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& VU, + const std::vector& pot_onsite, TR* data_pointer) { @@ -483,7 +483,7 @@ void hamilt::DFTU>::cal_HR_IJR( // --------------------------------------------- auto row_indexes = paraV->get_indexes_row(iat1); auto col_indexes = paraV->get_indexes_col(iat2); - const int m_size = int(sqrt(VU.size()) / npol); + const int m_size = int(sqrt(pot_onsite.size()) / npol); // step_trace = 0 for NSPIN=1,2; ={0, 1, local_col, local_col+1} for NSPIN=4 std::vector step_trace(npol * npol, 0); for (int is = 0; is < npol; is++) @@ -512,7 +512,7 @@ void hamilt::DFTU>::cal_HR_IJR( { for (int m2 = 0; m2 < m_size; m2++) { - nlm_tmp += nlm1[m1] * nlm2[m2] * VU[m1 * m_size + m2 + start]; + nlm_tmp += nlm1[m1] * nlm2[m2] * pot_onsite[m1 * m_size + m2 + start]; } } data_pointer[step_trace[is]] += nlm_tmp; @@ -587,24 +587,24 @@ void hamilt::DFTU>::cal_occ(const int& iat1, } template -void hamilt::DFTU>::transfer_vu(std::vector& vu_tmp, std::vector& vu) +void hamilt::DFTU>::transfer_pot_onsite(std::vector& pot_onsite_tmp, std::vector& pot_onsite) { #ifdef __DEBUG - assert(vu.size() == vu_tmp.size()); + assert(pot_onsite.size() == pot_onsite_tmp.size()); #endif - for (int i = 0; i < vu_tmp.size(); i++) + for (int i = 0; i < pot_onsite_tmp.size(); i++) { - vu[i] = vu_tmp[i]; + pot_onsite[i] = pot_onsite_tmp[i]; } } template <> -void hamilt::DFTU, std::complex>>::transfer_vu( - std::vector& vu_tmp, - std::vector>& vu) +void hamilt::DFTU, std::complex>>::transfer_pot_onsite( + std::vector& pot_onsite_tmp, + std::vector>& pot_onsite) { #ifdef __DEBUG - assert(vu.size() == vu_tmp.size()); + assert(pot_onsite.size() == pot_onsite_tmp.size()); #endif // Pauli-to-spinor conversion for DFT+U potential: @@ -615,9 +615,9 @@ void hamilt::DFTU, std::complex, std::complex(0.0, 1.0) * vu_tmp[index[2]]); - vu[index[2]] = 0.5 * (vu_tmp[index[1]] + std::complex(0.0, 1.0) * vu_tmp[index[2]]); + pot_onsite[index[0]] = 0.5 * (pot_onsite_tmp[index[0]] + pot_onsite_tmp[index[3]]); + pot_onsite[index[3]] = 0.5 * (pot_onsite_tmp[index[0]] - pot_onsite_tmp[index[3]]); + pot_onsite[index[1]] = 0.5 * (pot_onsite_tmp[index[1]] - std::complex(0.0, 1.0) * pot_onsite_tmp[index[2]]); + pot_onsite[index[2]] = 0.5 * (pot_onsite_tmp[index[1]] + std::complex(0.0, 1.0) * pot_onsite_tmp[index[2]]); } } } template -void hamilt::DFTU>::cal_v_of_u(const std::vector& occ, +void hamilt::DFTU>::cal_pot_onsite(const std::vector& occ, const int m_size, const double u_value, - double* vu, + double* pot_onsite, double& eu) { // calculate the local matrix @@ -652,7 +652,7 @@ void hamilt::DFTU>::cal_v_of_u(const std::vector>::cal_v_of_u(const std::vector>::cal_v_of_u(const std::vector> : public OperatorLCAO const double* data_pointer, std::vector& occupations); - /// transfer VU format from pauli matrix to normal for non-collinear spin case - void transfer_vu(std::vector& vu_tmp, std::vector& vu); - /// VU_{m, m'} = sum_{m,m'} (1/2*delta_{m, m'} - occ_{m, m'}) * U + /// transfer pot_onsite format from pauli matrix to normal for non-collinear spin case + void transfer_pot_onsite(std::vector& pot_onsite_tmp, std::vector& pot_onsite); + /// pot_onsite_{m, m'} = sum_{m,m'} (1/2*delta_{m, m'} - occ_{m, m'}) * U /// EU = sum_{m,m'} 1/2 * U * occ_{m, m'} * occ_{m', m} - void cal_v_of_u(const std::vector& occ, const int m_size, const double u_value, double* vu, double& eu); + void cal_pot_onsite(const std::vector& occ, const int m_size, const double u_value, double* pot_onsite, double& eu); /** * @brief calculate the HR local matrix of atom pair @@ -112,7 +112,7 @@ class DFTU> : public OperatorLCAO const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, TR* data_pointer); /** @@ -123,7 +123,7 @@ class DFTU> : public OperatorLCAO const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, double* force1, @@ -136,7 +136,7 @@ class DFTU> : public OperatorLCAO const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, const ModuleBase::Vector3& dis1, diff --git a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp index 243bd1b4ff..ed79940290 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao_op_legacy.cpp @@ -25,15 +25,15 @@ void OperatorDFTU>::contributeHk(int ik) ModuleBase::TITLE("OperatorDFTU", "contributeHk"); ModuleBase::timer::start("OperatorDFTU", "contributeHk"); // Effective potential of DFT+U is added to total Hamiltonian here; Quxin adds on 20201029 - std::vector eff_pot(this->hsk->get_pv()->nloc); + std::vector pot_uterm(this->hsk->get_pv()->nloc); - DFTU_LCAO::pot_uterm_real(*this->dftu, ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); + DFTU_LCAO::pot_uterm_real(*this->dftu, ik, &pot_uterm[0], isk, this->hsk->get_sk(), this->npol); double* hk = this->hsk->get_hk(); for (int irc = 0; irc < this->hsk->get_pv()->nloc; irc++) { - hk[irc] += eff_pot[irc]; + hk[irc] += pot_uterm[irc]; } ModuleBase::timer::end("OperatorDFTU", "contributeHk"); @@ -46,15 +46,15 @@ void OperatorDFTU, double>>::contributeHk(int ModuleBase::timer::start("OperatorDFTU", "contributeHk"); // Effective potential of DFT+U is added to total Hamiltonian here; Quxin adds on 20201029 - std::vector> eff_pot(this->hsk->get_pv()->nloc); + std::vector> pot_uterm(this->hsk->get_pv()->nloc); - DFTU_LCAO::pot_uterm_complex(*this->dftu, ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); + DFTU_LCAO::pot_uterm_complex(*this->dftu, ik, &pot_uterm[0], isk, this->hsk->get_sk(), this->npol); std::complex* hk = this->hsk->get_hk(); for (int irc = 0; irc < this->hsk->get_pv()->nloc; irc++) { - hk[irc] += eff_pot[irc]; + hk[irc] += pot_uterm[irc]; } ModuleBase::timer::end("OperatorDFTU", "contributeHk"); @@ -66,14 +66,14 @@ void OperatorDFTU, std::complex>>::con ModuleBase::TITLE("OperatorDFTU", "contributeHk"); ModuleBase::timer::start("OperatorDFTU", "contributeHk"); // Effective potential of DFT+U is added to total Hamiltonian here; Quxin adds on 20201029 - std::vector> eff_pot(this->hsk->get_pv()->nloc); + std::vector> pot_uterm(this->hsk->get_pv()->nloc); - DFTU_LCAO::pot_uterm_complex(*this->dftu, ik, &eff_pot[0], isk, this->hsk->get_sk(), this->npol); + DFTU_LCAO::pot_uterm_complex(*this->dftu, ik, &pot_uterm[0], isk, this->hsk->get_sk(), this->npol); std::complex* hk = this->hsk->get_hk(); for (int irc = 0; irc < this->hsk->get_pv()->nloc; irc++) { - hk[irc] += eff_pot[irc]; + hk[irc] += pot_uterm[irc]; } ModuleBase::timer::end("OperatorDFTU", "contributeHk"); diff --git a/source/source_lcao/module_dftu/dftu_tools.cpp b/source/source_lcao/module_dftu/dftu_tools.cpp index ca858d90e6..2c69b78c8f 100644 --- a/source/source_lcao/module_dftu/dftu_tools.cpp +++ b/source/source_lcao/module_dftu/dftu_tools.cpp @@ -1,10 +1,10 @@ #include "dftu_lcao.h" #ifdef __LCAO -void Plus_U::pot_onsite_complex(const int spin, const bool new_occ_mat, std::complex* VU, const int npol) +void Plus_U::pot_onsite_complex(const int spin, const bool new_occ_mat, std::complex* pot_onsite, const int npol) { ModuleBase::TITLE("Plus_U", "pot_onsite_complex"); - ModuleBase::GlobalFunc::ZEROS(VU, this->paraV->nloc); + ModuleBase::GlobalFunc::ZEROS(pot_onsite, this->paraV->nloc); for (int it = 0; it < this->ucell->ntype; ++it) { @@ -52,7 +52,7 @@ void Plus_U::pot_onsite_complex(const int spin, const bool new_occ_mat, std::com int m1_all = m1 + (2 * L + 1) * ipol1; int m2_all = m2 + (2 * L + 1) * ipol2; double val = get_onebody_eff_pot(it, iat, L, n, spin, m1_all, m2_all, new_occ_mat); - VU[nu * this->paraV->nrow + mu] = std::complex(val, 0.0); + pot_onsite[nu * this->paraV->nrow + mu] = std::complex(val, 0.0); } // ipol2 } // m2 } // ipol1 @@ -65,10 +65,10 @@ void Plus_U::pot_onsite_complex(const int spin, const bool new_occ_mat, std::com return; } -void Plus_U::pot_onsite_real(const int spin, const bool new_occ_mat, double* VU, const int npol) +void Plus_U::pot_onsite_real(const int spin, const bool new_occ_mat, double* pot_onsite, const int npol) { ModuleBase::TITLE("Plus_U", "pot_onsite_real"); - ModuleBase::GlobalFunc::ZEROS(VU, this->paraV->nloc); + ModuleBase::GlobalFunc::ZEROS(pot_onsite, this->paraV->nloc); for (int it = 0; it < this->ucell->ntype; ++it) { @@ -115,7 +115,7 @@ void Plus_U::pot_onsite_real(const int spin, const bool new_occ_mat, double* VU, int m1_all = m1 + (2 * L + 1) * ipol1; int m2_all = m2 + (2 * L + 1) * ipol2; - VU[nu * this->paraV->nrow + mu] + pot_onsite[nu * this->paraV->nrow + mu] = this->get_onebody_eff_pot(it, iat, L, n, spin, m1_all, m2_all, new_occ_mat); } // ipol2 @@ -141,7 +141,7 @@ double Plus_U::get_onebody_eff_pot(const int T, { ModuleBase::TITLE("Plus_U", "get_onebody_eff_pot"); - double VU = 0.0; + double pot_onsite = 0.0; switch (cal_type) { @@ -160,18 +160,18 @@ double Plus_U::get_onebody_eff_pot(const int T, { if (m0 == m1) { - VU = (this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) + pot_onsite = (this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) * (0.5 - this->occ_mat[iat][L][N][spin](m0, m1)); } else { - VU = -(this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) * this->occ_mat[iat][L][N][spin](m0, m1); + pot_onsite = -(this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) * this->occ_mat[iat][L][N][spin](m0, m1); } } else { if (m0 == m1) { - VU = (this->u_current[T]) * (0.5 - this->occ_mat[iat][L][N][spin](m0, m1)); + pot_onsite = (this->u_current[T]) * (0.5 - this->occ_mat[iat][L][N][spin](m0, m1)); } else { - VU = -(this->u_current[T]) * this->occ_mat[iat][L][N][spin](m0, m1); + pot_onsite = -(this->u_current[T]) * this->occ_mat[iat][L][N][spin](m0, m1); } } } @@ -180,19 +180,19 @@ double Plus_U::get_onebody_eff_pot(const int T, if (use_yukawa_) { if (m0 == m1) { - VU = (this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) + pot_onsite = (this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) * (0.5 - this->occ_mat_save[iat][L][N][spin](m0, m1)); } else { - VU = -(this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) + pot_onsite = -(this->U_Yukawa[T][L][N] - this->J_Yukawa[T][L][N]) * this->occ_mat_save[iat][L][N][spin](m0, m1); } } else { if (m0 == m1) { - VU = (this->u_current[T]) * (0.5 - this->occ_mat_save[iat][L][N][spin](m0, m1)); + pot_onsite = (this->u_current[T]) * (0.5 - this->occ_mat_save[iat][L][N][spin](m0, m1)); } else { - VU = -(this->u_current[T]) * this->occ_mat_save[iat][L][N][spin](m0, m1); + pot_onsite = -(this->u_current[T]) * this->occ_mat_save[iat][L][N][spin](m0, m1); } } } @@ -204,6 +204,6 @@ double Plus_U::get_onebody_eff_pot(const int T, break; } - return VU; + return pot_onsite; } #endif diff --git a/source/source_lcao/module_dftu/test/dftu_core_test.cpp b/source/source_lcao/module_dftu/test/dftu_core_test.cpp index ab40aded66..4a26654f74 100644 --- a/source/source_lcao/module_dftu/test/dftu_core_test.cpp +++ b/source/source_lcao/module_dftu/test/dftu_core_test.cpp @@ -9,14 +9,14 @@ * Unit tests for DFT+U core algorithms. * * These tests target the most complex and bug-prone logic: - * 1. eff_pot_pw_index calculation for mixed atom types and nspin modes + * 1. pot_uterm_pw_index calculation for mixed atom types and nspin modes * 2. copy_occ_mat <-> set_occ_mat roundtrip (3 data layouts) - * 3. VU effective potential formula (cal_type=3, FLL) + * 3. pot_onsite effective potential formula (cal_type=3, FLL) * 4. Energy correction and double-counting terms ***********************************************************************/ // ===================================================================== -// 1. eff_pot_pw_index calculation +// 1. pot_uterm_pw_index calculation // // nspin=1: offset = sum(tlp1^2), total = sum(all tlp1^2) // nspin=2: same per-spin-channel, then pot_index *= 2 (split layout) @@ -27,13 +27,13 @@ class EffPotIndexTest : public ::testing::Test { protected: struct AtomSpec { int l; int na; }; // correlated orbital l, number of atoms - std::vector eff_pot_pw_index; + std::vector pot_uterm_pw_index; int pot_index; void compute_indices(const std::vector& atoms, int nspin) { pot_index = 0; - eff_pot_pw_index.resize(atoms.size()); + pot_uterm_pw_index.resize(atoms.size()); for (size_t i = 0; i < atoms.size(); i++) { @@ -42,12 +42,12 @@ class EffPotIndexTest : public ::testing::Test if (nspin == 4) { - eff_pot_pw_index[i] = pot_index; + pot_uterm_pw_index[i] = pot_index; pot_index += tlp1_npol * tlp1_npol; } else { - eff_pot_pw_index[i] = pot_index; + pot_uterm_pw_index[i] = pot_index; pot_index += tlp1 * tlp1; } } @@ -64,9 +64,9 @@ TEST_F(EffPotIndexTest, Nspin1_MixedOrbitals) compute_indices(atoms, 1); // p: 9, d: 25, p: 9 - EXPECT_EQ(eff_pot_pw_index[0], 0); - EXPECT_EQ(eff_pot_pw_index[1], 9); - EXPECT_EQ(eff_pot_pw_index[2], 34); + EXPECT_EQ(pot_uterm_pw_index[0], 0); + EXPECT_EQ(pot_uterm_pw_index[1], 9); + EXPECT_EQ(pot_uterm_pw_index[2], 34); EXPECT_EQ(pot_index, 43); // 9 + 25 + 9 } @@ -75,15 +75,15 @@ TEST_F(EffPotIndexTest, Nspin2and4_SplitAndPauli) // nspin=2: 2 d-atoms, split layout [up | dn] std::vector atoms2 = {{2, 1}, {2, 1}}; compute_indices(atoms2, 2); - EXPECT_EQ(eff_pot_pw_index[0], 0); - EXPECT_EQ(eff_pot_pw_index[1], 25); + EXPECT_EQ(pot_uterm_pw_index[0], 0); + EXPECT_EQ(pot_uterm_pw_index[1], 25); EXPECT_EQ(pot_index, 100); // (25 + 25) * 2 // nspin=4: d + p atoms, Pauli blocks std::vector atoms4 = {{2, 1}, {1, 1}}; compute_indices(atoms4, 4); - EXPECT_EQ(eff_pot_pw_index[0], 0); // d: (5*2)^2 = 100 - EXPECT_EQ(eff_pot_pw_index[1], 100); // p: (3*2)^2 = 36 + EXPECT_EQ(pot_uterm_pw_index[0], 0); // d: (5*2)^2 = 100 + EXPECT_EQ(pot_uterm_pw_index[1], 100); // p: (3*2)^2 = 36 EXPECT_EQ(pot_index, 136); } @@ -107,7 +107,7 @@ static void copy_occ_mat_to_flat( const std::vector& locale_up, const std::vector& locale_dn, std::vector& uom_save, - const std::vector& eff_pot_pw_index, + const std::vector& pot_uterm_pw_index, int nspin) { if (nspin == 4) @@ -116,7 +116,7 @@ static void copy_occ_mat_to_flat( { int size = locale_up[iat].nr * locale_up[iat].nc; for (int mm = 0; mm < size; mm++) - uom_save[eff_pot_pw_index[iat] + mm] = locale_up[iat].data[mm]; + uom_save[pot_uterm_pw_index[iat] + mm] = locale_up[iat].data[mm]; } } else if (nspin == 2) // split layout: [up | dn] @@ -127,8 +127,8 @@ static void copy_occ_mat_to_flat( int size = locale_up[iat].nr * locale_up[iat].nc; for (int mm = 0; mm < size; mm++) { - uom_save[eff_pot_pw_index[iat] + mm] = locale_up[iat].data[mm]; - uom_save[half_size + eff_pot_pw_index[iat] + mm] = locale_dn[iat].data[mm]; + uom_save[pot_uterm_pw_index[iat] + mm] = locale_up[iat].data[mm]; + uom_save[half_size + pot_uterm_pw_index[iat] + mm] = locale_dn[iat].data[mm]; } } } @@ -138,7 +138,7 @@ static void copy_occ_mat_to_flat( { int size = locale_up[iat].nr * locale_up[iat].nc; for (int mm = 0; mm < size; mm++) - uom_save[eff_pot_pw_index[iat] + mm] = locale_up[iat].data[mm]; + uom_save[pot_uterm_pw_index[iat] + mm] = locale_up[iat].data[mm]; } } } @@ -147,7 +147,7 @@ static void set_occ_mat_from_flat( const std::vector& uom_array, std::vector& locale_up, std::vector& locale_dn, - const std::vector& eff_pot_pw_index, + const std::vector& pot_uterm_pw_index, int nspin) { if (nspin == 4) @@ -156,7 +156,7 @@ static void set_occ_mat_from_flat( { int size = locale_up[iat].nr * locale_up[iat].nc; for (int mm = 0; mm < size; mm++) - locale_up[iat].data[mm] = uom_array[eff_pot_pw_index[iat] + mm]; + locale_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; } } else if (nspin == 2) @@ -167,8 +167,8 @@ static void set_occ_mat_from_flat( int size = locale_up[iat].nr * locale_up[iat].nc; for (int mm = 0; mm < size; mm++) { - locale_up[iat].data[mm] = uom_array[eff_pot_pw_index[iat] + mm]; - locale_dn[iat].data[mm] = uom_array[half_size + eff_pot_pw_index[iat] + mm]; + locale_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; + locale_dn[iat].data[mm] = uom_array[half_size + pot_uterm_pw_index[iat] + mm]; } } } @@ -178,7 +178,7 @@ static void set_occ_mat_from_flat( { int size = locale_up[iat].nr * locale_up[iat].nc; for (int mm = 0; mm < size; mm++) - locale_up[iat].data[mm] = uom_array[eff_pot_pw_index[iat] + mm]; + locale_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; } } } @@ -200,10 +200,10 @@ TEST_F(OccMatRoundtripTest, Nspin1and2_SingleAndSplitLayout) for (int i = 0; i < size; i++) locale_up[0].data[i] = static_cast(i + 1); - std::vector eff_pot_pw_index = {0}; + std::vector pot_uterm_pw_index = {0}; std::vector uom_save(size, 0.0); - copy_occ_mat_to_flat(locale_up, locale_dn, uom_save, eff_pot_pw_index, 1); - set_occ_mat_from_flat(uom_save, locale_up, locale_dn, eff_pot_pw_index, 1); + copy_occ_mat_to_flat(locale_up, locale_dn, uom_save, pot_uterm_pw_index, 1); + set_occ_mat_from_flat(uom_save, locale_up, locale_dn, pot_uterm_pw_index, 1); for (int i = 0; i < size; i++) EXPECT_DOUBLE_EQ(locale_up[0].data[i], static_cast(i + 1)); @@ -215,14 +215,14 @@ TEST_F(OccMatRoundtripTest, Nspin1and2_SingleAndSplitLayout) locale_dn[0].data[i] = static_cast(i + 100); } uom_save.assign(total, 0.0); - copy_occ_mat_to_flat(locale_up, locale_dn, uom_save, eff_pot_pw_index, 2); + copy_occ_mat_to_flat(locale_up, locale_dn, uom_save, pot_uterm_pw_index, 2); // Verify split layout for (int i = 0; i < size; i++) { EXPECT_DOUBLE_EQ(uom_save[i], static_cast(i + 1)); EXPECT_DOUBLE_EQ(uom_save[size + i], static_cast(i + 100)); } - set_occ_mat_from_flat(uom_save, locale_up, locale_dn, eff_pot_pw_index, 2); + set_occ_mat_from_flat(uom_save, locale_up, locale_dn, pot_uterm_pw_index, 2); for (int i = 0; i < size; i++) { EXPECT_DOUBLE_EQ(locale_up[0].data[i], static_cast(i + 1)); @@ -245,11 +245,11 @@ TEST_F(OccMatRoundtripTest, Nspin4_PauliBlocks) } int total = std::accumulate(sizes.begin(), sizes.end(), 0); - std::vector eff_pot_pw_index(specs.size()); + std::vector pot_uterm_pw_index(specs.size()); int offset = 0; for (size_t i = 0; i < specs.size(); i++) { - eff_pot_pw_index[i] = offset; + pot_uterm_pw_index[i] = offset; offset += sizes[i]; } @@ -265,8 +265,8 @@ TEST_F(OccMatRoundtripTest, Nspin4_PauliBlocks) std::vector uom_array(total, 0.0); std::vector locale_dn(specs.size()); // unused for nspin=4 - copy_occ_mat_to_flat(locale, locale_dn, uom_array, eff_pot_pw_index, 4); - set_occ_mat_from_flat(uom_array, locale, locale_dn, eff_pot_pw_index, 4); + copy_occ_mat_to_flat(locale, locale_dn, uom_array, pot_uterm_pw_index, 4); + set_occ_mat_from_flat(uom_array, locale, locale_dn, pot_uterm_pw_index, 4); for (size_t i = 0; i < specs.size(); i++) for (int j = 0; j < sizes[i]; j++) @@ -274,13 +274,13 @@ TEST_F(OccMatRoundtripTest, Nspin4_PauliBlocks) } // ===================================================================== -// 3. VU effective potential formula (cal_type=3, FLL) +// 3. pot_onsite effective potential formula (cal_type=3, FLL) // -// VU[m0,m1] = U * (0.5*delta(m0,m1) - locale[m0,m1]) (diagonal) -// VU[m0,m1] = -U * locale[m0,m1] (off-diagonal) +// pot_onsite[m0,m1] = U * (0.5*delta(m0,m1) - locale[m0,m1]) (diagonal) +// pot_onsite[m0,m1] = -U * locale[m0,m1] (off-diagonal) // ===================================================================== -static double compute_vu(double U_val, int m0, int m1, double locale_val) +static double compute_pot_onsite(double U_val, int m0, int m1, double locale_val) { if (m0 == m1) return U_val * (0.5 - locale_val); @@ -288,34 +288,34 @@ static double compute_vu(double U_val, int m0, int m1, double locale_val) return -U_val * locale_val; } -class VUPotentialTest : public ::testing::Test +class PotOnsitePotentialTest : public ::testing::Test { protected: void SetUp() override {} }; -TEST_F(VUPotentialTest, Diagonal_HalfFilled) +TEST_F(PotOnsitePotentialTest, Diagonal_HalfFilled) { double U = 4.0; double locale = 0.5; // half-filled - double vu = compute_vu(U, 0, 0, locale); - EXPECT_DOUBLE_EQ(vu, 0.0); // U * (0.5 - 0.5) = 0 + double pot_onsite = compute_pot_onsite(U, 0, 0, locale); + EXPECT_DOUBLE_EQ(pot_onsite, 0.0); // U * (0.5 - 0.5) = 0 } -TEST_F(VUPotentialTest, Diagonal_FullyOccupied) +TEST_F(PotOnsitePotentialTest, Diagonal_FullyOccupied) { double U = 4.0; double locale = 1.0; // fully occupied - double vu = compute_vu(U, 0, 0, locale); - EXPECT_DOUBLE_EQ(vu, -2.0); // U * (0.5 - 1.0) = -2.0 + double pot_onsite = compute_pot_onsite(U, 0, 0, locale); + EXPECT_DOUBLE_EQ(pot_onsite, -2.0); // U * (0.5 - 1.0) = -2.0 } -TEST_F(VUPotentialTest, OffDiagonal) +TEST_F(PotOnsitePotentialTest, OffDiagonal) { double U = 5.0; double locale = 0.3; - double vu = compute_vu(U, 0, 1, locale); - EXPECT_DOUBLE_EQ(vu, -1.5); // -U * locale = -1.5 + double pot_onsite = compute_pot_onsite(U, 0, 1, locale); + EXPECT_DOUBLE_EQ(pot_onsite, -1.5); // -U * locale = -1.5 } // ===================================================================== @@ -368,7 +368,7 @@ TEST_F(EnergyCorrectionTest, OffDiagonal_Contribution) TEST_F(EnergyCorrectionTest, DoubleCounting_Energy) { - // E_dc = sum_{m1,m2,spin} VU[m1,m2] * n[m2,m1] + // E_dc = sum_{m1,m2,spin} pot_onsite[m1,m2] * n[m2,m1] const int m_size = 3; double U = 4.0; std::vector locale = { @@ -381,9 +381,9 @@ TEST_F(EnergyCorrectionTest, DoubleCounting_Energy) for (int m1 = 0; m1 < m_size; m1++) for (int m2 = 0; m2 < m_size; m2++) { - double vu = (m1 == m2) ? U * (0.5 - locale[m1 * m_size + m2]) + double pot_onsite = (m1 == m2) ? U * (0.5 - locale[m1 * m_size + m2]) : -U * locale[m1 * m_size + m2]; - e_dc += vu * locale[m2 * m_size + m1]; + e_dc += pot_onsite * locale[m2 * m_size + m1]; } // Only diagonal: m=0: 0*0.5=0, m=1: 0.8*0.3=0.24, m=2: 1.2*0.2=0.24 diff --git a/source/source_lcao/module_dftu/test/dftu_operator_test.cpp b/source/source_lcao/module_dftu/test/dftu_operator_test.cpp index 2856017d41..89a6b39911 100644 --- a/source/source_lcao/module_dftu/test/dftu_operator_test.cpp +++ b/source/source_lcao/module_dftu/test/dftu_operator_test.cpp @@ -6,22 +6,22 @@ /*********************************************************************** * Unit tests for DFT+U and DeltaSpin operator math and force/stress. - * Tests cover: cal_v_of_u, transfer_vu, cal_coeff_lambda, + * Tests cover: cal_pot_onsite, transfer_pot_onsite, cal_coeff_lambda, * Force/IJR, Stress/IJR, Voigt->matrix, PW index setup ***********************************************************************/ // ===================================================================== -// 1. cal_v_of_u: Hubbard potential calculation -// nspin=1,2 (spin_fold < 4): VU[is] = U * (0.5*delta - occ^T) +// 1. cal_pot_onsite: Hubbard potential calculation +// nspin=1,2 (spin_fold < 4): pot_onsite[is] = U * (0.5*delta - occ^T) // E_U += U * 0.5 * occ * occ^T -// nspin=4 (spin_fold == 4): VU[0] = U * (1.0*delta - occ^T), VU[is>0] = -U * occ^T +// nspin=4 (spin_fold == 4): pot_onsite[0] = U * (1.0*delta - occ^T), pot_onsite[is>0] = -U * occ^T // E_U += U * 0.25 * occ * occ^T // ===================================================================== -static void cal_v_of_u(const std::vector& occ, int m_size, double u_value, - std::vector& vu, double& eu) +static void cal_pot_onsite(const std::vector& occ, int m_size, double u_value, + std::vector& pot_onsite, double& eu) { - vu.assign(occ.size(), 0.0); + pot_onsite.assign(occ.size(), 0.0); eu = 0.0; int spin_fold = occ.size() / m_size / m_size; if (spin_fold < 4) // nspin=1,2 @@ -32,7 +32,7 @@ static void cal_v_of_u(const std::vector& occ, int m_size, double u_valu for (int m1 = 0; m1 < m_size; m1++) for (int m2 = 0; m2 < m_size; m2++) { - vu[start + m1 * m_size + m2] = u_value * (0.5 * (m1 == m2) - occ[start + m2 * m_size + m1]); + pot_onsite[start + m1 * m_size + m2] = u_value * (0.5 * (m1 == m2) - occ[start + m2 * m_size + m1]); eu += u_value * 0.5 * occ[start + m2 * m_size + m1] * occ[start + m1 * m_size + m2]; } } @@ -43,7 +43,7 @@ static void cal_v_of_u(const std::vector& occ, int m_size, double u_valu for (int m1 = 0; m1 < m_size; m1++) for (int m2 = 0; m2 < m_size; m2++) { - vu[m1 * m_size + m2] = u_value * (1.0 * (m1 == m2) - occ[m2 * m_size + m1]); + pot_onsite[m1 * m_size + m2] = u_value * (1.0 * (m1 == m2) - occ[m2 * m_size + m1]); eu += u_value * 0.25 * occ[m2 * m_size + m1] * occ[m1 * m_size + m2]; } // is=1,2,3: Pauli off-diagonal blocks @@ -53,7 +53,7 @@ static void cal_v_of_u(const std::vector& occ, int m_size, double u_valu for (int m1 = 0; m1 < m_size; m1++) for (int m2 = 0; m2 < m_size; m2++) { - vu[start + m1 * m_size + m2] = u_value * (0.0 - occ[start + m2 * m_size + m1]); + pot_onsite[start + m1 * m_size + m2] = u_value * (0.0 - occ[start + m2 * m_size + m1]); eu += u_value * 0.25 * occ[start + m2 * m_size + m1] * occ[start + m1 * m_size + m2]; } } @@ -65,10 +65,10 @@ class CalVOfUTest : public ::testing::Test { protected: void SetUp() override {} TEST_F(CalVOfUTest, Nspin1_SingleOrbital_HalfFilled) { std::vector occ = {0.5}; - std::vector vu; double eu = 0.0; - cal_v_of_u(occ, 1, 4.0, vu, eu); - // VU = 4*(0.5-0.5)=0, E_U = 4*0.5*0.5*0.5=0.5 - EXPECT_DOUBLE_EQ(vu[0], 0.0); + std::vector pot_onsite; double eu = 0.0; + cal_pot_onsite(occ, 1, 4.0, pot_onsite, eu); + // pot_onsite = 4*(0.5-0.5)=0, E_U = 4*0.5*0.5*0.5=0.5 + EXPECT_DOUBLE_EQ(pot_onsite[0], 0.0); EXPECT_DOUBLE_EQ(eu, 0.5); } @@ -78,11 +78,11 @@ TEST_F(CalVOfUTest, Nspin2_DOrbital_SpinPolarized) std::vector occ(m_size * m_size * 2, 0.0); for (int m = 0; m < m_size; m++) occ[m * m_size + m] = 0.8; // spin-up majority for (int m = 0; m < m_size; m++) occ[m_size*m_size + m*m_size + m] = 0.2; // spin-down minority - std::vector vu; double eu = 0.0; - cal_v_of_u(occ, m_size, 5.0, vu, eu); - // spin-up VU: 5*(0.5-0.8)=-1.5, spin-down VU: 5*(0.5-0.2)=1.5 - for (int m = 0; m < m_size; m++) EXPECT_NEAR(vu[m*m_size+m], -1.5, 1e-14); - for (int m = 0; m < m_size; m++) EXPECT_NEAR(vu[m_size*m_size+m*m_size+m], 1.5, 1e-14); + std::vector pot_onsite; double eu = 0.0; + cal_pot_onsite(occ, m_size, 5.0, pot_onsite, eu); + // spin-up pot_onsite: 5*(0.5-0.8)=-1.5, spin-down pot_onsite: 5*(0.5-0.2)=1.5 + for (int m = 0; m < m_size; m++) EXPECT_NEAR(pot_onsite[m*m_size+m], -1.5, 1e-14); + for (int m = 0; m < m_size; m++) EXPECT_NEAR(pot_onsite[m_size*m_size+m*m_size+m], 1.5, 1e-14); // E_U = 5*0.5*[5*(0.8^2)+5*(0.2^2)] = 8.5 EXPECT_NEAR(eu, 8.5, 1e-14); } @@ -92,72 +92,72 @@ TEST_F(CalVOfUTest, Nspin4_Porbital_PauliBlocks) const int m_size = 3; std::vector occ(m_size * m_size * 4, 0.0); for (int m = 0; m < m_size; m++) occ[m * m_size + m] = 0.5; // Pauli I block - std::vector vu; double eu = 0.0; - cal_v_of_u(occ, m_size, 4.0, vu, eu); - // is=0: VU=4*(1.0-0.5)=2.0, is=1,2,3: VU=0 - for (int m = 0; m < m_size; m++) EXPECT_NEAR(vu[m*m_size+m], 2.0, 1e-14); + std::vector pot_onsite; double eu = 0.0; + cal_pot_onsite(occ, m_size, 4.0, pot_onsite, eu); + // is=0: pot_onsite=4*(1.0-0.5)=2.0, is=1,2,3: pot_onsite=0 + for (int m = 0; m < m_size; m++) EXPECT_NEAR(pot_onsite[m*m_size+m], 2.0, 1e-14); for (int is = 1; is < 4; is++) - for (int i = 0; i < m_size*m_size; i++) EXPECT_NEAR(vu[is*m_size*m_size+i], 0.0, 1e-14); + for (int i = 0; i < m_size*m_size; i++) EXPECT_NEAR(pot_onsite[is*m_size*m_size+i], 0.0, 1e-14); // E_U = 4*0.25*3*(0.5*0.5) = 0.75 EXPECT_NEAR(eu, 0.75, 1e-14); } // ===================================================================== -// 2. transfer_vu: Pauli matrix transformation (nspin=4) -// vu[0] = 0.5*(vu_tmp[0]+vu_tmp[3]) // Pauli I -// vu[3] = 0.5*(vu_tmp[0]-vu_tmp[3]) // Pauli sigma_z -// vu[1] = 0.5*(vu_tmp[1]+i*vu_tmp[2]) // sigma_x+i*sigma_y -// vu[2] = 0.5*(vu_tmp[1]-i*vu_tmp[2]) // sigma_x-i*sigma_y +// 2. transfer_pot_onsite: Pauli matrix transformation (nspin=4) +// pot_onsite[0] = 0.5*(pot_onsite_tmp[0]+pot_onsite_tmp[3]) // Pauli I +// pot_onsite[3] = 0.5*(pot_onsite_tmp[0]-pot_onsite_tmp[3]) // Pauli sigma_z +// pot_onsite[1] = 0.5*(pot_onsite_tmp[1]+i*pot_onsite_tmp[2]) // sigma_x+i*sigma_y +// pot_onsite[2] = 0.5*(pot_onsite_tmp[1]-i*pot_onsite_tmp[2]) // sigma_x-i*sigma_y // ===================================================================== -static void transfer_vu(const std::vector& vu_tmp, - std::vector>& vu) +static void transfer_pot_onsite(const std::vector& pot_onsite_tmp, + std::vector>& pot_onsite) { - const int m_size = int(sqrt(vu_tmp.size()) / 2); + const int m_size = int(sqrt(pot_onsite_tmp.size()) / 2); const int m_size2 = m_size * m_size; - vu.resize(vu_tmp.size()); + pot_onsite.resize(pot_onsite_tmp.size()); for (int m1 = 0; m1 < m_size; m1++) for (int m2 = 0; m2 < m_size; m2++) { int idx[4] = {m1*m_size+m2, m1*m_size+m2+m_size2, m2*m_size+m1+2*m_size2, m2*m_size+m1+3*m_size2}; - vu[idx[0]] = 0.5 * (vu_tmp[idx[0]] + vu_tmp[idx[3]]); - vu[idx[3]] = 0.5 * (vu_tmp[idx[0]] - vu_tmp[idx[3]]); - vu[idx[1]] = 0.5 * (vu_tmp[idx[1]] + std::complex(0,1) * vu_tmp[idx[2]]); - vu[idx[2]] = 0.5 * (vu_tmp[idx[1]] - std::complex(0,1) * vu_tmp[idx[2]]); + pot_onsite[idx[0]] = 0.5 * (pot_onsite_tmp[idx[0]] + pot_onsite_tmp[idx[3]]); + pot_onsite[idx[3]] = 0.5 * (pot_onsite_tmp[idx[0]] - pot_onsite_tmp[idx[3]]); + pot_onsite[idx[1]] = 0.5 * (pot_onsite_tmp[idx[1]] + std::complex(0,1) * pot_onsite_tmp[idx[2]]); + pot_onsite[idx[2]] = 0.5 * (pot_onsite_tmp[idx[1]] - std::complex(0,1) * pot_onsite_tmp[idx[2]]); } } -class TransferVUTest : public ::testing::Test { protected: void SetUp() override {} }; +class Transferpot_onsiteTest : public ::testing::Test { protected: void SetUp() override {} }; -TEST_F(TransferVUTest, PauliI_IdentityInput) +TEST_F(Transferpot_onsiteTest, PauliI_IdentityInput) { - std::vector vu_tmp = {1.0, 0.0, 0.0, 1.0}; - std::vector> vu; - transfer_vu(vu_tmp, vu); - EXPECT_NEAR(vu[0].real(), 1.0, 1e-15); EXPECT_NEAR(vu[0].imag(), 0.0, 1e-15); - EXPECT_NEAR(vu[3].real(), 0.0, 1e-15); + std::vector pot_onsite_tmp = {1.0, 0.0, 0.0, 1.0}; + std::vector> pot_onsite; + transfer_pot_onsite(pot_onsite_tmp, pot_onsite); + EXPECT_NEAR(pot_onsite[0].real(), 1.0, 1e-15); EXPECT_NEAR(pot_onsite[0].imag(), 0.0, 1e-15); + EXPECT_NEAR(pot_onsite[3].real(), 0.0, 1e-15); } -TEST_F(TransferVUTest, PureSigmaZ) +TEST_F(Transferpot_onsiteTest, PureSigmaZ) { - std::vector vu_tmp = {1.0, 0.0, 0.0, -1.0}; - std::vector> vu; - transfer_vu(vu_tmp, vu); - EXPECT_NEAR(vu[0].real(), 0.0, 1e-15); EXPECT_NEAR(vu[3].real(), 1.0, 1e-15); + std::vector pot_onsite_tmp = {1.0, 0.0, 0.0, -1.0}; + std::vector> pot_onsite; + transfer_pot_onsite(pot_onsite_tmp, pot_onsite); + EXPECT_NEAR(pot_onsite[0].real(), 0.0, 1e-15); EXPECT_NEAR(pot_onsite[3].real(), 1.0, 1e-15); } -TEST_F(TransferVUTest, SigmaX_Y_Combined) +TEST_F(Transferpot_onsiteTest, SigmaX_Y_Combined) { - std::vector vu_tmp_x = {0.0, 1.0, 1.0, 0.0}; - std::vector> vu; - transfer_vu(vu_tmp_x, vu); - EXPECT_NEAR(vu[1].real(), 0.5, 1e-15); EXPECT_NEAR(vu[1].imag(), 0.5, 1e-15); - EXPECT_NEAR(vu[2].real(), 0.5, 1e-15); EXPECT_NEAR(vu[2].imag(), -0.5, 1e-15); - - std::vector vu_tmp_y = {0.0, 1.0, -1.0, 0.0}; - transfer_vu(vu_tmp_y, vu); - EXPECT_NEAR(vu[1].real(), 0.5, 1e-15); EXPECT_NEAR(vu[1].imag(), -0.5, 1e-15); - EXPECT_NEAR(vu[2].real(), 0.5, 1e-15); EXPECT_NEAR(vu[2].imag(), 0.5, 1e-15); + std::vector pot_onsite_tmp_x = {0.0, 1.0, 1.0, 0.0}; + std::vector> pot_onsite; + transfer_pot_onsite(pot_onsite_tmp_x, pot_onsite); + EXPECT_NEAR(pot_onsite[1].real(), 0.5, 1e-15); EXPECT_NEAR(pot_onsite[1].imag(), 0.5, 1e-15); + EXPECT_NEAR(pot_onsite[2].real(), 0.5, 1e-15); EXPECT_NEAR(pot_onsite[2].imag(), -0.5, 1e-15); + + std::vector pot_onsite_tmp_y = {0.0, 1.0, -1.0, 0.0}; + transfer_pot_onsite(pot_onsite_tmp_y, pot_onsite); + EXPECT_NEAR(pot_onsite[1].real(), 0.5, 1e-15); EXPECT_NEAR(pot_onsite[1].imag(), -0.5, 1e-15); + EXPECT_NEAR(pot_onsite[2].real(), 0.5, 1e-15); EXPECT_NEAR(pot_onsite[2].imag(), 0.5, 1e-15); } // ===================================================================== @@ -202,12 +202,12 @@ TEST_F(CalCoeffLambdaTest, NonCollinear_General) // ===================================================================== // 4. Force/IJR core loop -// force1 += VU * * * DM -// force2 -= VU * * * DM +// force1 += pot_onsite * * * DM +// force2 -= pot_onsite * * * DM // nlm arrays: [value, deri_x, deri_y, deri_z] // ===================================================================== -static void cal_force_IJR_core(const std::vector& vu_in, +static void cal_force_IJR_core(const std::vector& pot_onsite_in, const std::vector& nlm1, const std::vector& nlm2, const double dm_val, int m_size, int nspin, double force1[3], double force2[3]) { @@ -216,13 +216,13 @@ static void cal_force_IJR_core(const std::vector& vu_in, for (int m1 = 0; m1 < m_size; m1++) for (int m2 = 0; m2 < m_size; m2++) { - double vu = vu_in[m1*m_size + m2 + is*m_size2], dm = dm_val; - force1[0] += vu * nlm1[m1+m_size] * nlm2[m2] * dm; - force1[1] += vu * nlm1[m1+2*m_size] * nlm2[m2] * dm; - force1[2] += vu * nlm1[m1+3*m_size] * nlm2[m2] * dm; - force2[0] -= vu * nlm1[m1+m_size] * nlm2[m2] * dm; - force2[1] -= vu * nlm1[m1+2*m_size] * nlm2[m2] * dm; - force2[2] -= vu * nlm1[m1+3*m_size] * nlm2[m2] * dm; + double pot_onsite = pot_onsite_in[m1*m_size + m2 + is*m_size2], dm = dm_val; + force1[0] += pot_onsite * nlm1[m1+m_size] * nlm2[m2] * dm; + force1[1] += pot_onsite * nlm1[m1+2*m_size] * nlm2[m2] * dm; + force1[2] += pot_onsite * nlm1[m1+3*m_size] * nlm2[m2] * dm; + force2[0] -= pot_onsite * nlm1[m1+m_size] * nlm2[m2] * dm; + force2[1] -= pot_onsite * nlm1[m1+2*m_size] * nlm2[m2] * dm; + force2[2] -= pot_onsite * nlm1[m1+3*m_size] * nlm2[m2] * dm; } } @@ -230,30 +230,30 @@ class ForceIJRTest : public ::testing::Test { protected: void SetUp() override { TEST_F(ForceIJRTest, SingleOrbital_SingleSpin) { - std::vector vu = {2.0}, nlm1 = {1.0, 0.1, 0.2, 0.3}, nlm2 = {1.0, 0.0, 0.0, 0.0}; + std::vector pot_onsite = {2.0}, nlm1 = {1.0, 0.1, 0.2, 0.3}, nlm2 = {1.0, 0.0, 0.0, 0.0}; double dm_val = 0.5, force1[3]={0}, force2[3]={0}; - cal_force_IJR_core(vu, nlm1, nlm2, dm_val, 1, 1, force1, force2); - // force = VU*deri(nlm1)*val(nlm2)*DM = 2.0*{0.1,0.2,0.3}*1.0*0.5 = {0.1,0.2,0.3} + cal_force_IJR_core(pot_onsite, nlm1, nlm2, dm_val, 1, 1, force1, force2); + // force = pot_onsite*deri(nlm1)*val(nlm2)*DM = 2.0*{0.1,0.2,0.3}*1.0*0.5 = {0.1,0.2,0.3} EXPECT_NEAR(force1[0], 0.1, 1e-15); EXPECT_NEAR(force1[1], 0.2, 1e-15); EXPECT_NEAR(force1[2], 0.3, 1e-15); EXPECT_NEAR(force2[0], -0.1, 1e-15); EXPECT_NEAR(force2[1], -0.2, 1e-15); EXPECT_NEAR(force2[2], -0.3, 1e-15); } TEST_F(ForceIJRTest, ActionReaction) { - std::vector vu = {1.5}, nlm1 = {1.0, 0.3, 0.4, 0.5}, nlm2 = {1.0, 0.0, 0.0, 0.0}; + std::vector pot_onsite = {1.5}, nlm1 = {1.0, 0.3, 0.4, 0.5}, nlm2 = {1.0, 0.0, 0.0, 0.0}; double dm_val = 1.0, force1[3]={0}, force2[3]={0}; - cal_force_IJR_core(vu, nlm1, nlm2, dm_val, 1, 1, force1, force2); + cal_force_IJR_core(pot_onsite, nlm1, nlm2, dm_val, 1, 1, force1, force2); for (int i = 0; i < 3; i++) EXPECT_NEAR(force1[i], -force2[i], 1e-15); } // ===================================================================== // 5. Stress/IJR core loop -// stress[0]+=VU*DM*(nlm1_dx*dis1.x*nlm2_val+nlm1_val*nlm2_dx*dis2.x) -// stress[3]+=VU*DM*(nlm1_dy*dis1.y*nlm2_val+nlm1_val*nlm2_dy*dis2.y) -// stress[5]+=VU*DM*(nlm1_dz*dis1.z*nlm2_val+nlm1_val*nlm2_dz*dis2.z) +// stress[0]+=pot_onsite*DM*(nlm1_dx*dis1.x*nlm2_val+nlm1_val*nlm2_dx*dis2.x) +// stress[3]+=pot_onsite*DM*(nlm1_dy*dis1.y*nlm2_val+nlm1_val*nlm2_dy*dis2.y) +// stress[5]+=pot_onsite*DM*(nlm1_dz*dis1.z*nlm2_val+nlm1_val*nlm2_dz*dis2.z) // ===================================================================== -static void cal_stress_IJR_core(const std::vector& vu_in, +static void cal_stress_IJR_core(const std::vector& pot_onsite_in, const std::vector& nlm1, const std::vector& nlm2, const double dm_val, int m_size, int nspin, double dis1[3], double dis2[3], double stress[6]) @@ -263,7 +263,7 @@ static void cal_stress_IJR_core(const std::vector& vu_in, for (int m1 = 0; m1 < m_size; m1++) for (int m2 = 0; m2 < m_size; m2++) { - double tmp = vu_in[m1*m_size+m2+is*m_size2] * dm_val; + double tmp = pot_onsite_in[m1*m_size+m2+is*m_size2] * dm_val; stress[0] += tmp*(nlm1[m1+m_size]*dis1[0]*nlm2[m2] + nlm1[m1]*nlm2[m2+m_size]*dis2[0]); stress[1] += tmp*(nlm1[m1+m_size]*dis1[1]*nlm2[m2] + nlm1[m1]*nlm2[m2+m_size]*dis2[1]); stress[2] += tmp*(nlm1[m1+m_size]*dis1[2]*nlm2[m2] + nlm1[m1]*nlm2[m2+m_size]*dis2[2]); @@ -277,9 +277,9 @@ class StressIJRTest : public ::testing::Test { protected: void SetUp() override TEST_F(StressIJRTest, SingleOrbital_XDisplacement) { - std::vector vu = {1.0}, nlm1 = {1.0, 0.1, 0.0, 0.0}, nlm2 = {1.0, 0.2, 0.0, 0.0}; + std::vector pot_onsite = {1.0}, nlm1 = {1.0, 0.1, 0.0, 0.0}, nlm2 = {1.0, 0.2, 0.0, 0.0}; double dm_val = 1.0, dis1[3] = {1.0, 0.0, 0.0}, dis2[3] = {-1.0, 0.0, 0.0}, stress[6] = {0.0}; - cal_stress_IJR_core(vu, nlm1, nlm2, dm_val, 1, 1, dis1, dis2, stress); + cal_stress_IJR_core(pot_onsite, nlm1, nlm2, dm_val, 1, 1, dis1, dis2, stress); // stress[0] = 1.0*(0.1*1.0*1.0 + 1.0*0.2*(-1.0)) = -0.1 EXPECT_NEAR(stress[0], -0.1, 1e-15); EXPECT_NEAR(stress[1], 0.0, 1e-15); EXPECT_NEAR(stress[2], 0.0, 1e-15); @@ -287,9 +287,9 @@ TEST_F(StressIJRTest, SingleOrbital_XDisplacement) TEST_F(StressIJRTest, SymmetricDisplacement) { - std::vector vu = {2.0}, nlm1 = {1.0, 0.1, 0.2, 0.3}, nlm2 = {1.0, 0.1, 0.2, 0.3}; + std::vector pot_onsite = {2.0}, nlm1 = {1.0, 0.1, 0.2, 0.3}, nlm2 = {1.0, 0.1, 0.2, 0.3}; double dm_val = 1.0, dis1[3] = {1.0, 2.0, 3.0}, dis2[3] = {1.0, 2.0, 3.0}, stress[6] = {0.0}; - cal_stress_IJR_core(vu, nlm1, nlm2, dm_val, 1, 1, dis1, dis2, stress); + cal_stress_IJR_core(pot_onsite, nlm1, nlm2, dm_val, 1, 1, dis1, dis2, stress); EXPECT_NEAR(stress[0], 2.0*(0.1*1.0 + 1.0*0.1*1.0), 1e-15); // xx EXPECT_NEAR(stress[4], 2.0*(0.2*3.0 + 1.0*0.2*3.0), 1e-15); // yz } @@ -325,9 +325,9 @@ TEST_F(VoigtToMatrixTest, FullMappingAndSymmetry) } // ===================================================================== -// 7. PW operator index setup (ip_iat, ip_m, vu_begin_iat) +// 7. PW operator index setup (ip_iat, ip_m, pot_onsite_begin_iat) // ip_m[ip] = m index if projector is correlated, else -1 -// ip_iat[ip] = atom index, vu_begin_iat[iat] = VU array offset +// ip_iat[ip] = atom index, pot_onsite_begin_iat[iat] = pot_onsite array offset // ===================================================================== class PWIndexSetupTest : public ::testing::Test @@ -337,10 +337,10 @@ class PWIndexSetupTest : public ::testing::Test void setup_indices(const std::vector& atoms, std::vector& ip_iat, std::vector& ip_m, - std::vector& vu_begin_iat, int& vu_total_size) + std::vector& pot_onsite_begin_iat, int& pot_onsite_total_size) { - int ip0 = 0, vu_begin = 0, npol = 1; - ip_iat.resize(0); ip_m.resize(0); vu_begin_iat.resize(atoms.size()); + int ip0 = 0, pot_onsite_begin = 0, npol = 1; + ip_iat.resize(0); ip_m.resize(0); pot_onsite_begin_iat.resize(atoms.size()); for (const auto& atom : atoms) { ip_iat.resize(ip_iat.size() + atom.nh); @@ -349,13 +349,13 @@ class PWIndexSetupTest : public ::testing::Test { for (int ip = 0; ip < atom.nh; ip++) { ip_iat[ip0] = static_cast(&atom - &atoms[0]); ip_m[ip0++] = -1; } - vu_begin_iat[&atom - &atoms[0]] = 0; + pot_onsite_begin_iat[&atom - &atoms[0]] = 0; } else { int tlp1 = 2 * atom.target_l + 1; - vu_begin_iat[&atom - &atoms[0]] = vu_begin; - vu_begin += tlp1 * tlp1 * npol * npol; + pot_onsite_begin_iat[&atom - &atoms[0]] = pot_onsite_begin; + pot_onsite_begin += tlp1 * tlp1 * npol * npol; int m_begin = atom.target_l * atom.target_l; int m_end = (atom.target_l + 1) * (atom.target_l + 1); for (int ip = 0; ip < atom.nh; ip++) @@ -365,28 +365,28 @@ class PWIndexSetupTest : public ::testing::Test } } } - vu_total_size = vu_begin; + pot_onsite_total_size = pot_onsite_begin; } }; TEST_F(PWIndexSetupTest, SingleCorrelatedAtom_DOrbital) { std::vector atoms = {{0, 9, 2}}; // s(1)+p(3)+d(5) projectors, l=2 - std::vector ip_iat, ip_m, vu_begin_iat; int vu_total_size; - setup_indices(atoms, ip_iat, ip_m, vu_begin_iat, vu_total_size); + std::vector ip_iat, ip_m, pot_onsite_begin_iat; int pot_onsite_total_size; + setup_indices(atoms, ip_iat, ip_m, pot_onsite_begin_iat, pot_onsite_total_size); // Projectors 0-3 (s+p): m=-1; 4-8 (d): m=0..4 EXPECT_EQ(ip_iat.size(), 9u); for (int ip = 0; ip < 4; ip++) EXPECT_EQ(ip_m[ip], -1); for (int ip = 4; ip < 9; ip++) { EXPECT_EQ(ip_iat[ip], 0); EXPECT_EQ(ip_m[ip], ip-4); } - EXPECT_EQ(vu_begin_iat[0], 0); - EXPECT_EQ(vu_total_size, 25); // 5*5 + EXPECT_EQ(pot_onsite_begin_iat[0], 0); + EXPECT_EQ(pot_onsite_total_size, 25); // 5*5 } TEST_F(PWIndexSetupTest, MixedCorrelatedUncorrelated) { std::vector atoms = {{0, 4, 1}, {1, 2, -1}}; // atom0: p-correlated, atom1: not - std::vector ip_iat, ip_m, vu_begin_iat; int vu_total_size; - setup_indices(atoms, ip_iat, ip_m, vu_begin_iat, vu_total_size); + std::vector ip_iat, ip_m, pot_onsite_begin_iat; int pot_onsite_total_size; + setup_indices(atoms, ip_iat, ip_m, pot_onsite_begin_iat, pot_onsite_total_size); // atom0: s(ip=0)->m=-1, p(ip=1,2,3)->m=0,1,2 EXPECT_EQ(ip_iat[0], 0); EXPECT_EQ(ip_m[0], -1); EXPECT_EQ(ip_iat[1], 0); EXPECT_EQ(ip_m[1], 0); @@ -395,5 +395,5 @@ TEST_F(PWIndexSetupTest, MixedCorrelatedUncorrelated) // atom1: all m=-1 EXPECT_EQ(ip_iat[4], 1); EXPECT_EQ(ip_m[4], -1); EXPECT_EQ(ip_iat[5], 1); EXPECT_EQ(ip_m[5], -1); - EXPECT_EQ(vu_total_size, 9); // 3*3 for p-orbital + EXPECT_EQ(pot_onsite_total_size, 9); // 3*3 for p-orbital } diff --git a/source/source_lcao/module_dftu/test/dftu_pw_test.cpp b/source/source_lcao/module_dftu/test/dftu_pw_test.cpp index ae50e082e1..dc838e1db2 100644 --- a/source/source_lcao/module_dftu/test/dftu_pw_test.cpp +++ b/source/source_lcao/module_dftu/test/dftu_pw_test.cpp @@ -13,11 +13,11 @@ * Test targets: * 1. Energy weight logic: weight_eu and diag_coeff for nspin=1/2/4 * 2. Becp index logic: different index formulas for nspin=1/2 vs nspin=4 - * 3. VU effective potential: cal_occ_pw VU calculation for all nspin modes + * 3. pot_onsite effective potential: cal_occ_pw pot_onsite calculation for all nspin modes * 4. Energy calculation: E_U accumulation with correct weights * 5. Occupation matrix accumulation from becp: the core loop of cal_occ_pw * 6. Multi-atom split layout: [all_up | all_dn] layout for nspin=2 - * 7. OnsitePsOp kernel: vu application to ps for npol=1 + * 7. OnsitePsOp kernel: pot_onsite application to ps for npol=1 * * Strategy: test energy weights and becp index logic as pure * arithmetic — no need to link against full ABACUS libraries. @@ -67,12 +67,12 @@ TEST_F(DftuPwTest, BecpIndexNspin12vs4) } // ===================================================================== -// VU effective potential tests (cal_occ_pw logic) +// pot_onsite effective potential tests (cal_occ_pw logic) // ===================================================================== -TEST_F(DftuPwTest, VUPotNspin1_DiagonalLocale) +TEST_F(DftuPwTest, PotOnsitePotNspin1_DiagonalLocale) { - // For nspin=1: VU[m1,m2] = U * (0.5*delta(m1,m2) - locale[m2*m_size+m1]) + // For nspin=1: pot_onsite[m1,m2] = U * (0.5*delta(m1,m2) - locale[m2*m_size+m1]) // With diagonal locale: locale[m,m] = 0.3 const double U_val = 4.0; const int m_size = 5; // d-orbital: 2*2+1 @@ -82,20 +82,20 @@ TEST_F(DftuPwTest, VUPotNspin1_DiagonalLocale) for (int m = 0; m < m_size; m++) locale_c[m * m_size + m] = 0.3; // diagonal - std::vector> vu(size, {0.0, 0.0}); - dftu_pw::compute_vu_scalar(vu.data(), locale_c.data(), U_val, 0.5, 1.0, m_size); + std::vector> pot_onsite(size, {0.0, 0.0}); + dftu_pw::compute_pot_onsite_scalar(pot_onsite.data(), locale_c.data(), U_val, 0.5, 1.0, m_size); // diagonal: U*(0.5 - 0.3) = 4.0*0.2 = 0.8 for (int m = 0; m < m_size; m++) - EXPECT_DOUBLE_EQ(vu[m * m_size + m].real(), 0.8); + EXPECT_DOUBLE_EQ(pot_onsite[m * m_size + m].real(), 0.8); // off-diagonal: U*(0 - 0) = 0 - EXPECT_DOUBLE_EQ(vu[0 * m_size + 1].real(), 0.0); - EXPECT_DOUBLE_EQ(vu[1 * m_size + 0].real(), 0.0); + EXPECT_DOUBLE_EQ(pot_onsite[0 * m_size + 1].real(), 0.0); + EXPECT_DOUBLE_EQ(pot_onsite[1 * m_size + 0].real(), 0.0); } -TEST_F(DftuPwTest, VUPotNspin2_TwoSpinChannels) +TEST_F(DftuPwTest, PotOnsitePotNspin2_TwoSpinChannels) { - // nspin=2: two independent spin channels with same formula VU = U*(0.5*delta - locale) + // nspin=2: two independent spin channels with same formula pot_onsite = U*(0.5*delta - locale) const double U_val = 5.0; const int m_size = 3; const int size = m_size * m_size; @@ -105,44 +105,44 @@ TEST_F(DftuPwTest, VUPotNspin2_TwoSpinChannels) locale_up[0] = 0.4; // locale_up(0,0) = 0.4 locale_dn[0] = 0.1; // locale_dn(0,0) = 0.1 - std::vector> vu_up(size, {0.0, 0.0}); - std::vector> vu_dn(size, {0.0, 0.0}); - dftu_pw::compute_vu_scalar(vu_up.data(), locale_up.data(), U_val, 0.5, 0.5, m_size); - dftu_pw::compute_vu_scalar(vu_dn.data(), locale_dn.data(), U_val, 0.5, 0.5, m_size); + std::vector> pot_onsite_up(size, {0.0, 0.0}); + std::vector> pot_onsite_dn(size, {0.0, 0.0}); + dftu_pw::compute_pot_onsite_scalar(pot_onsite_up.data(), locale_up.data(), U_val, 0.5, 0.5, m_size); + dftu_pw::compute_pot_onsite_scalar(pot_onsite_dn.data(), locale_dn.data(), U_val, 0.5, 0.5, m_size); - // VU_up[0,0] = U*(0.5 - 0.4) = 0.5 - EXPECT_DOUBLE_EQ(vu_up[0].real(), 0.5); - // VU_dn[0,0] = U*(0.5 - 0.1) = 2.0 - EXPECT_DOUBLE_EQ(vu_dn[0].real(), 2.0); + // pot_onsite_up[0,0] = U*(0.5 - 0.4) = 0.5 + EXPECT_DOUBLE_EQ(pot_onsite_up[0].real(), 0.5); + // pot_onsite_dn[0,0] = U*(0.5 - 0.1) = 2.0 + EXPECT_DOUBLE_EQ(pot_onsite_dn[0].real(), 2.0); } -TEST_F(DftuPwTest, VUPotNspin4_PauliTransform) +TEST_F(DftuPwTest, PotOnsitePotNspin4_PauliTransform) { - // nspin=4: after computing VU in Pauli basis, transform to spin basis - // vu_spin[0] = 0.5*(vu_pauli[0] + vu_pauli[3]) - // vu_spin[3] = 0.5*(vu_pauli[0] - vu_pauli[3]) - // vu_spin[1] = 0.5*(vu_pauli[1] + i*vu_pauli[2]) - // vu_spin[2] = 0.5*(vu_pauli[1] - i*vu_pauli[2]) + // nspin=4: after computing pot_onsite in Pauli basis, transform to spin basis + // pot_onsite_spin[0] = 0.5*(pot_onsite_pauli[0] + pot_onsite_pauli[3]) + // pot_onsite_spin[3] = 0.5*(pot_onsite_pauli[0] - pot_onsite_pauli[3]) + // pot_onsite_spin[1] = 0.5*(pot_onsite_pauli[1] + i*pot_onsite_pauli[2]) + // pot_onsite_spin[2] = 0.5*(pot_onsite_pauli[1] - i*pot_onsite_pauli[2]) const int m_size = 1; const int size = m_size * m_size; // For a single (m1,m2) pair, test the Pauli->spin transform (in-place) - std::complex vu[4]; - vu[0] = {1.0, 0.0}; // charge channel - vu[1] = {0.5, 0.0}; // sigma_x - vu[2] = {0.3, 0.0}; // sigma_y - vu[3] = {0.2, 0.0}; // sigma_z - - dftu_pw::pauli_to_spin_basis(vu, m_size); - - EXPECT_DOUBLE_EQ(vu[0].real(), 0.6); // 0.5*(1.0+0.2) - EXPECT_DOUBLE_EQ(vu[0].imag(), 0.0); - EXPECT_DOUBLE_EQ(vu[3].real(), 0.4); // 0.5*(1.0-0.2) - EXPECT_DOUBLE_EQ(vu[3].imag(), 0.0); - EXPECT_DOUBLE_EQ(vu[1].real(), 0.25); // 0.5*0.5 - EXPECT_DOUBLE_EQ(vu[1].imag(), 0.15); // 0.5*0.3 - EXPECT_DOUBLE_EQ(vu[2].real(), 0.25); // 0.5*0.5 - EXPECT_DOUBLE_EQ(vu[2].imag(), -0.15);// -0.5*0.3 + std::complex pot_onsite[4]; + pot_onsite[0] = {1.0, 0.0}; // charge channel + pot_onsite[1] = {0.5, 0.0}; // sigma_x + pot_onsite[2] = {0.3, 0.0}; // sigma_y + pot_onsite[3] = {0.2, 0.0}; // sigma_z + + dftu_pw::pauli_to_spin_basis(pot_onsite, m_size); + + EXPECT_DOUBLE_EQ(pot_onsite[0].real(), 0.6); // 0.5*(1.0+0.2) + EXPECT_DOUBLE_EQ(pot_onsite[0].imag(), 0.0); + EXPECT_DOUBLE_EQ(pot_onsite[3].real(), 0.4); // 0.5*(1.0-0.2) + EXPECT_DOUBLE_EQ(pot_onsite[3].imag(), 0.0); + EXPECT_DOUBLE_EQ(pot_onsite[1].real(), 0.25); // 0.5*0.5 + EXPECT_DOUBLE_EQ(pot_onsite[1].imag(), 0.15); // 0.5*0.3 + EXPECT_DOUBLE_EQ(pot_onsite[2].real(), 0.25); // 0.5*0.5 + EXPECT_DOUBLE_EQ(pot_onsite[2].imag(), -0.15);// -0.5*0.3 } // ===================================================================== @@ -163,21 +163,21 @@ TEST_F(DftuPwTest, EnergyNspin12_DiagonalLocale) locale_c[2 * m_size + 2] = 0.2; // nspin=1: E = U * 1.0 * (0.5^2 + 0.3^2 + 0.2^2) = 4 * 0.38 = 1.52 - std::vector> vu_nspin1(size, {0.0, 0.0}); - double energy_u = dftu_pw::compute_vu_scalar( - vu_nspin1.data(), locale_c.data(), U_val, 0.5, 1.0, m_size); + std::vector> pot_onsite_nspin1(size, {0.0, 0.0}); + double energy_u = dftu_pw::compute_pot_onsite_scalar( + pot_onsite_nspin1.data(), locale_c.data(), U_val, 0.5, 1.0, m_size); EXPECT_DOUBLE_EQ(energy_u, 1.52); // nspin=2: two spin channels, weight_eu = 0.5 std::vector locale_up(size, 0.0), locale_dn(size, 0.0); locale_up[0] = 0.4; locale_dn[0] = 0.6; - std::vector> vu_up(size, {0.0, 0.0}); - std::vector> vu_dn(size, {0.0, 0.0}); + std::vector> pot_onsite_up(size, {0.0, 0.0}); + std::vector> pot_onsite_dn(size, {0.0, 0.0}); energy_u = 0.0; - energy_u += dftu_pw::compute_vu_scalar( - vu_up.data(), locale_up.data(), U_val, 0.5, 0.5, m_size); - energy_u += dftu_pw::compute_vu_scalar( - vu_dn.data(), locale_dn.data(), U_val, 0.5, 0.5, m_size); + energy_u += dftu_pw::compute_pot_onsite_scalar( + pot_onsite_up.data(), locale_up.data(), U_val, 0.5, 0.5, m_size); + energy_u += dftu_pw::compute_pot_onsite_scalar( + pot_onsite_dn.data(), locale_dn.data(), U_val, 0.5, 0.5, m_size); // E = U*0.5*(0.4^2 + 0.6^2) = 4*0.5*(0.16+0.36) = 1.04 EXPECT_DOUBLE_EQ(energy_u, 1.04); } @@ -199,9 +199,9 @@ TEST_F(DftuPwTest, EnergyNspin4_WithOffDiagonal) locale_c[size + 0] = 0.2; locale_c[size + 1] = 0.0; locale_c[size + 2] = 0.0; locale_c[size + 3] = 0.2; - std::vector> vu(size * 4, {0.0, 0.0}); - double energy_u = dftu_pw::compute_vu_spinor( - vu.data(), locale_c.data(), U_val, 1.0, weight_eu, m_size); + std::vector> pot_onsite(size * 4, {0.0, 0.0}); + double energy_u = dftu_pw::compute_pot_onsite_spinor( + pot_onsite.data(), locale_c.data(), U_val, 1.0, weight_eu, m_size); // is=0: 2*0.25*(0.5*0.5 + 0.1*0.1 + 0.1*0.1 + 0.5*0.5) = 0.26 // is=1: 2*0.25*(0.2*0.2 + 0 + 0 + 0.2*0.2) = 0.04 @@ -285,8 +285,8 @@ TEST_F(DftuPwTest, MultiAtomSplitLayout_Nspin2) const int nat = 2, m_size = 5, size = m_size * m_size; const int P = nat * size, total = P * 2, half_size = P; - // eff_pot_pw_index: split layout, each atom gets `size` entries - std::vector eff_pot_pw_index = {0, size}; + // pot_uterm_pw_index: split layout, each atom gets `size` entries + std::vector pot_uterm_pw_index = {0, size}; // Simulate locale values for both atoms std::vector loc_up[2], loc_dn[2]; @@ -302,8 +302,8 @@ TEST_F(DftuPwTest, MultiAtomSplitLayout_Nspin2) std::vector uom_array(total, 0.0); for (int iat = 0; iat < nat; iat++) for (int mm = 0; mm < size; mm++) { - uom_array[eff_pot_pw_index[iat] + mm] = loc_up[iat][mm]; - uom_array[half_size + eff_pot_pw_index[iat] + mm] = loc_dn[iat][mm]; + uom_array[pot_uterm_pw_index[iat] + mm] = loc_up[iat][mm]; + uom_array[half_size + pot_uterm_pw_index[iat] + mm] = loc_dn[iat][mm]; } // Verify split layout: first half = all spin-up, second half = all spin-down @@ -314,32 +314,32 @@ TEST_F(DftuPwTest, MultiAtomSplitLayout_Nspin2) // --- Read back and verify round-trip --- for (int iat = 0; iat < nat; iat++) - EXPECT_DOUBLE_EQ(uom_array[eff_pot_pw_index[iat]], loc_up[iat][0]); + EXPECT_DOUBLE_EQ(uom_array[pot_uterm_pw_index[iat]], loc_up[iat][0]); - // --- VU values in split layout --- + // --- pot_onsite values in split layout --- const double U_val = 5.0; const double diag_coeff = 0.5; - std::vector> eff_pot_pw(total, {0.0, 0.0}); - - // atom 0 spin-up VU - std::complex* vu_up_0 = &eff_pot_pw[0]; - vu_up_0[0] = U_val * (diag_coeff - loc_up[0][0]); - // atom 0 spin-down VU (split layout: offset by half_size) - std::complex* vu_dn_0 = &eff_pot_pw[half_size]; - vu_dn_0[0] = U_val * (diag_coeff - loc_dn[0][0]); - - EXPECT_DOUBLE_EQ(vu_up_0[0].real(), -1.5); // 5*(0.5-0.8) - EXPECT_DOUBLE_EQ(vu_dn_0[0].real(), 1.5); // 5*(0.5-0.2) - - // Verify no overlap between atoms in VU arrays - std::complex* vu_up_1 = &eff_pot_pw[size]; - vu_up_1[0] = U_val * (diag_coeff - loc_up[1][0]); - EXPECT_NE(vu_up_0[0], vu_up_1[0]); + std::vector> pot_uterm_pw(total, {0.0, 0.0}); + + // atom 0 spin-up pot_onsite + std::complex* pot_onsite_up_0 = &pot_uterm_pw[0]; + pot_onsite_up_0[0] = U_val * (diag_coeff - loc_up[0][0]); + // atom 0 spin-down pot_onsite (split layout: offset by half_size) + std::complex* pot_onsite_dn_0 = &pot_uterm_pw[half_size]; + pot_onsite_dn_0[0] = U_val * (diag_coeff - loc_dn[0][0]); + + EXPECT_DOUBLE_EQ(pot_onsite_up_0[0].real(), -1.5); // 5*(0.5-0.8) + EXPECT_DOUBLE_EQ(pot_onsite_dn_0[0].real(), 1.5); // 5*(0.5-0.2) + + // Verify no overlap between atoms in pot_onsite arrays + std::complex* pot_onsite_up_1 = &pot_uterm_pw[size]; + pot_onsite_up_1[0] = U_val * (diag_coeff - loc_up[1][0]); + EXPECT_NE(pot_onsite_up_0[0], pot_onsite_up_1[0]); } // ===================================================================== // OnsitePsOp kernel test (simplified npol=1 branch) -// Tests the vu application to ps without full ABACUS integration +// Tests the pot_onsite application to ps without full ABACUS integration // ===================================================================== TEST_F(DftuPwTest, OnsitePsOpKernel_Nspin2_Npol1) @@ -347,15 +347,15 @@ TEST_F(DftuPwTest, OnsitePsOpKernel_Nspin2_Npol1) // Simulate the npol=1 branch of onsite_ps_op kernel const int npm = 4, tnp = 10, orb_l = 2, tlp1 = 2 * orb_l + 1, nat = 2; - // vu array: 2 atoms, each with tlp1*tlp1 = 25 elements - std::vector> vu(nat * tlp1 * tlp1); - for (size_t i = 0; i < vu.size(); i++) - vu[i] = {static_cast(i + 1), 0.0}; + // pot_onsite array: 2 atoms, each with tlp1*tlp1 = 25 elements + std::vector> pot_onsite(nat * tlp1 * tlp1); + for (size_t i = 0; i < pot_onsite.size(); i++) + pot_onsite[i] = {static_cast(i + 1), 0.0}; // ip_m: maps each projector to m index within its atom std::vector ip_m = {0, 1, 2, 3, 4, 0, 1, 2, 3, 4}; std::vector ip_iat = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; - std::vector vu_begin_iat = {0, tlp1 * tlp1}; + std::vector pot_onsite_begin_iat = {0, tlp1 * tlp1}; // becp: npm * tnp std::vector> becp(npm * tnp, {0.0, 0.0}); @@ -372,21 +372,21 @@ TEST_F(DftuPwTest, OnsitePsOpKernel_Nspin2_Npol1) int m1 = ip_m[ip]; if (m1 < 0) continue; int iat = ip_iat[ip]; - const std::complex* vu_iat = vu.data() + vu_begin_iat[iat]; + const std::complex* pot_onsite_iat = pot_onsite.data() + pot_onsite_begin_iat[iat]; int ip2_begin = ip - m1, ip2_end = ip - m1 + tlp1; const int psind = ip * npm + ib; for (int ip2 = ip2_begin; ip2 < ip2_end; ip2++) { int m2 = ip_m[ip2]; - ps[psind] += vu_iat[m1 * tlp1 + m2] * becp[ib * tnp + ip2]; + ps[psind] += pot_onsite_iat[m1 * tlp1 + m2] * becp[ib * tnp + ip2]; } } } // Verify ps[0] (ib=0, ip=0, m1=0, iat=0) - // ps[0] = sum_{ip2=0..4} vu[0*tlp1+ip_m[ip2]] * becp[0*tnp+ip2] + // ps[0] = sum_{ip2=0..4} pot_onsite[0*tlp1+ip_m[ip2]] * becp[0*tnp+ip2] std::complex expected = {0.0, 0.0}; for (int ip2 = 0; ip2 < tlp1; ip2++) - expected += vu[ip2] * becp[ip2]; + expected += pot_onsite[ip2] * becp[ip2]; EXPECT_DOUBLE_EQ(ps[0].real(), expected.real()); EXPECT_DOUBLE_EQ(ps[0].imag(), expected.imag()); } diff --git a/source/source_pw/module_pwdft/dftu_base.cpp b/source/source_pw/module_pwdft/dftu_base.cpp index 08b282948f..8290c7fec4 100644 --- a/source/source_pw/module_pwdft/dftu_base.cpp +++ b/source/source_pw/module_pwdft/dftu_base.cpp @@ -73,7 +73,7 @@ void Plus_U_Base::init_base(UnitCell& cell, this->occ_mat.resize(cell.nat); this->occ_mat_save.resize(cell.nat); - this->eff_pot_pw_index.resize(cell.nat); + this->pot_uterm_pw_index.resize(cell.nat); int pot_index = 0; this->iatlnmipol2iwt.resize(cell.nat); @@ -100,12 +100,12 @@ void Plus_U_Base::init_base(UnitCell& cell, const int elem_size = tlp1 * tlp1; if(nspin == 4) { - this->eff_pot_pw_index[iat] = pot_index; + this->pot_uterm_pw_index[iat] = pot_index; pot_index += tlp1_npol * tlp1_npol; } else { - this->eff_pot_pw_index[iat] = pot_index; + this->pot_uterm_pw_index[iat] = pot_index; pot_index += elem_size; } @@ -174,7 +174,7 @@ void Plus_U_Base::init_base(UnitCell& cell, if (nspin == 2) pot_index *= 2; - this->eff_pot_pw.resize(pot_index, 0.0); + this->pot_uterm_pw.resize(pot_index, 0.0); this->uom_array.resize(pot_index, 0.0); this->uom_save.resize(pot_index, 0.0); @@ -310,7 +310,7 @@ void Plus_U_Base::copy_occ_mat(const UnitCell& ucell) const int size = occ_mat[iat][target_l][0][0].nr * occ_mat[iat][target_l][0][0].nc; for(int mm=0; mmuom_save[eff_pot_pw_index[iat]+mm] = occ_mat[iat][target_l][0][0].c[mm]; + this->uom_save[pot_uterm_pw_index[iat]+mm] = occ_mat[iat][target_l][0][0].c[mm]; } } } @@ -324,8 +324,8 @@ void Plus_U_Base::copy_occ_mat(const UnitCell& ucell) const int half_size = this->uom_save.size() / 2; for(int mm=0; mmuom_save[eff_pot_pw_index[iat]+mm] = occ_mat[iat][target_l][0][0].c[mm]; - this->uom_save[half_size + eff_pot_pw_index[iat]+mm] = occ_mat[iat][target_l][0][1].c[mm]; + this->uom_save[pot_uterm_pw_index[iat]+mm] = occ_mat[iat][target_l][0][0].c[mm]; + this->uom_save[half_size + pot_uterm_pw_index[iat]+mm] = occ_mat[iat][target_l][0][1].c[mm]; } } } @@ -403,7 +403,7 @@ void Plus_U_Base::mix_occ_mat(const UnitCell& ucell, { for (int mm = 0; mm < size; mm++) { - this->uom_save[eff_pot_pw_index[iat] + mm] = occ_mat[iat][target_l][0][0].c[mm]; + this->uom_save[pot_uterm_pw_index[iat] + mm] = occ_mat[iat][target_l][0][0].c[mm]; } } } @@ -420,8 +420,8 @@ void Plus_U_Base::mix_occ_mat(const UnitCell& ucell, { for (int mm = 0; mm < size; mm++) { - this->uom_save[eff_pot_pw_index[iat] + mm] = occ_mat[iat][target_l][0][0].c[mm]; - this->uom_save[half_size + eff_pot_pw_index[iat] + mm] = occ_mat[iat][target_l][0][1].c[mm]; + this->uom_save[pot_uterm_pw_index[iat] + mm] = occ_mat[iat][target_l][0][0].c[mm]; + this->uom_save[half_size + pot_uterm_pw_index[iat] + mm] = occ_mat[iat][target_l][0][1].c[mm]; } } } @@ -446,17 +446,17 @@ void Plus_U_Base::set_occ_mat(const UnitCell& ucell) if (this->nspin == 4) { for(int mm = 0; mm < occ_mat[iat][l][0][0].nr * occ_mat[iat][l][0][0].nc; mm++) - occ_mat[iat][l][0][0].c[mm] = this->uom_array[eff_pot_pw_index[iat] + mm]; + occ_mat[iat][l][0][0].c[mm] = this->uom_array[pot_uterm_pw_index[iat] + mm]; } else if (this->nspin == 1 || this->nspin == 2) { const int half_size = this->uom_array.size() / 2; for(int mm = 0; mm < occ_mat[iat][l][0][0].nr * occ_mat[iat][l][0][0].nc; mm++) { - occ_mat[iat][l][0][0].c[mm] = this->uom_array[eff_pot_pw_index[iat] + mm]; + occ_mat[iat][l][0][0].c[mm] = this->uom_array[pot_uterm_pw_index[iat] + mm]; if (this->nspin == 2) { - occ_mat[iat][l][0][1].c[mm] = this->uom_array[half_size + eff_pot_pw_index[iat] + mm]; + occ_mat[iat][l][0][1].c[mm] = this->uom_array[half_size + pot_uterm_pw_index[iat] + mm]; } } } diff --git a/source/source_pw/module_pwdft/dftu_base.h b/source/source_pw/module_pwdft/dftu_base.h index 54aed4ec15..29561e1235 100644 --- a/source/source_pw/module_pwdft/dftu_base.h +++ b/source/source_pw/module_pwdft/dftu_base.h @@ -78,17 +78,17 @@ class Plus_U_Base /// get effective potential pointer for the given spin channel (PW basis) /// - /// nspin=1: isk is ignored, returns &eff_pot_pw[0] + /// nspin=1: isk is ignored, returns &pot_uterm_pw[0] /// nspin=2: isk selects spin-up (0) or spin-down (1) half of the /// split layout [all_up | all_dn] - /// nspin=4: isk is ignored, returns &eff_pot_pw[0] (all Pauli blocks) - const std::complex* get_eff_pot_pw_spin(const int isk) const + /// nspin=4: isk is ignored, returns &pot_uterm_pw[0] (all Pauli blocks) + const std::complex* get_pot_uterm_pw_spin(const int isk) const { if (nspin == 2 && isk == 1) { - return eff_pot_pw.data() + eff_pot_pw.size() / 2; + return pot_uterm_pw.data() + pot_uterm_pw.size() / 2; } - return eff_pot_pw.data(); + return pot_uterm_pw.data(); } /// get size of effective potential for a single spin channel (PW basis) @@ -96,23 +96,23 @@ class Plus_U_Base /// nspin=1: full array size /// nspin=2: half of the total (one spin channel in split layout) /// nspin=4: full array size (all Pauli blocks are packed together) - int get_size_eff_pot_pw_spin() const + int get_size_pot_uterm_pw_spin() const { - return (nspin == 2) ? static_cast(eff_pot_pw.size() / 2) - : static_cast(eff_pot_pw.size()); + return (nspin == 2) ? static_cast(pot_uterm_pw.size() / 2) + : static_cast(pot_uterm_pw.size()); } /// get effective potential matrix for PW base (per-atom, raw index) - /// @deprecated Use get_eff_pot_pw_spin() for nspin-aware access. - [[deprecated("Use get_eff_pot_pw_spin() for nspin-aware access")]] - const std::complex* get_eff_pot_pw(const int iat) const + /// @deprecated Use get_pot_uterm_pw_spin() for nspin-aware access. + [[deprecated("Use get_pot_uterm_pw_spin() for nspin-aware access")]] + const std::complex* get_pot_uterm_pw(const int iat) const { - return &(eff_pot_pw[eff_pot_pw_index[iat]]); + return &(pot_uterm_pw[pot_uterm_pw_index[iat]]); } - int get_size_eff_pot_pw() const + int get_size_pot_uterm_pw() const { - return eff_pot_pw.size(); + return pot_uterm_pw.size(); } // dftu can be calculated only after occ_mat has been initialized @@ -197,12 +197,12 @@ class Plus_U_Base /// copy occ_mat to uom_array for mixing (nspin-aware split layout) void sync_occ_to_uom(const UnitCell& cell); - /// compute effective potential VU and DFT+U energy from occ_mat + /// compute effective potential pot_onsite and DFT+U energy from occ_mat /// (assumes occ_mat has already been reduced across k-pools) void compute_eff_pot_and_energy(const UnitCell& cell); - std::vector> eff_pot_pw; - std::vector eff_pot_pw_index; + std::vector> pot_uterm_pw; + std::vector pot_uterm_pw_index; std::vector uom_array; std::vector uom_save; diff --git a/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp b/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp index eadb24e19f..35fb8922c0 100644 --- a/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp @@ -9,7 +9,7 @@ /// calculate occupation matrix for DFT+U (PW basis) /// /// nspin=1 (npol=1): single spin channel; occ_mat[iat][l][n][0] only; -/// eff_pot_pw has one block of tlp1^2 per atom. +/// pot_uterm_pw has one block of tlp1^2 per atom. /// /// nspin=2 (npol=1): two spin channels stored separately: /// occ_mat[iat][l][n][0] = spin-up, occ_mat[iat][l][n][1] = spin-down; @@ -102,10 +102,10 @@ void Plus_U_Base::reduce_occ_mat(const UnitCell& cell) /// copy occ_mat to uom_array for mixing. /// /// Layout: -/// nspin=1: uom_array[eff_pot_pw_index[iat] + mm] = occ_mat[...][0][0] +/// nspin=1: uom_array[pot_uterm_pw_index[iat] + mm] = occ_mat[...][0][0] /// nspin=2: split layout [all_up | all_dn], each atom's spin-up in the /// first half and spin-down in the second half, both indexed by -/// eff_pot_pw_index[iat] +/// pot_uterm_pw_index[iat] /// nspin=4: not used here (uom_array mixing only covers nspin=1/2 in the /// current code path; the nspin=4 branch is a no-op) void Plus_U_Base::sync_occ_to_uom(const UnitCell& cell) @@ -126,7 +126,7 @@ void Plus_U_Base::sync_occ_to_uom(const UnitCell& cell) for(int mm = 0; mm < size; mm++) { - this->uom_array[eff_pot_pw_index[iat] + mm] = + this->uom_array[pot_uterm_pw_index[iat] + mm] = this->occ_mat[iat][target_l][0][0].c[mm]; } if(this->nspin == 2) @@ -134,21 +134,21 @@ void Plus_U_Base::sync_occ_to_uom(const UnitCell& cell) const int half_size = this->uom_array.size() / 2; for(int mm = 0; mm < size; mm++) { - this->uom_array[half_size + eff_pot_pw_index[iat] + mm] = + this->uom_array[half_size + pot_uterm_pw_index[iat] + mm] = this->occ_mat[iat][target_l][0][1].c[mm]; } } } } -/// compute effective potential VU and DFT+U energy from occ_mat. +/// compute effective potential pot_onsite and DFT+U energy from occ_mat. /// /// Preconditions: /// - occ_mat has been accumulated from psi and reduced across k-pools /// (cal_occ_pw calls this after the reduce + mixing steps). /// /// Outputs: -/// - eff_pot_pw: VU = U * (diag*delta - occ) written per atom +/// - pot_uterm_pw: pot_onsite = U * (diag*delta - occ) written per atom /// nspin=4: 4 Pauli blocks per atom, then transformed to spin basis /// nspin=1: single channel /// nspin=2: two channels in split layout [all_up | all_dn] @@ -158,7 +158,7 @@ void Plus_U_Base::compute_eff_pot_and_energy(const UnitCell& cell) this->energy_u = 0.0; const double weight_eu = (this->nspin == 1) ? 1.0 : (this->nspin == 2) ? 0.5 : 0.25; const double diag_coeff = (this->nspin == 4) ? 1.0 : 0.5; - // calculate VU and energy (occ_mat already reduced above) + // calculate pot_onsite and energy (occ_mat already reduced above) for(int iat = 0; iat < cell.nat; iat++) { const int it = cell.iat2it[iat]; @@ -171,35 +171,35 @@ void Plus_U_Base::compute_eff_pot_and_energy(const UnitCell& cell) //update effective potential const double u_value = this->u_current[it]; - std::complex* vu_iat = &(this->eff_pot_pw[this->eff_pot_pw_index[iat]]); + std::complex* pot_onsite_iat = &(this->pot_uterm_pw[this->pot_uterm_pw_index[iat]]); const int m_size = 2 * target_l + 1; if(this->nspin == 4) { - // VU is stored as 4 contiguous Pauli blocks per atom: + // pot_onsite is stored as 4 contiguous Pauli blocks per atom: // is=0: charge channel (identity), Hubbard U contributes the // diagonal term diag_coeff*delta(m1,m2) // is=1,2,3: spin channels (sigma_x/y/z), no U diagonal term // The occupation matrix occ_mat[...][0][0].c packs all 4 blocks // contiguously, each of size m_size*m_size. - this->energy_u += dftu_pw::compute_vu_spinor( - vu_iat, + this->energy_u += dftu_pw::compute_pot_onsite_spinor( + pot_onsite_iat, this->occ_mat[iat][target_l][0][0].c, u_value, diag_coeff, weight_eu, m_size); } else // nspin=1 or nspin=2 { // spin-up channel - this->energy_u += dftu_pw::compute_vu_scalar( - vu_iat, + this->energy_u += dftu_pw::compute_pot_onsite_scalar( + pot_onsite_iat, this->occ_mat[iat][target_l][0][0].c, u_value, diag_coeff, weight_eu, m_size); // spin-down channel for nspin=2 if(this->nspin == 2) { - std::complex* vu_iat1 = &(this->eff_pot_pw[this->eff_pot_pw.size()/2 + this->eff_pot_pw_index[iat]]); - this->energy_u += dftu_pw::compute_vu_scalar( - vu_iat1, + std::complex* pot_onsite_iat1 = &(this->pot_uterm_pw[this->pot_uterm_pw.size()/2 + this->pot_uterm_pw_index[iat]]); + this->energy_u += dftu_pw::compute_pot_onsite_scalar( + pot_onsite_iat1, this->occ_mat[iat][target_l][0][1].c, u_value, diag_coeff, weight_eu, m_size); } diff --git a/source/source_pw/module_pwdft/dftu_tools_pw.cpp b/source/source_pw/module_pwdft/dftu_tools_pw.cpp index 5cc4a5f2e5..036d2d8625 100644 --- a/source/source_pw/module_pwdft/dftu_tools_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_tools_pw.cpp @@ -2,7 +2,7 @@ namespace dftu_pw { -void pauli_to_spin_basis(std::complex* vu, int m_size) +void pauli_to_spin_basis(std::complex* pot_onsite, int m_size) { const int size = m_size * m_size; for (int m1 = 0; m1 < m_size; m1++) @@ -14,21 +14,21 @@ void pauli_to_spin_basis(std::complex* vu, int m_size) index[1] = m1 * m_size + m2 + size; index[2] = m1 * m_size + m2 + size * 2; index[3] = m1 * m_size + m2 + size * 3; - std::complex vu_tmp[4]; + std::complex pot_onsite_tmp[4]; for (int i = 0; i < 4; i++) { - vu_tmp[i] = vu[index[i]]; + pot_onsite_tmp[i] = pot_onsite[index[i]]; } - vu[index[0]] = 0.5 * (vu_tmp[0] + vu_tmp[3]); - vu[index[3]] = 0.5 * (vu_tmp[0] - vu_tmp[3]); - vu[index[1]] = 0.5 * (vu_tmp[1] + std::complex(0.0, 1.0) * vu_tmp[2]); - vu[index[2]] = 0.5 * (vu_tmp[1] - std::complex(0.0, 1.0) * vu_tmp[2]); + pot_onsite[index[0]] = 0.5 * (pot_onsite_tmp[0] + pot_onsite_tmp[3]); + pot_onsite[index[3]] = 0.5 * (pot_onsite_tmp[0] - pot_onsite_tmp[3]); + pot_onsite[index[1]] = 0.5 * (pot_onsite_tmp[1] + std::complex(0.0, 1.0) * pot_onsite_tmp[2]); + pot_onsite[index[2]] = 0.5 * (pot_onsite_tmp[1] - std::complex(0.0, 1.0) * pot_onsite_tmp[2]); } } } -double compute_vu_spinor( - std::complex* vu, +double compute_pot_onsite_spinor( + std::complex* pot_onsite, const double* occ, double u_value, double diag_coeff, @@ -45,7 +45,7 @@ double compute_vu_spinor( { for (int m2 = 0; m2 < m_size; m2++) { - vu[start + m1 * m_size + m2] = u_value * + pot_onsite[start + m1 * m_size + m2] = u_value * (diag * (m1 == m2) - occ[start + m2 * m_size + m1]); energy_u += u_value * weight_eu * occ[start + m2 * m_size + m1] @@ -53,12 +53,12 @@ double compute_vu_spinor( } } } - pauli_to_spin_basis(vu, m_size); + pauli_to_spin_basis(pot_onsite, m_size); return energy_u; } -double compute_vu_scalar( - std::complex* vu, +double compute_pot_onsite_scalar( + std::complex* pot_onsite, const double* occ, double u_value, double diag_coeff, @@ -70,7 +70,7 @@ double compute_vu_scalar( { for (int m2 = 0; m2 < m_size; m2++) { - vu[m1 * m_size + m2] = u_value * + pot_onsite[m1 * m_size + m2] = u_value * (diag_coeff * (m1 == m2) - occ[m2 * m_size + m1]); energy_u += u_value * weight_eu * occ[m2 * m_size + m1] diff --git a/source/source_pw/module_pwdft/dftu_tools_pw.h b/source/source_pw/module_pwdft/dftu_tools_pw.h index 738c0eda37..188a5127ce 100644 --- a/source/source_pw/module_pwdft/dftu_tools_pw.h +++ b/source/source_pw/module_pwdft/dftu_tools_pw.h @@ -9,44 +9,44 @@ /// These functions are pure (no access to Plus_U_Base members) so they can be /// unit-tested directly by including this header. The member functions in /// dftu_pw.cpp call them after computing per-atom offsets and fetching the -/// relevant member state (occ_mat, eff_pot_pw, u_current, etc.). +/// relevant member state (occ_mat, pot_uterm_pw, u_current, etc.). namespace dftu_pw { -/// transform VU from Pauli basis to spin basis (in-place, nspin==4 only). +/// transform pot_onsite from Pauli basis to spin basis (in-place, nspin==4 only). /// -/// vu points to the per-atom VU block of size 4 * m_size * m_size, storing +/// pot_onsite points to the per-atom pot_onsite block of size 4 * m_size * m_size, storing /// 4 contiguous Pauli blocks (is=0 charge, is=1 sigma_x, is=2 sigma_y, /// is=3 sigma_z). After the transform, the same memory holds the spin /// representation: -/// vu[0] <- 0.5 * (vu_pauli[0] + vu_pauli[3]) -/// vu[3*size] <- 0.5 * (vu_pauli[0] - vu_pauli[3]) -/// vu[size] <- 0.5 * (vu_pauli[1] + i * vu_pauli[2]) -/// vu[2*size] <- 0.5 * (vu_pauli[1] - i * vu_pauli[2]) -void pauli_to_spin_basis(std::complex* vu, int m_size); +/// pot_onsite[0] <- 0.5 * (pot_onsite_pauli[0] + pot_onsite_pauli[3]) +/// pot_onsite[3*size] <- 0.5 * (pot_onsite_pauli[0] - pot_onsite_pauli[3]) +/// pot_onsite[size] <- 0.5 * (pot_onsite_pauli[1] + i * pot_onsite_pauli[2]) +/// pot_onsite[2*size] <- 0.5 * (pot_onsite_pauli[1] - i * pot_onsite_pauli[2]) +void pauli_to_spin_basis(std::complex* pot_onsite, int m_size); -/// compute VU and energy contribution for one atom (nspin==4, spinor). +/// compute pot_onsite and energy contribution for one atom (nspin==4, spinor). /// -/// Writes 4 Pauli blocks of VU into vu (size 4 * m_size * m_size) and +/// Writes 4 Pauli blocks of pot_onsite into pot_onsite (size 4 * m_size * m_size) and /// returns the energy_u increment. Internally calls pauli_to_spin_basis -/// to convert vu to spin basis in-place. +/// to convert pot_onsite to spin basis in-place. /// -/// vu: pointer to eff_pot_pw[eff_pot_pw_index[iat]] +/// pot_onsite: pointer to pot_uterm_pw[pot_uterm_pw_index[iat]] /// occ: pointer to occ_mat[iat][target_l][0][0].c (4 Pauli blocks packed) -double compute_vu_spinor( - std::complex* vu, +double compute_pot_onsite_spinor( + std::complex* pot_onsite, const double* occ, double u_value, double diag_coeff, double weight_eu, int m_size); -/// compute VU and energy contribution for one atom, one spin channel +/// compute pot_onsite and energy contribution for one atom, one spin channel /// (nspin==1 or nspin==2). Returns the energy_u increment. /// -/// vu: pointer to the spin channel's VU block (size m_size * m_size) +/// pot_onsite: pointer to the spin channel's pot_onsite block (size m_size * m_size) /// occ: pointer to occ_mat[iat][target_l][0][is].c for this channel -double compute_vu_scalar( - std::complex* vu, +double compute_pot_onsite_scalar( + std::complex* pot_onsite, const double* occ, double u_value, double diag_coeff, diff --git a/source/source_pw/module_pwdft/kernels/cuda/force_op.cu b/source/source_pw/module_pwdft/kernels/cuda/force_op.cu index cdcd477e82..eb633ec5a1 100644 --- a/source/source_pw/module_pwdft/kernels/cuda/force_op.cu +++ b/source/source_pw/module_pwdft/kernels/cuda/force_op.cu @@ -328,7 +328,7 @@ __global__ void cal_force_onsite(int wg_nc, const int* atom_na, int tpiba, const FPTYPE* d_wg, - const thrust::complex* vu, + const thrust::complex* pot_onsite, const int* orbital_corr, const thrust::complex* becp, const thrust::complex* dbecp, @@ -349,7 +349,7 @@ __global__ void cal_force_onsite(int wg_nc, { iat += atom_na[ii]; sum += atom_na[ii] * atom_nh[ii]; - vu += npol * npol * tlp1_2 * atom_na[ii]; + pot_onsite += npol * npol * tlp1_2 * atom_na[ii]; } const int ib2 = ib * npol; @@ -371,7 +371,7 @@ __global__ void cal_force_onsite(int wg_nc, FPTYPE tmp = 0; if (npol == 2) { - thrust::complex ps[4] = {vu[mm], vu[mm + tlp1_2], vu[mm + 2 * tlp1_2], vu[mm + 3 * tlp1_2]}; + thrust::complex ps[4] = {pot_onsite[mm], pot_onsite[mm + tlp1_2], pot_onsite[mm + 2 * tlp1_2], pot_onsite[mm + 3 * tlp1_2]}; const thrust::complex dbb0 = conj(dbecp[inkb0]) * becp[inkb2]; const thrust::complex dbb1 = conj(dbecp[inkb0]) * becp[inkb2 + nkb]; const thrust::complex dbb2 = conj(dbecp[inkb0 + nkb]) * becp[inkb2]; @@ -380,14 +380,14 @@ __global__ void cal_force_onsite(int wg_nc, } else { - tmp = -fac * (vu[mm] * conj(dbecp[inkb0]) * becp[inkb2]).real(); + tmp = -fac * (pot_onsite[mm] * conj(dbecp[inkb0]) * becp[inkb2]).real(); } atomicAdd(force + iat * forcenl_nc + ipol, tmp); } } ++iat; sum += nprojs; - vu += npol * npol * tlp1_2; + pot_onsite += npol * npol * tlp1_2; } } @@ -482,7 +482,7 @@ void cal_force_nl_op::operator()(const base_dev const int* atom_na, const FPTYPE& tpiba, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, @@ -501,7 +501,7 @@ void cal_force_nl_op::operator()(const base_dev atom_na, tpiba, d_wg, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), orbital_corr, reinterpret_cast*>(becp), reinterpret_cast*>(dbecp), @@ -520,7 +520,7 @@ void cal_force_nl_op::operator()(const base_dev atom_na, tpiba, d_wg, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), orbital_corr, reinterpret_cast*>(becp), reinterpret_cast*>(dbecp), diff --git a/source/source_pw/module_pwdft/kernels/cuda/onsite_op.cu b/source/source_pw/module_pwdft/kernels/cuda/onsite_op.cu index 0c3f0a181a..51aa8f2216 100644 --- a/source/source_pw/module_pwdft/kernels/cuda/onsite_op.cu +++ b/source/source_pw/module_pwdft/kernels/cuda/onsite_op.cu @@ -50,9 +50,9 @@ __global__ void onsite_op(const int npm, const int* orb_l_iat, const int* ip_iat, const int* ip_m, - const int* vu_begin_iat, + const int* pot_onsite_begin_iat, const int tnp, - const thrust::complex* vu, + const thrust::complex* pot_onsite, thrust::complex* ps, const thrust::complex* becp) { @@ -62,7 +62,7 @@ __global__ void onsite_op(const int npm, { const int nbands = npm / npol; int iat = ip_iat[ip]; - const thrust::complex* vu_iat = vu + vu_begin_iat[iat]; + const thrust::complex* pot_onsite_iat = pot_onsite + pot_onsite_begin_iat[iat]; int orb_l = orb_l_iat[iat]; int tlp1 = 2 * orb_l + 1; int tlp1_2 = tlp1 * tlp1; @@ -80,9 +80,9 @@ __global__ void onsite_op(const int npm, const int becpind = ib2 * tnp + ip2; int m2 = ip_m[ip2]; const int index_mm = m1 * tlp1 + m2; - ps[psind] += vu_iat[index_mm] * becp[becpind] + vu_iat[index_mm + tlp1_2 * 2] * becp[becpind + tnp]; - ps[psind + 1] += vu_iat[index_mm + tlp1_2 * 1] * becp[becpind] - + vu_iat[index_mm + tlp1_2 * 3] * becp[becpind + tnp]; + ps[psind] += pot_onsite_iat[index_mm] * becp[becpind] + pot_onsite_iat[index_mm + tlp1_2 * 2] * becp[becpind + tnp]; + ps[psind + 1] += pot_onsite_iat[index_mm + tlp1_2 * 1] * becp[becpind] + + pot_onsite_iat[index_mm + tlp1_2 * 3] * becp[becpind + tnp]; } } } @@ -96,7 +96,7 @@ __global__ void onsite_op(const int npm, const int becpind = ib * tnp + ip2; int m2 = ip_m[ip2]; const int index_mm = m1 * tlp1 + m2; - ps[psind] += vu_iat[index_mm] * becp[becpind]; + ps[psind] += pot_onsite_iat[index_mm] * becp[becpind]; } } } @@ -134,9 +134,9 @@ void hamilt::onsite_ps_op::operator()(const bas const int* orb_l_iat, const int* ip_iat, const int* ip_m, - const int* vu_begin_iat, + const int* pot_onsite_begin_iat, const int& tnp, - const std::complex* vu, + const std::complex* pot_onsite, std::complex* ps, const std::complex* becp) { @@ -148,9 +148,9 @@ void hamilt::onsite_ps_op::operator()(const bas orb_l_iat, ip_iat, ip_m, - vu_begin_iat, + pot_onsite_begin_iat, tnp, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), reinterpret_cast*>(ps), // array of data reinterpret_cast*>(becp)); // array of data diff --git a/source/source_pw/module_pwdft/kernels/cuda/stress_op.cu b/source/source_pw/module_pwdft/kernels/cuda/stress_op.cu index fcb6190e7c..ea73f8eb28 100644 --- a/source/source_pw/module_pwdft/kernels/cuda/stress_op.cu +++ b/source/source_pw/module_pwdft/kernels/cuda/stress_op.cu @@ -936,7 +936,7 @@ __global__ void cal_stress_onsite( const int *atom_nh, const int *atom_na, const FPTYPE *d_wg, - const thrust::complex *vu, + const thrust::complex *pot_onsite, const int* orbital_corr, const thrust::complex *becp, const thrust::complex *dbecp, @@ -955,7 +955,7 @@ __global__ void cal_stress_onsite( for (int ii = 0; ii < it; ii++) { iat += atom_na[ii]; sum += atom_na[ii] * atom_nh[ii]; - vu += npol * npol * tlp1_2 * atom_na[ii]; + pot_onsite += npol * npol * tlp1_2 * atom_na[ii]; } FPTYPE stress_var = 0; @@ -973,7 +973,7 @@ __global__ void cal_stress_onsite( const int inkb2 = sum + ip2 + ib2 * nkb; if (npol == 2) { - thrust::complex ps[4] = {vu[mm], vu[mm + tlp1_2], vu[mm + 2 * tlp1_2], vu[mm + 3 * tlp1_2]}; + thrust::complex ps[4] = {pot_onsite[mm], pot_onsite[mm + tlp1_2], pot_onsite[mm + 2 * tlp1_2], pot_onsite[mm + 3 * tlp1_2]}; const thrust::complex dbb0 = conj(dbecp[inkb1]) * becp[inkb2]; const thrust::complex dbb1 = conj(dbecp[inkb1]) * becp[inkb2 + nkb]; const thrust::complex dbb2 = conj(dbecp[inkb1 + nkb]) * becp[inkb2]; @@ -982,12 +982,12 @@ __global__ void cal_stress_onsite( } else { - stress_var -= fac * (vu[mm] * (conj(dbecp[inkb1]) * becp[inkb2])).real(); + stress_var -= fac * (pot_onsite[mm] * (conj(dbecp[inkb1]) * becp[inkb2])).real(); } } ++iat; sum+=nprojs; - vu += npol * npol * tlp1_2; + pot_onsite += npol * npol * tlp1_2; }//ia __syncwarp(); warp_reduce(stress_var); @@ -1073,7 +1073,7 @@ void cal_stress_nl_op::operator()(const base_de const int* atom_nh, const int* atom_na, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, @@ -1089,7 +1089,7 @@ void cal_stress_nl_op::operator()(const base_de atom_nh, atom_na, d_wg, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), orbital_corr, reinterpret_cast*>(becp), reinterpret_cast*>(dbecp), @@ -1105,7 +1105,7 @@ void cal_stress_nl_op::operator()(const base_de atom_nh, atom_na, d_wg, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), orbital_corr, reinterpret_cast*>(becp), reinterpret_cast*>(dbecp), diff --git a/source/source_pw/module_pwdft/kernels/force_op.cpp b/source/source_pw/module_pwdft/kernels/force_op.cpp index 35483375c9..e132fdb1cb 100644 --- a/source/source_pw/module_pwdft/kernels/force_op.cpp +++ b/source/source_pw/module_pwdft/kernels/force_op.cpp @@ -297,7 +297,7 @@ struct cal_force_nl_op const int* atom_na, const FPTYPE& tpiba, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, @@ -340,7 +340,7 @@ struct cal_force_nl_op std::complex ps[4]; for(int i = 0; i < 4; i++) { - ps[i] = vu[(i * tlp1_2 + m * tlp1 + m2)]; + ps[i] = pot_onsite[(i * tlp1_2 + m * tlp1 + m2)]; } for (int iforce = 0; iforce < 3; iforce++) @@ -361,7 +361,7 @@ struct cal_force_nl_op { const int index0 = iforce * nbands * npol * nkb + ib2 * nkb + inkb; const int index1 = ib2 * nkb + jnkb; - local_force[iforce] -= fac * (vu[(m * tlp1 + m2)] * conj(dbecp[index0]) * becp[index1]).real(); + local_force[iforce] -= fac * (pot_onsite[(m * tlp1 + m2)] * conj(dbecp[index0]) * becp[index1]).real(); } } } @@ -371,7 +371,7 @@ struct cal_force_nl_op force[iat * forcenl_nc + iforce] += local_force[iforce]; } } - vu += npol * npol * tlp1_2;// step for vu + pot_onsite += npol * npol * tlp1_2;// step for pot_onsite } // end ia iat0 += atom_na[it]; sum0 += atom_na[it] * nproj; diff --git a/source/source_pw/module_pwdft/kernels/force_op.h b/source/source_pw/module_pwdft/kernels/force_op.h index b97c6688a6..5ce771fedc 100644 --- a/source/source_pw/module_pwdft/kernels/force_op.h +++ b/source/source_pw/module_pwdft/kernels/force_op.h @@ -125,7 +125,7 @@ struct cal_force_nl_op const int* atom_na, const FPTYPE& tpiba, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, @@ -257,7 +257,7 @@ struct cal_force_nl_op const int* atom_na, const FPTYPE& tpiba, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, diff --git a/source/source_pw/module_pwdft/kernels/onsite_op.cpp b/source/source_pw/module_pwdft/kernels/onsite_op.cpp index 8ac4e8fb84..875f3dc9cd 100644 --- a/source/source_pw/module_pwdft/kernels/onsite_op.cpp +++ b/source/source_pw/module_pwdft/kernels/onsite_op.cpp @@ -61,9 +61,9 @@ struct onsite_ps_op const int* orb_l_iat, const int* ip_iat, const int* ip_m, - const int* vu_begin_iat, + const int* pot_onsite_begin_iat, const int& tnp, - const std::complex* vu, + const std::complex* pot_onsite, std::complex* ps, const std::complex* becp) { @@ -80,7 +80,7 @@ struct onsite_ps_op if(m1 < 0) continue; int ib2 = ib * npol; int iat = ip_iat[ip]; - const std::complex* vu_iat = vu + vu_begin_iat[iat]; + const std::complex* pot_onsite_iat = pot_onsite + pot_onsite_begin_iat[iat]; int orb_l = orb_l_iat[iat]; int tlp1 = 2 * orb_l + 1; int tlp1_2 = tlp1 * tlp1; @@ -92,10 +92,10 @@ struct onsite_ps_op const int becpind = ib2 * tnp + ip2; int m2 = ip_m[ip2]; const int index_mm = m1 * tlp1 + m2; - ps[psind] += vu_iat[index_mm] * becp[becpind] - + vu_iat[index_mm + tlp1_2 * 2] * becp[becpind + tnp]; - ps[psind + 1] += vu_iat[index_mm + tlp1_2 * 1] * becp[becpind] - + vu_iat[index_mm + tlp1_2 * 3] * becp[becpind + tnp]; + ps[psind] += pot_onsite_iat[index_mm] * becp[becpind] + + pot_onsite_iat[index_mm + tlp1_2 * 2] * becp[becpind + tnp]; + ps[psind + 1] += pot_onsite_iat[index_mm + tlp1_2 * 1] * becp[becpind] + + pot_onsite_iat[index_mm + tlp1_2 * 3] * becp[becpind + tnp]; } } // end ip } // end ib @@ -112,7 +112,7 @@ struct onsite_ps_op int m1 = ip_m[ip]; if(m1 < 0) continue; int iat = ip_iat[ip]; - const std::complex* vu_iat = vu + vu_begin_iat[iat]; + const std::complex* pot_onsite_iat = pot_onsite + pot_onsite_begin_iat[iat]; int orb_l = orb_l_iat[iat]; int tlp1 = 2 * orb_l + 1; int ip2_begin = ip - m1; @@ -123,7 +123,7 @@ struct onsite_ps_op const int becpind = ib * tnp + ip2; int m2 = ip_m[ip2]; const int index_mm = m1 * tlp1 + m2; - ps[psind] += vu_iat[index_mm] * becp[becpind]; + ps[psind] += pot_onsite_iat[index_mm] * becp[becpind]; } } // end ip } // end ib diff --git a/source/source_pw/module_pwdft/kernels/onsite_op.h b/source/source_pw/module_pwdft/kernels/onsite_op.h index 83f3790d6b..5ad221ba3f 100644 --- a/source/source_pw/module_pwdft/kernels/onsite_op.h +++ b/source/source_pw/module_pwdft/kernels/onsite_op.h @@ -24,9 +24,9 @@ struct onsite_ps_op { const int* orb_l_iat, const int* ip_iat, const int* ip_m, - const int* vu_begin_iat, + const int* pot_onsite_begin_iat, const int& tnp, - const std::complex* vu, + const std::complex* pot_onsite, std::complex* ps, const std::complex* becp); }; @@ -52,9 +52,9 @@ struct onsite_ps_op { const int* orb_l_iat, const int* ip_iat, const int* ip_m, - const int* vu_begin_iat, + const int* pot_onsite_begin_iat, const int& tnp, - const std::complex* vu, + const std::complex* pot_onsite, std::complex* ps, const std::complex* becp); }; diff --git a/source/source_pw/module_pwdft/kernels/rocm/force_op.hip.cu b/source/source_pw/module_pwdft/kernels/rocm/force_op.hip.cu index cd4edf33ec..64c2a68269 100644 --- a/source/source_pw/module_pwdft/kernels/rocm/force_op.hip.cu +++ b/source/source_pw/module_pwdft/kernels/rocm/force_op.hip.cu @@ -314,7 +314,7 @@ __global__ void cal_force_onsite(int wg_nc, const int* atom_na, int tpiba, const FPTYPE* d_wg, - const thrust::complex* vu, + const thrust::complex* pot_onsite, const int* orbital_corr, const thrust::complex* becp, const thrust::complex* dbecp, @@ -335,7 +335,7 @@ __global__ void cal_force_onsite(int wg_nc, { iat += atom_na[ii]; sum += atom_na[ii] * atom_nh[ii]; - vu += npol * npol * tlp1_2 * atom_na[ii]; + pot_onsite += npol * npol * tlp1_2 * atom_na[ii]; } const int ib2 = ib * npol; @@ -357,7 +357,7 @@ __global__ void cal_force_onsite(int wg_nc, FPTYPE tmp = 0; if (npol == 2) { - thrust::complex ps[4] = {vu[mm], vu[mm + tlp1_2], vu[mm + 2 * tlp1_2], vu[mm + 3 * tlp1_2]}; + thrust::complex ps[4] = {pot_onsite[mm], pot_onsite[mm + tlp1_2], pot_onsite[mm + 2 * tlp1_2], pot_onsite[mm + 3 * tlp1_2]}; const thrust::complex dbb0 = conj(dbecp[inkb0]) * becp[inkb2]; const thrust::complex dbb1 = conj(dbecp[inkb0]) * becp[inkb2 + nkb]; const thrust::complex dbb2 = conj(dbecp[inkb0 + nkb]) * becp[inkb2]; @@ -366,14 +366,14 @@ __global__ void cal_force_onsite(int wg_nc, } else { - tmp = -fac * (vu[mm] * conj(dbecp[inkb0]) * becp[inkb2]).real(); + tmp = -fac * (pot_onsite[mm] * conj(dbecp[inkb0]) * becp[inkb2]).real(); } atomicAdd(force + iat * forcenl_nc + ipol, tmp); } } ++iat; sum += nprojs; - vu += npol * npol * tlp1_2; + pot_onsite += npol * npol * tlp1_2; } } @@ -468,7 +468,7 @@ void cal_force_nl_op::operator()(const base_dev const int* atom_na, const FPTYPE& tpiba, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, @@ -491,7 +491,7 @@ void cal_force_nl_op::operator()(const base_dev atom_na, tpiba, d_wg, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), orbital_corr, reinterpret_cast*>(becp), reinterpret_cast*>(dbecp), @@ -514,7 +514,7 @@ void cal_force_nl_op::operator()(const base_dev atom_na, tpiba, d_wg, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), orbital_corr, reinterpret_cast*>(becp), reinterpret_cast*>(dbecp), diff --git a/source/source_pw/module_pwdft/kernels/rocm/onsite_op.hip.cu b/source/source_pw/module_pwdft/kernels/rocm/onsite_op.hip.cu index 71fdf82c50..3c1e9e6922 100644 --- a/source/source_pw/module_pwdft/kernels/rocm/onsite_op.hip.cu +++ b/source/source_pw/module_pwdft/kernels/rocm/onsite_op.hip.cu @@ -50,9 +50,9 @@ __global__ void onsite_op(const int npm, const int* orb_l_iat, const int* ip_iat, const int* ip_m, - const int* vu_begin_iat, + const int* pot_onsite_begin_iat, const int tnp, - const thrust::complex* vu, + const thrust::complex* pot_onsite, thrust::complex* ps, const thrust::complex* becp) { @@ -62,7 +62,7 @@ __global__ void onsite_op(const int npm, { const int nbands = npm / npol; int iat = ip_iat[ip]; - const thrust::complex* vu_iat = vu + vu_begin_iat[iat]; + const thrust::complex* pot_onsite_iat = pot_onsite + pot_onsite_begin_iat[iat]; int orb_l = orb_l_iat[iat]; int tlp1 = 2 * orb_l + 1; int tlp1_2 = tlp1 * tlp1; @@ -80,9 +80,9 @@ __global__ void onsite_op(const int npm, const int becpind = ib2 * tnp + ip2; int m2 = ip_m[ip2]; const int index_mm = m1 * tlp1 + m2; - ps[psind] += vu_iat[index_mm] * becp[becpind] + vu_iat[index_mm + tlp1_2 * 2] * becp[becpind + tnp]; - ps[psind + 1] += vu_iat[index_mm + tlp1_2 * 1] * becp[becpind] - + vu_iat[index_mm + tlp1_2 * 3] * becp[becpind + tnp]; + ps[psind] += pot_onsite_iat[index_mm] * becp[becpind] + pot_onsite_iat[index_mm + tlp1_2 * 2] * becp[becpind + tnp]; + ps[psind + 1] += pot_onsite_iat[index_mm + tlp1_2 * 1] * becp[becpind] + + pot_onsite_iat[index_mm + tlp1_2 * 3] * becp[becpind + tnp]; } } } @@ -96,7 +96,7 @@ __global__ void onsite_op(const int npm, const int becpind = ib * tnp + ip2; int m2 = ip_m[ip2]; const int index_mm = m1 * tlp1 + m2; - ps[psind] += vu_iat[index_mm] * becp[becpind]; + ps[psind] += pot_onsite_iat[index_mm] * becp[becpind]; } } } @@ -134,9 +134,9 @@ void hamilt::onsite_ps_op::operator()(const bas const int* orb_l_iat, const int* ip_iat, const int* ip_m, - const int* vu_begin_iat, + const int* pot_onsite_begin_iat, const int& tnp, - const std::complex* vu, + const std::complex* pot_onsite, std::complex* ps, const std::complex* becp) { @@ -148,9 +148,9 @@ void hamilt::onsite_ps_op::operator()(const bas orb_l_iat, ip_iat, ip_m, - vu_begin_iat, + pot_onsite_begin_iat, tnp, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), reinterpret_cast*>(ps), // array of data reinterpret_cast*>(becp)); // array of data diff --git a/source/source_pw/module_pwdft/kernels/rocm/stress_op.hip.cu b/source/source_pw/module_pwdft/kernels/rocm/stress_op.hip.cu index 45db4048d8..d5c093cb51 100644 --- a/source/source_pw/module_pwdft/kernels/rocm/stress_op.hip.cu +++ b/source/source_pw/module_pwdft/kernels/rocm/stress_op.hip.cu @@ -925,7 +925,7 @@ __global__ void cal_stress_onsite( const int *atom_nh, const int *atom_na, const FPTYPE *d_wg, - const thrust::complex *vu, + const thrust::complex *pot_onsite, const int* orbital_corr, const thrust::complex *becp, const thrust::complex *dbecp, @@ -944,7 +944,7 @@ __global__ void cal_stress_onsite( for (int ii = 0; ii < it; ii++) { iat += atom_na[ii]; sum += atom_na[ii] * atom_nh[ii]; - vu += npol * npol * tlp1_2 * atom_na[ii]; + pot_onsite += npol * npol * tlp1_2 * atom_na[ii]; } FPTYPE stress_var = 0; @@ -962,7 +962,7 @@ __global__ void cal_stress_onsite( const int inkb2 = sum + ip2 + ib2 * nkb; if (npol == 2) { - thrust::complex ps[4] = {vu[mm], vu[mm + tlp1_2], vu[mm + 2 * tlp1_2], vu[mm + 3 * tlp1_2]}; + thrust::complex ps[4] = {pot_onsite[mm], pot_onsite[mm + tlp1_2], pot_onsite[mm + 2 * tlp1_2], pot_onsite[mm + 3 * tlp1_2]}; const thrust::complex dbb0 = conj(dbecp[inkb1]) * becp[inkb2]; const thrust::complex dbb1 = conj(dbecp[inkb1]) * becp[inkb2 + nkb]; const thrust::complex dbb2 = conj(dbecp[inkb1 + nkb]) * becp[inkb2]; @@ -971,12 +971,12 @@ __global__ void cal_stress_onsite( } else { - stress_var -= fac * (vu[mm] * (conj(dbecp[inkb1]) * becp[inkb2])).real(); + stress_var -= fac * (pot_onsite[mm] * (conj(dbecp[inkb1]) * becp[inkb2])).real(); } } ++iat; sum+=nprojs; - vu += npol * npol * tlp1_2; + pot_onsite += npol * npol * tlp1_2; }//ia __syncwarp(); warp_reduce(stress_var); @@ -1062,7 +1062,7 @@ void cal_stress_nl_op::operator()(const base_de const int* atom_nh, const int* atom_na, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, @@ -1078,7 +1078,7 @@ void cal_stress_nl_op::operator()(const base_de atom_nh, atom_na, d_wg, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), orbital_corr, reinterpret_cast*>(becp), reinterpret_cast*>(dbecp), @@ -1094,7 +1094,7 @@ void cal_stress_nl_op::operator()(const base_de atom_nh, atom_na, d_wg, - reinterpret_cast*>(vu), + reinterpret_cast*>(pot_onsite), orbital_corr, reinterpret_cast*>(becp), reinterpret_cast*>(dbecp), diff --git a/source/source_pw/module_pwdft/kernels/stress_op.cpp b/source/source_pw/module_pwdft/kernels/stress_op.cpp index 09e04f8eac..a6d0612b65 100644 --- a/source/source_pw/module_pwdft/kernels/stress_op.cpp +++ b/source/source_pw/module_pwdft/kernels/stress_op.cpp @@ -255,7 +255,7 @@ struct cal_stress_nl_op const int* atom_nh, const int* atom_na, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, @@ -294,7 +294,7 @@ struct cal_stress_nl_op { const int m2 = ip2 - ip_begin; const int inkb2 = ib2 * nkb + sum + ia * nproj + ip2; - local_stress -= fac * (vu[m1 * tlp1 + m2] * (conj(dbecp[inkb1]) * becp[inkb2])).real(); + local_stress -= fac * (pot_onsite[m1 * tlp1 + m2] * (conj(dbecp[inkb1]) * becp[inkb2])).real(); } } // end ip break; @@ -309,7 +309,7 @@ struct cal_stress_nl_op std::complex ps[4]; for(int i = 0; i < 4; i++) { - ps[i] = vu[(i * tlp1_2 + m1 * tlp1 + m2)]; + ps[i] = pot_onsite[(i * tlp1_2 + m1 * tlp1 + m2)]; } const int inkb2 = ib2 * nkb + sum + ia * nproj + ip2; @@ -325,7 +325,7 @@ struct cal_stress_nl_op break; } }// ib - vu += npol * npol * tlp1_2;// step for vu + pot_onsite += npol * npol * tlp1_2;// step for pot_onsite }// ia sum += atom_na[it] * nproj; } // end it diff --git a/source/source_pw/module_pwdft/kernels/stress_op.h b/source/source_pw/module_pwdft/kernels/stress_op.h index d107431e3d..260053dba6 100644 --- a/source/source_pw/module_pwdft/kernels/stress_op.h +++ b/source/source_pw/module_pwdft/kernels/stress_op.h @@ -132,7 +132,7 @@ struct cal_stress_nl_op const int* atom_nh, const int* atom_na, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, @@ -340,7 +340,7 @@ struct cal_stress_nl_op const int* atom_nh, const int* atom_na, const FPTYPE* d_wg, - const std::complex* vu, + const std::complex* pot_onsite, const int* orbital_corr, const std::complex* becp, const std::complex* dbecp, diff --git a/source/source_pw/module_pwdft/kernels/test/onsite_op_test.cpp b/source/source_pw/module_pwdft/kernels/test/onsite_op_test.cpp index 41d301f8c4..9d42c509ff 100644 --- a/source/source_pw/module_pwdft/kernels/test/onsite_op_test.cpp +++ b/source/source_pw/module_pwdft/kernels/test/onsite_op_test.cpp @@ -173,11 +173,11 @@ TEST_F(OnsitePsDeltaSpinNpol2Test, MultiBand) // For npol=1: // for each ip: // m1 = ip_m[ip], if m1 < 0 continue -// iat = ip_iat[ip], vu_iat = vu + vu_begin_iat[iat] +// iat = ip_iat[ip], pot_onsite_iat = pot_onsite + pot_onsite_begin_iat[iat] // tlp1 = 2*orb_l + 1 // for ip2 in [ip-m1, ip-m1+tlp1): // m2 = ip_m[ip2] -// ps[ip * npm + ib] += vu_iat[m1*tlp1 + m2] * becp[ib * tnp + ip2] +// ps[ip * npm + ib] += pot_onsite_iat[m1*tlp1 + m2] * becp[ib * tnp + ip2] // ===================================================================== class OnsitePsDftuNpol1Test : public ::testing::Test @@ -196,26 +196,26 @@ TEST_F(OnsitePsDftuNpol1Test, SingleBandSingleAtom_DOrbital) std::vector orb_l_iat = {2}; // d-orbital (l=2) std::vector ip_iat = {0, 0, 0, 0, 0}; // all belong to atom 0 std::vector ip_m = {0, 1, 2, 3, 4}; // m indices - std::vector vu_begin_iat = {0}; // VU starts at index 0 + std::vector pot_onsite_begin_iat = {0}; // pot_onsite starts at index 0 - // VU matrix for d-orbital (5x5), row-major - std::vector vu(25, 0.0); - vu[0] = 1.0; // VU[0,0] - vu[6] = 2.0; // VU[1,1] - vu[12] = 3.0; // VU[2,2] + // pot_onsite matrix for d-orbital (5x5), row-major + std::vector pot_onsite(25, 0.0); + pot_onsite[0] = 1.0; // pot_onsite[0,0] + pot_onsite[6] = 2.0; // pot_onsite[1,1] + pot_onsite[12] = 3.0; // pot_onsite[2,2] std::vector becp = {1.0, 0.5, 0.3, 0.2, 0.1}; // 5 projectors std::vector ps(5, 0.0); // tnp * npm = 5 kernel(nullptr, npm, npol, - orb_l_iat.data(), ip_iat.data(), ip_m.data(), vu_begin_iat.data(), - tnp, vu.data(), ps.data(), becp.data()); + orb_l_iat.data(), ip_iat.data(), ip_m.data(), pot_onsite_begin_iat.data(), + tnp, pot_onsite.data(), ps.data(), becp.data()); // For ip=0 (m1=0): ip2 ranges from 0 to 5 - // ps[0] += VU[0,0]*becp[0] + VU[0,1]*becp[1] + ... + // ps[0] += pot_onsite[0,0]*becp[0] + pot_onsite[0,1]*becp[1] + ... // = 1.0*1.0 + 0 + 0 + 0 + 0 = 1.0 // For ip=1 (m1=1): ip2 ranges from 0 to 5 - // ps[1] += VU[1,0]*becp[0] + VU[1,1]*becp[1] + ... + // ps[1] += pot_onsite[1,0]*becp[0] + pot_onsite[1,1]*becp[1] + ... // = 0 + 2.0*0.5 + 0 + 0 + 0 = 1.0 // For ip=2 (m1=2): ps[2] += 3.0*0.3 = 0.9 EXPECT_NEAR(ps[0].real(), 1.0, 1e-15); @@ -225,33 +225,33 @@ TEST_F(OnsitePsDftuNpol1Test, SingleBandSingleAtom_DOrbital) EXPECT_NEAR(ps[4].real(), 0.0, 1e-15); } -TEST_F(OnsitePsDftuNpol1Test, OffDiagonalVU) +TEST_F(OnsitePsDftuNpol1Test, OffDiagonalPotOnsite) { - // Test off-diagonal VU elements + // Test off-diagonal pot_onsite elements const int npm = 1, npol = 1, tnp = 3; // p-orbital std::vector orb_l_iat = {1}; // p-orbital std::vector ip_iat = {0, 0, 0}; std::vector ip_m = {0, 1, 2}; - std::vector vu_begin_iat = {0}; + std::vector pot_onsite_begin_iat = {0}; - // VU with off-diagonal: VU[0,1] = 0.5, VU[1,0] = 0.5 - std::vector vu(9, 0.0); - vu[1] = 0.5; // VU[0,1] - vu[3] = 0.5; // VU[1,0] + // pot_onsite with off-diagonal: pot_onsite[0,1] = 0.5, pot_onsite[1,0] = 0.5 + std::vector pot_onsite(9, 0.0); + pot_onsite[1] = 0.5; // pot_onsite[0,1] + pot_onsite[3] = 0.5; // pot_onsite[1,0] std::vector becp = {1.0, 2.0, 3.0}; std::vector ps(3, 0.0); kernel(nullptr, npm, npol, - orb_l_iat.data(), ip_iat.data(), ip_m.data(), vu_begin_iat.data(), - tnp, vu.data(), ps.data(), becp.data()); + orb_l_iat.data(), ip_iat.data(), ip_m.data(), pot_onsite_begin_iat.data(), + tnp, pot_onsite.data(), ps.data(), becp.data()); // ip=0 (m1=0): ip2 from 0 to 3 - // ps[0] += VU[0,0]*becp[0] + VU[0,1]*becp[1] + VU[0,2]*becp[2] + // ps[0] += pot_onsite[0,0]*becp[0] + pot_onsite[0,1]*becp[1] + pot_onsite[0,2]*becp[2] // = 0*1.0 + 0.5*2.0 + 0*3.0 = 1.0 // ip=1 (m1=1): - // ps[1] += VU[1,0]*becp[0] + VU[1,1]*becp[1] + VU[1,2]*becp[2] + // ps[1] += pot_onsite[1,0]*becp[0] + pot_onsite[1,1]*becp[1] + pot_onsite[1,2]*becp[2] // = 0.5*1.0 + 0*2.0 + 0*3.0 = 0.5 EXPECT_NEAR(ps[0].real(), 1.0, 1e-15); EXPECT_NEAR(ps[1].real(), 0.5, 1e-15); @@ -266,20 +266,20 @@ TEST_F(OnsitePsDftuNpol1Test, NonCorrelatedProjector_MMinus1) std::vector ip_iat = {0, 0, 0, 0}; // First projector is not correlated (m=-1), rest are p-type (m=0,1,2) std::vector ip_m = {-1, 0, 1, 2}; - std::vector vu_begin_iat = {0}; + std::vector pot_onsite_begin_iat = {0}; - std::vector vu(9, 1.0); // all VU = 1.0 + std::vector pot_onsite(9, 1.0); // all pot_onsite = 1.0 std::vector becp = {1.0, 1.0, 1.0, 1.0}; std::vector ps(4, 0.0); kernel(nullptr, npm, npol, - orb_l_iat.data(), ip_iat.data(), ip_m.data(), vu_begin_iat.data(), - tnp, vu.data(), ps.data(), becp.data()); + orb_l_iat.data(), ip_iat.data(), ip_m.data(), pot_onsite_begin_iat.data(), + tnp, pot_onsite.data(), ps.data(), becp.data()); // ip=0: m1=-1, skipped // ip=1,2,3: should have contributions EXPECT_NEAR(ps[0].real(), 0.0, 1e-15); // skipped - EXPECT_NEAR(ps[1].real(), 3.0, 1e-15); // sum of VU[1,*]*becp + EXPECT_NEAR(ps[1].real(), 3.0, 1e-15); // sum of pot_onsite[1,*]*becp EXPECT_NEAR(ps[2].real(), 3.0, 1e-15); EXPECT_NEAR(ps[3].real(), 3.0, 1e-15); } @@ -291,10 +291,10 @@ TEST_F(OnsitePsDftuNpol1Test, MultiBand_DOrbital) std::vector orb_l_iat = {2}; std::vector ip_iat = {0, 0, 0, 0, 0}; std::vector ip_m = {0, 1, 2, 3, 4}; - std::vector vu_begin_iat = {0}; + std::vector pot_onsite_begin_iat = {0}; - std::vector vu(25, 0.0); - vu[0] = 2.0; // VU[0,0] + std::vector pot_onsite(25, 0.0); + pot_onsite[0] = 2.0; // pot_onsite[0,0] // Band 0: becp[0..4], Band 1: becp[5..9] std::vector becp = { @@ -304,11 +304,11 @@ TEST_F(OnsitePsDftuNpol1Test, MultiBand_DOrbital) std::vector ps(10, 0.0); // tnp * npm = 10 kernel(nullptr, npm, npol, - orb_l_iat.data(), ip_iat.data(), ip_m.data(), vu_begin_iat.data(), - tnp, vu.data(), ps.data(), becp.data()); + orb_l_iat.data(), ip_iat.data(), ip_m.data(), pot_onsite_begin_iat.data(), + tnp, pot_onsite.data(), ps.data(), becp.data()); - // Band 0: ps[0] += VU[0,0] * becp[0] = 2.0 * 1.0 = 2.0 - // Band 1: ps[5] += VU[0,0] * becp[5] = 2.0 * 0.0 = 0.0 + // Band 0: ps[0] += pot_onsite[0,0] * becp[0] = 2.0 * 1.0 = 2.0 + // Band 1: ps[5] += pot_onsite[0,0] * becp[5] = 2.0 * 0.0 = 0.0 // Wait, becp indexing: becp[ib * tnp + ip2] // For band 1, ib=1: becp[1*5 + 0] = becp[5] = 0.0 EXPECT_NEAR(ps[0].real(), 2.0, 1e-15); @@ -319,10 +319,10 @@ TEST_F(OnsitePsDftuNpol1Test, MultiBand_DOrbital) // 4. DFT+U kernel (npol=2 branch) // // For npol=2: -// ps[ip * npm + ib2] += vu_iat[index_mm] * becp[ib2*tnp + ip2] -// + vu_iat[index_mm + 2*tlp1^2] * becp[ib2*tnp + ip2 + tnp] -// ps[ip * npm + ib2+1] += vu_iat[index_mm + tlp1^2] * becp[ib2*tnp + ip2] -// + vu_iat[index_mm + 3*tlp1^2] * becp[ib2*tnp + ip2 + tnp] +// ps[ip * npm + ib2] += pot_onsite_iat[index_mm] * becp[ib2*tnp + ip2] +// + pot_onsite_iat[index_mm + 2*tlp1^2] * becp[ib2*tnp + ip2 + tnp] +// ps[ip * npm + ib2+1] += pot_onsite_iat[index_mm + tlp1^2] * becp[ib2*tnp + ip2] +// + pot_onsite_iat[index_mm + 3*tlp1^2] * becp[ib2*tnp + ip2 + tnp] // // where index_mm = m1 * tlp1 + m2 // ===================================================================== @@ -343,14 +343,14 @@ TEST_F(OnsitePsDftuNpol2Test, SingleBandSingleAtom_Porbital) std::vector orb_l_iat = {1}; // p-orbital std::vector ip_iat = {0, 0, 0}; std::vector ip_m = {0, 1, 2}; - std::vector vu_begin_iat = {0}; + std::vector pot_onsite_begin_iat = {0}; - // VU: 4 blocks of 3x3 = 36 elements - std::vector vu(36, 0.0); - // Block 0 (Pauli I): VU[0,0] = 2.0 - vu[0] = 2.0; - // Block 1 (Pauli X): VU[0,0] = 1.0 - vu[9] = 1.0; // tlp1^2 = 9 + // pot_onsite: 4 blocks of 3x3 = 36 elements + std::vector pot_onsite(36, 0.0); + // Block 0 (Pauli I): pot_onsite[0,0] = 2.0 + pot_onsite[0] = 2.0; + // Block 1 (Pauli X): pot_onsite[0,0] = 1.0 + pot_onsite[9] = 1.0; // tlp1^2 = 9 // becp: 2 rows (spin up/down) x 3 projectors std::vector becp = { @@ -360,12 +360,12 @@ TEST_F(OnsitePsDftuNpol2Test, SingleBandSingleAtom_Porbital) std::vector ps = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // tnp * npm = 6 kernel(nullptr, npm, npol, - orb_l_iat.data(), ip_iat.data(), ip_m.data(), vu_begin_iat.data(), - tnp, vu.data(), ps.data(), becp.data()); + orb_l_iat.data(), ip_iat.data(), ip_m.data(), pot_onsite_begin_iat.data(), + tnp, pot_onsite.data(), ps.data(), becp.data()); // For ip=0 (m1=0): ip2 from 0 to 3 - // ps[0] += vu[0]*becp[0] + vu[18]*becp[3] = 2.0*1.0 + 0*0.0 = 2.0 - // ps[1] += vu[9]*becp[0] + vu[27]*becp[3] = 1.0*1.0 + 0*0.0 = 1.0 + // ps[0] += pot_onsite[0]*becp[0] + pot_onsite[18]*becp[3] = 2.0*1.0 + 0*0.0 = 2.0 + // ps[1] += pot_onsite[9]*becp[0] + pot_onsite[27]*becp[3] = 1.0*1.0 + 0*0.0 = 1.0 EXPECT_NEAR(ps[0].real(), 2.0, 1e-15); EXPECT_NEAR(ps[1].real(), 1.0, 1e-15); } @@ -377,10 +377,10 @@ TEST_F(OnsitePsDftuNpol2Test, MultiBand) std::vector orb_l_iat = {1}; std::vector ip_iat = {0, 0, 0}; std::vector ip_m = {0, 1, 2}; - std::vector vu_begin_iat = {0}; + std::vector pot_onsite_begin_iat = {0}; - std::vector vu(36, 0.0); - vu[0] = 2.0; // Block 0, VU[0,0] + std::vector pot_onsite(36, 0.0); + pot_onsite[0] = 2.0; // Block 0, pot_onsite[0,0] // becp: 2 spin x 3 proj x 2 bands = 12 elements // Layout: [band0_up, band0_dn, band1_up, band1_dn] @@ -393,13 +393,13 @@ TEST_F(OnsitePsDftuNpol2Test, MultiBand) std::vector ps(12, 0.0); kernel(nullptr, npm, npol, - orb_l_iat.data(), ip_iat.data(), ip_m.data(), vu_begin_iat.data(), - tnp, vu.data(), ps.data(), becp.data()); + orb_l_iat.data(), ip_iat.data(), ip_m.data(), pot_onsite_begin_iat.data(), + tnp, pot_onsite.data(), ps.data(), becp.data()); // Band pair 0 (ib=0, ib2=0): - // ps[0] += vu[0]*becp[0] + vu[18]*becp[3] = 2.0*1.0 + 0 = 2.0 + // ps[0] += pot_onsite[0]*becp[0] + pot_onsite[18]*becp[3] = 2.0*1.0 + 0 = 2.0 // Band pair 1 (ib=1, ib2=2): - // ps[2] += vu[0]*becp[6] + vu[18]*becp[9] = 2.0*0.2 + 0 = 0.4 + // ps[2] += pot_onsite[0]*becp[6] + pot_onsite[18]*becp[9] = 2.0*0.2 + 0 = 0.4 EXPECT_NEAR(ps[0].real(), 2.0, 1e-15); EXPECT_NEAR(ps[2].real(), 0.4, 1e-15); } @@ -447,23 +447,23 @@ TEST_F(OnsitePsEdgeCasesTest, ZeroLambda) EXPECT_NEAR(ps[1].real(), 20.0, 1e-15); } -TEST_F(OnsitePsEdgeCasesTest, ComplexVU) +TEST_F(OnsitePsEdgeCasesTest, Complexpot_onsite) { - // DFT+U with complex VU elements + // DFT+U with complex pot_onsite elements const int npm = 1, npol = 1, tnp = 2; std::vector orb_l_iat = {0}; // s-orbital, but 2 projectors std::vector ip_iat = {0, 0}; std::vector ip_m = {0, -1}; // first correlated, second not - std::vector vu_begin_iat = {0}; + std::vector pot_onsite_begin_iat = {0}; - std::vector vu = {complexd(1.0, 2.0)}; // 1x1 VU matrix + std::vector pot_onsite = {complexd(1.0, 2.0)}; // 1x1 pot_onsite matrix std::vector becp = {complexd(0.5, 0.5), 1.0}; std::vector ps = {0.0, 0.0}; kernel(nullptr, npm, npol, - orb_l_iat.data(), ip_iat.data(), ip_m.data(), vu_begin_iat.data(), - tnp, vu.data(), ps.data(), becp.data()); + orb_l_iat.data(), ip_iat.data(), ip_m.data(), pot_onsite_begin_iat.data(), + tnp, pot_onsite.data(), ps.data(), becp.data()); // ps[0] += (1+complexd(0.0, 2.0)) * (0.5+0.5i) = 0.5+0.5i + complexd(0.0, 1.0)-1 = -0.5+1.5i EXPECT_NEAR(ps[0].real(), -0.5, 1e-15); diff --git a/source/source_pw/module_pwdft/onsite_proj.cpp b/source/source_pw/module_pwdft/onsite_proj.cpp index 331d3331bd..40b0747cd7 100644 --- a/source/source_pw/module_pwdft/onsite_proj.cpp +++ b/source/source_pw/module_pwdft/onsite_proj.cpp @@ -594,10 +594,10 @@ void projectors::OnsiteProjector::cal_force_onsite_dftu(int ik, int n const double* wg_ik) const { const int isk_val = this->isk_ ? this->isk_[ik] : 0; - const std::complex* vu_ptr = dftu.get_eff_pot_pw_spin(isk_val); - const int vu_size = dftu.get_size_eff_pot_pw_spin(); + const std::complex* pot_onsite_ptr = dftu.get_pot_uterm_pw_spin(isk_val); + const int pot_onsite_size = dftu.get_size_pot_uterm_pw_spin(); this->fs_tools->cal_force_dftu(ik, npm, force, - dftu.get_orbital_corr_data(), vu_ptr, vu_size, wg_ik); + dftu.get_orbital_corr_data(), pot_onsite_ptr, pot_onsite_size, wg_ik); } template @@ -606,10 +606,10 @@ double projectors::OnsiteProjector::cal_stress_onsite_dftu(int ik, in const double* wg_ik) const { const int isk_val = this->isk_ ? this->isk_[ik] : 0; - const std::complex* vu_ptr = dftu.get_eff_pot_pw_spin(isk_val); - const int vu_size = dftu.get_size_eff_pot_pw_spin(); + const std::complex* pot_onsite_ptr = dftu.get_pot_uterm_pw_spin(isk_val); + const int pot_onsite_size = dftu.get_size_pot_uterm_pw_spin(); return this->fs_tools->cal_stress_dftu(ik, npm, - dftu.get_orbital_corr_data(), vu_ptr, vu_size, wg_ik); + dftu.get_orbital_corr_data(), pot_onsite_ptr, pot_onsite_size, wg_ik); } template diff --git a/source/source_pw/module_pwdft/onsite_proj_tools.cpp b/source/source_pw/module_pwdft/onsite_proj_tools.cpp index 4239d8fa9e..593804ca11 100644 --- a/source/source_pw/module_pwdft/onsite_proj_tools.cpp +++ b/source/source_pw/module_pwdft/onsite_proj_tools.cpp @@ -809,26 +809,26 @@ void Onsite_Proj_tools::cal_force_dftu(int ik, int npm, FPTYPE* force, const int* orbital_corr, - const std::complex* vu, - const int size_vu, + const std::complex* pot_onsite, + const int size_pot_onsite, const FPTYPE* h_wg) { int* orbital_corr_tmp = nullptr; - std::complex* vu_tmp = nullptr; + std::complex* pot_onsite_tmp = nullptr; #if defined(__CUDA) || defined(__ROCM) if (this->device == base_device::GpuDevice) { resmem_int_op()(orbital_corr_tmp, this->ucell_->ntype); syncmem_int_h2d_op()(orbital_corr_tmp, orbital_corr, this->ucell_->ntype); - resmem_complex_op()(vu_tmp, size_vu); - syncmem_complex_h2d_op()(vu_tmp, vu, size_vu); + resmem_complex_op()(pot_onsite_tmp, size_pot_onsite); + syncmem_complex_h2d_op()(pot_onsite_tmp, pot_onsite, size_pot_onsite); syncmem_var_h2d_op()(d_wg, h_wg, this->nbands * (ik+1)); } else #endif { orbital_corr_tmp = const_cast(orbital_corr); - vu_tmp = const_cast*>(vu); + pot_onsite_tmp = const_cast*>(pot_onsite); d_wg = const_cast(h_wg); } const int force_nc = 3; @@ -846,7 +846,7 @@ void Onsite_Proj_tools::cal_force_dftu(int ik, atom_na, this->ucell_->tpiba, d_wg, - vu_tmp, + pot_onsite_tmp, orbital_corr_tmp, becp, dbecp, @@ -854,7 +854,7 @@ void Onsite_Proj_tools::cal_force_dftu(int ik, #if defined(__CUDA) || defined(__ROCM) if (this->device == base_device::GpuDevice) { - delmem_complex_op()(vu_tmp); + delmem_complex_op()(pot_onsite_tmp); delmem_int_op()(orbital_corr_tmp); } #endif @@ -921,15 +921,15 @@ template double Onsite_Proj_tools::cal_stress_dftu(int ik, int npm, const int* orb_corr, - const std::complex* vu, - const int size_vu, + const std::complex* pot_onsite, + const int size_pot_onsite, const FPTYPE* h_wg) { double stress_out = 0.0; const int npol = this->ucell_->get_npol(); int* orb_corr_tmp = nullptr; - std::complex* vu_tmp = nullptr; + std::complex* pot_onsite_tmp = nullptr; #if defined(__CUDA) || defined(__ROCM) if (this->device == base_device::GpuDevice) { @@ -937,9 +937,9 @@ double Onsite_Proj_tools::cal_stress_dftu(int ik, resmem_int_op()(orb_corr_tmp, this->ucell_->ntype); syncmem_int_h2d_op()(orb_corr_tmp, orb_corr, this->ucell_->ntype); - // vu_tmp - resmem_complex_op()(vu_tmp, size_vu); - syncmem_complex_h2d_op()(vu_tmp, vu, size_vu); + // pot_onsite_tmp + resmem_complex_op()(pot_onsite_tmp, size_pot_onsite); + syncmem_complex_h2d_op()(pot_onsite_tmp, pot_onsite, size_pot_onsite); // transfer data from from host to device syncmem_var_h2d_op()(d_wg, h_wg, this->nbands * (ik+1)); @@ -959,7 +959,7 @@ double Onsite_Proj_tools::cal_stress_dftu(int ik, atom_nh, atom_na, d_wg, - vu_tmp, + pot_onsite_tmp, orb_corr_tmp, becp, dbecp, @@ -968,14 +968,14 @@ double Onsite_Proj_tools::cal_stress_dftu(int ik, // Transfer stress from device to host syncmem_var_d2h_op()(&stress_out, stress_device, 1); delmem_var_op()(stress_device); - delmem_complex_op()(vu_tmp); + delmem_complex_op()(pot_onsite_tmp); delmem_int_op()(orb_corr_tmp); } else #endif { orb_corr_tmp = const_cast(orb_corr); - vu_tmp = const_cast*>(vu); + pot_onsite_tmp = const_cast*>(pot_onsite); d_wg = const_cast(h_wg); cal_stress_nl_op()(this->ctx, @@ -988,7 +988,7 @@ double Onsite_Proj_tools::cal_stress_dftu(int ik, atom_nh, atom_na, d_wg, - vu_tmp, + pot_onsite_tmp, orb_corr_tmp, becp, dbecp, diff --git a/source/source_pw/module_pwdft/onsite_proj_tools.h b/source/source_pw/module_pwdft/onsite_proj_tools.h index 0b7ef73b83..6c3ecc0a37 100644 --- a/source/source_pw/module_pwdft/onsite_proj_tools.h +++ b/source/source_pw/module_pwdft/onsite_proj_tools.h @@ -78,8 +78,8 @@ class Onsite_Proj_tools int npm, FPTYPE* force, const int* orbital_corr, - const std::complex* vu, - const int size_vu, + const std::complex* pot_onsite, + const int size_pot_onsite, const FPTYPE* h_wg ); @@ -96,8 +96,8 @@ class Onsite_Proj_tools int ik, int npm, const int* orbital_corr, - const std::complex* vu, - const int size_vu, + const std::complex* pot_onsite, + const int size_pot_onsite, const FPTYPE* h_wg ); diff --git a/source/source_pw/module_pwdft/op_pw_proj.cpp b/source/source_pw/module_pwdft/op_pw_proj.cpp index 7244b315f7..35cd7f6f9b 100644 --- a/source/source_pw/module_pwdft/op_pw_proj.cpp +++ b/source/source_pw/module_pwdft/op_pw_proj.cpp @@ -44,7 +44,7 @@ OnsiteProj>::~OnsiteProj() { delmem_int_op()(this->orb_l_iat); delmem_int_op()(this->ip_m); delmem_int_op()(this->vu_begin_iat); - delmem_complex_op()(this->vu_device); + delmem_complex_op()(this->pot_onsite_device); } } @@ -181,15 +181,15 @@ void OnsiteProj>::cal_ps_delta_spin(const int npol, const this->ps, becp); } -// cal_ps_dftu — compute ps = VU * becp for DFT+U Hamiltonian contribution +// cal_ps_dftu — compute ps = pot_onsite * becp for DFT+U Hamiltonian contribution // -// eff_pot_pw layout by nspin: +// pot_uterm_pw layout by nspin: // nspin=1: [iat0_tlp1^2 | iat1_tlp1^2 | ...] // single spin channel, full array uploaded // nspin=2: [iat0_up | iat1_up | ... | iat0_dn | iat1_dn | ...] // split layout — first half is spin-up, second half spin-down. // For isk==1 (spin-down k-point), only the second half is -// uploaded to vu_device so that vu_begin_iat[iat] indexes +// uploaded to pot_onsite_device so that vu_begin_iat[iat] indexes // correctly into the spin-down block. // nspin=4: [iat0_Pauli_4blocks | iat1_Pauli_4blocks | ...] // 4*(2l+1)^2 entries per atom; kernel uses npol=2 spinor @@ -260,7 +260,7 @@ void OnsiteProj>::setup_pw_dftu_indices() const syncmem_int_h2d_op()(this->ip_m, ip_m0.data(), onsite_p->get_tot_nproj()); syncmem_int_h2d_op()(this->vu_begin_iat, vu_begin_iat0.data(), this->ucell->nat); - resmem_complex_op()(this->vu_device, dftu->get_size_eff_pot_pw()); + resmem_complex_op()(this->pot_onsite_device, dftu->get_size_pot_uterm_pw()); } template @@ -291,9 +291,9 @@ void OnsiteProj>::cal_ps_dftu( } const int isk_val = (PARAM.inp.nspin == 2) ? this->isk[this->ik] : 0; - const std::complex* vu_host = dftu->get_eff_pot_pw_spin(isk_val); - const int vu_size = dftu->get_size_eff_pot_pw_spin(); - syncmem_complex_h2d_op()(this->vu_device, vu_host, vu_size); + const std::complex* pot_onsite_host = dftu->get_pot_uterm_pw_spin(isk_val); + const int pot_onsite_size = dftu->get_size_pot_uterm_pw_spin(); + syncmem_complex_h2d_op()(this->pot_onsite_device, pot_onsite_host, pot_onsite_size); hamilt::onsite_ps_op()( this->ctx, m, @@ -303,7 +303,7 @@ void OnsiteProj>::cal_ps_dftu( this->ip_m, this->vu_begin_iat, tnp, - this->vu_device, + this->pot_onsite_device, this->ps, becp); } @@ -375,7 +375,7 @@ void OnsiteProj, base_device::DEVICE_GPU>>::cal_p // // nspin handling in cal_ps_dftu: // nspin=1 (npol=1): single spin channel, no spin selection needed -// nspin=2 (npol=1): eff_pot_pw uses split layout [all_up | all_dn]; +// nspin=2 (npol=1): pot_uterm_pw uses split layout [all_up | all_dn]; // spin-up k-points (isk=0) read from the first half; // spin-down k-points (isk=1) read from the second half. // nspin=4 (npol=2): all 4 Pauli blocks stored per-atom; kernel uses From 3dd888323e00629904c12f7ca0d2557357d896f1 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 17:51:19 +0800 Subject: [PATCH 20/23] fix(dftu): rename remaining vu_device / vu_begin_iat / vu_in members missed in previous commit The previous rename commit (3ac7790de) used rg with word-boundary patterns, which missed identifiers like 'vu_device', 'vu_begin_iat', 'vu_begin_iat0', 'vu_begin', 'vu_in' -- because underscore is a word character, so '\bvu\b' does not match 'vu' followed by '_'. Compile failure: op_pw_proj.cpp:47: error: 'class hamilt::OnsiteProj<...>' has no member named 'pot_onsite_device' op_pw_proj.cpp:263: error: ... has no member named 'pot_onsite_device' This was because the member declaration in op_pw_proj.h:75 was still 'vu_device' while op_pw_proj.cpp called this->pot_onsite_device. Files fixed (loose-pattern search 'vu' as substring): * source/source_pw/module_pwdft/op_pw_proj.h: - vu_begin_iat -> pot_onsite_begin_iat (member) - vu_device -> pot_onsite_device (member) * source/source_pw/module_pwdft/op_pw_proj.cpp: - vu_begin_iat, vu_begin_iat0, vu_begin -> pot_onsite_* * source/source_lcao/module_dftu/dftu_fs.cpp: - vu_in -> pot_onsite_in (function parameter, 14 occurrences) Verification: - rg 'vu' (substring, no word boundary) over DFTU scope returns no matches. - python3 tools/03_code_analysis/agent_governance_check.py --staged passes with no findings. --- source/source_lcao/module_dftu/dftu_fs.cpp | 28 ++++++++++---------- source/source_pw/module_pwdft/op_pw_proj.cpp | 22 +++++++-------- source/source_pw/module_pwdft/op_pw_proj.h | 6 ++--- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/source/source_lcao/module_dftu/dftu_fs.cpp b/source/source_lcao/module_dftu/dftu_fs.cpp index 54621d29e0..ddd4955dbe 100644 --- a/source/source_lcao/module_dftu/dftu_fs.cpp +++ b/source/source_lcao/module_dftu/dftu_fs.cpp @@ -275,7 +275,7 @@ void DFTU>::cal_force_IJR(const int& iat1, const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, double* force1, @@ -290,7 +290,7 @@ void DFTU>::cal_force_IJR(const int& iat1, // --------------------------------------------- auto row_indexes = paraV->get_indexes_row(iat1); auto col_indexes = paraV->get_indexes_col(iat2); - const int m_size = int(sqrt(vu_in.size() / nspin)); + const int m_size = int(sqrt(pot_onsite_in.size() / nspin)); const int m_size2 = m_size * m_size; // step_trace = 0 for NSPIN=1,2; ={0, 1, local_col, local_col+1} for NSPIN=4 @@ -323,11 +323,11 @@ void DFTU>::cal_force_IJR(const int& iat1, { for (int m2 = 0; m2 < m_size; m2++) { - tmp[0] = vu_in[m1 * m_size + m2 + is * m_size2] * nlm1[m1 + m_size] + tmp[0] = pot_onsite_in[m1 * m_size + m2 + is * m_size2] * nlm1[m1 + m_size] * nlm2[m2] * dm_pointer[step_trace[step_is]]; - tmp[1] = vu_in[m1 * m_size + m2 + is * m_size2] * nlm1[m1 + m_size * 2] + tmp[1] = pot_onsite_in[m1 * m_size + m2 + is * m_size2] * nlm1[m1 + m_size * 2] * nlm2[m2] * dm_pointer[step_trace[step_is]]; - tmp[2] = vu_in[m1 * m_size + m2 + is * m_size2] * nlm1[m1 + m_size * 3] + tmp[2] = pot_onsite_in[m1 * m_size + m2 + is * m_size2] * nlm1[m1 + m_size * 3] * nlm2[m2] * dm_pointer[step_trace[step_is]]; // force1 = - pot_onsite * * // force2 = - pot_onsite * * } @@ -352,7 +352,7 @@ void DFTU>::cal_stress_IJR(const int& iat1, const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, const ModuleBase::Vector3& dis1, @@ -368,7 +368,7 @@ void DFTU>::cal_stress_IJR(const int& iat1, // --------------------------------------------- auto row_indexes = paraV->get_indexes_row(iat1); auto col_indexes = paraV->get_indexes_col(iat2); - const int m_size = int(sqrt(vu_in.size() / nspin)); + const int m_size = int(sqrt(pot_onsite_in.size() / nspin)); const int m_size2 = m_size * m_size; // step_trace = 0 for NSPIN=1,2; ={0, 1, local_col, local_col+1} for NSPIN=4 @@ -400,7 +400,7 @@ void DFTU>::cal_stress_IJR(const int& iat1, { for (int m2 = 0; m2 < m_size; m2++) { - double tmp = vu_in[m1 * m_size + m2 + is * m_size2] * dm_pointer[step_trace[step_is]]; + double tmp = pot_onsite_in[m1 * m_size + m2 + is * m_size2] * dm_pointer[step_trace[step_is]]; // std::cout<<__FILE__<<__LINE__<<" "<>::cal_force_IJR( const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, double* force1, double* force2); @@ -450,7 +450,7 @@ template void DFTU, double>>::cal_force_IJR( const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, double* force1, double* force2); @@ -459,7 +459,7 @@ template void DFTU, std::complex>>::ca const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, double* force1, double* force2); @@ -469,7 +469,7 @@ template void DFTU>::cal_stress_IJR( const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, const ModuleBase::Vector3& dis1, @@ -480,7 +480,7 @@ template void DFTU, double>>::cal_stress_IJR( const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, const ModuleBase::Vector3& dis1, @@ -491,7 +491,7 @@ template void DFTU, std::complex>>::ca const Parallel_Orbitals* paraV, const std::unordered_map>& nlm1_all, const std::unordered_map>& nlm2_all, - const std::vector& vu_in, + const std::vector& pot_onsite_in, const hamilt::BaseMatrix** dmR_pointer, const int nspin, const ModuleBase::Vector3& dis1, diff --git a/source/source_pw/module_pwdft/op_pw_proj.cpp b/source/source_pw/module_pwdft/op_pw_proj.cpp index 35cd7f6f9b..9321138cc9 100644 --- a/source/source_pw/module_pwdft/op_pw_proj.cpp +++ b/source/source_pw/module_pwdft/op_pw_proj.cpp @@ -43,7 +43,7 @@ OnsiteProj>::~OnsiteProj() { } delmem_int_op()(this->orb_l_iat); delmem_int_op()(this->ip_m); - delmem_int_op()(this->vu_begin_iat); + delmem_int_op()(this->pot_onsite_begin_iat); delmem_complex_op()(this->pot_onsite_device); } } @@ -189,13 +189,13 @@ void OnsiteProj>::cal_ps_delta_spin(const int npol, const // nspin=2: [iat0_up | iat1_up | ... | iat0_dn | iat1_dn | ...] // split layout — first half is spin-up, second half spin-down. // For isk==1 (spin-down k-point), only the second half is -// uploaded to pot_onsite_device so that vu_begin_iat[iat] indexes +// uploaded to pot_onsite_device so that pot_onsite_begin_iat[iat] indexes // correctly into the spin-down block. // nspin=4: [iat0_Pauli_4blocks | iat1_Pauli_4blocks | ...] // 4*(2l+1)^2 entries per atom; kernel uses npol=2 spinor // structure with 2x2 Pauli matrix coefficients. // -// vu_begin_iat is computed as tlp1^2 * npol^2 per atom at init time, +// pot_onsite_begin_iat is computed as tlp1^2 * npol^2 per atom at init time, // which gives the correct offset for each nspin case: // nspin=1: tlp1^2 * 1 = tlp1^2 // nspin=2: tlp1^2 * 1 = tlp1^2 (per spin channel, selected by isk) @@ -209,15 +209,15 @@ void OnsiteProj>::setup_pw_dftu_indices() const resmem_int_op()(this->orb_l_iat, this->ucell->nat); resmem_int_op()(this->ip_m, onsite_p->get_tot_nproj()); - resmem_int_op()(this->vu_begin_iat, this->ucell->nat); + resmem_int_op()(this->pot_onsite_begin_iat, this->ucell->nat); resmem_int_op()(this->ip_iat, onsite_p->get_tot_nproj()); std::vector ip_iat0(onsite_p->get_tot_nproj()); std::vector ip_m0(onsite_p->get_tot_nproj()); - std::vector vu_begin_iat0(this->ucell->nat); + std::vector pot_onsite_begin_iat0(this->ucell->nat); std::vector orb_l_iat0(this->ucell->nat); int ip0 = 0; - int vu_begin = 0; + int pot_onsite_begin = 0; for(int iat=0;iatucell->nat;iat++) { const int it = this->ucell->iat2it[iat]; @@ -231,14 +231,14 @@ void OnsiteProj>::setup_pw_dftu_indices() const ip_iat0[ip0] = iat; ip_m0[ip0++] = -1; } - vu_begin_iat0[iat] = 0; + pot_onsite_begin_iat0[iat] = 0; continue; } else { const int tlp1 = 2 * target_l + 1; - vu_begin_iat0[iat] = vu_begin; - vu_begin += tlp1 * tlp1 * npol * npol; + pot_onsite_begin_iat0[iat] = pot_onsite_begin; + pot_onsite_begin += tlp1 * tlp1 * npol * npol; const int m_begin = target_l * target_l; const int m_end = (target_l + 1) * (target_l + 1); for(int ip=0;ip>::setup_pw_dftu_indices() const syncmem_int_h2d_op()(this->orb_l_iat, orb_l_iat0.data(), this->ucell->nat); syncmem_int_h2d_op()(this->ip_iat, ip_iat0.data(), onsite_p->get_tot_nproj()); syncmem_int_h2d_op()(this->ip_m, ip_m0.data(), onsite_p->get_tot_nproj()); - syncmem_int_h2d_op()(this->vu_begin_iat, vu_begin_iat0.data(), this->ucell->nat); + syncmem_int_h2d_op()(this->pot_onsite_begin_iat, pot_onsite_begin_iat0.data(), this->ucell->nat); resmem_complex_op()(this->pot_onsite_device, dftu->get_size_pot_uterm_pw()); } @@ -301,7 +301,7 @@ void OnsiteProj>::cal_ps_dftu( this->orb_l_iat, this->ip_iat, this->ip_m, - this->vu_begin_iat, + this->pot_onsite_begin_iat, tnp, this->pot_onsite_device, this->ps, becp); diff --git a/source/source_pw/module_pwdft/op_pw_proj.h b/source/source_pw/module_pwdft/op_pw_proj.h index 298cd8749c..4cece48299 100644 --- a/source/source_pw/module_pwdft/op_pw_proj.h +++ b/source/source_pw/module_pwdft/op_pw_proj.h @@ -54,7 +54,7 @@ class OnsiteProj> : public OperatorPW void cal_ps_dftu(const int npol, const int m) const; - /// one-time setup of DFT+U PW index arrays (orb_l_iat, ip_iat, ip_m, vu_begin_iat) + /// one-time setup of DFT+U PW index arrays (orb_l_iat, ip_iat, ip_m, pot_onsite_begin_iat) void setup_pw_dftu_indices() const; void update_becp(const T* psi_in, const int npol, const int m, const int npwx) const; @@ -71,8 +71,8 @@ class OnsiteProj> : public OperatorPW mutable T* lambda_coeff = nullptr; mutable int* orb_l_iat = nullptr; mutable int* ip_m = nullptr; - mutable int* vu_begin_iat = nullptr; - mutable T* vu_device = nullptr; + mutable int* pot_onsite_begin_iat = nullptr; + mutable T* pot_onsite_device = nullptr; mutable int nkb_m = 0; From 36b5ac0315f1302b0cd758ab4275038f82d885d1 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 17:52:36 +0800 Subject: [PATCH 21/23] fix(dftu): restore cal_eff_pot_mat_R_{double,complex_double} function names Commit 5ac6ca73f claimed 'R-space versions cal_eff_pot_mat_R_* kept as-is for follow-up' in its message, but actually renamed the function definitions in dftu_hamilt.cpp to cal_pot_uterm_mat_R_*. The member declarations in dftu_lcao.h were not renamed, causing header/implementation mismatch: dftu_hamilt.cpp:127: error: no declaration matches 'void Plus_U::cal_pot_uterm_mat_R_double(int, double*, double*, int)' dftu_hamilt.cpp:157: error: no declaration matches 'void Plus_U::cal_pot_uterm_mat_R_complex_double(...)' Restore the original names cal_eff_pot_mat_R_double and cal_eff_pot_mat_mat_R_complex_double in dftu_hamilt.cpp so they match the declarations in dftu_lcao.h:80,82 and the call sites in spar_u.cpp:76,195. The R-space functions will be renamed in a follow-up commit that also updates spar_u.cpp and the header in lock-step. Verification: - rg 'cal_pot_uterm_mat_R' returns no matches (no stale callers). - rg 'cal_eff_pot_mat_R' shows consistent use across dftu_lcao.h (declarations), dftu_hamilt.cpp (definitions), spar_u.cpp (call sites). --- source/source_lcao/module_dftu/dftu_hamilt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/source_lcao/module_dftu/dftu_hamilt.cpp b/source/source_lcao/module_dftu/dftu_hamilt.cpp index 2798baa03a..692a221490 100644 --- a/source/source_lcao/module_dftu/dftu_hamilt.cpp +++ b/source/source_lcao/module_dftu/dftu_hamilt.cpp @@ -124,7 +124,7 @@ void pot_uterm_real(Plus_U& dftu, } // namespace DFTU_LCAO -void Plus_U::cal_pot_uterm_mat_R_double(const int ispin, double* SR, double* HR, const int npol) +void Plus_U::cal_eff_pot_mat_R_double(const int ispin, double* SR, double* HR, const int npol) { const char transN = 'N', transT = 'T'; const int one_int = 1; @@ -154,7 +154,7 @@ void Plus_U::cal_pot_uterm_mat_R_double(const int ispin, double* SR, double* HR, return; } -void Plus_U::cal_pot_uterm_mat_R_complex_double(const int ispin, std::complex* SR, std::complex* HR, const int npol) +void Plus_U::cal_eff_pot_mat_R_complex_double(const int ispin, std::complex* SR, std::complex* HR, const int npol) { const char transN = 'N', transT = 'T'; const int one_int = 1; From a9678d815b9511684ba31659120c8003bc139731 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 17:57:12 +0800 Subject: [PATCH 22/23] refactor(dftu): rename 'locale' to 'occ_mat' in DFT+U tests and input docs The DFTU tests and input parameter docs used 'locale' as a variable and annotation name for the occupation matrix. This is confusing because 'locale' is also a C++ standard library concept (std::locale, localization). The actual physical quantity is the occupation matrix n_{mm'}, so rename to 'occ_mat' for clarity and consistency with the existing Plus_U_Base member 'occ_mat' and 'get_occ_mat()' accessor. Renames (variable scope limited to tests + comments): * dftu_pw_test.cpp: locale_c / locale_up / locale_dn -> occ_mat_c / occ_mat_up / occ_mat_dn (flattened occupation matrix passed to compute_pot_onsite_scalar); comments updated. * dftu_core_test.cpp: function parameters locale_up / locale_dn -> occ_mat_up / occ_mat_dn (Matrix2D per-atom occupation matrices). * dftu_lcao_op.cpp:192 comment 'Reads locale ...' -> 'Reads occ_mat ...' * input_parameter.h:115 annotation 'mix locale' -> 'mix occ_mat' (parameter name 'mixing_dftu' unchanged, no INPUT behavior change). * read_inp_estruc.cpp:760 annotation 'mix locale' -> 'mix occ_mat' Out of scope (intentionally untouched): * Plus_U_Base::occ_mat member -- already named 'occ_mat', no change. * Non-DFTU 'locale' occurrences (input_parameter.h is touched only for the DFT+U annotation line). Verification: - rg '\blocale\b' over DFTU scope + module_parameter returns no matches. - python3 tools/03_code_analysis/agent_governance_check.py --staged passes with no findings. Test/Doc plan: * Tests: pure rename of test-local variables and comments; no semantic change; existing tests in dftu_pw_test.cpp and dftu_core_test.cpp updated in lock-step. * Docs: no INPUT parameter name change (still 'mixing_dftu'); only the annotation string is reworded for clarity. parameters.yaml and input-main.md do not mention 'locale' so no update required there. --- .../module_parameter/input_parameter.h | 2 +- .../module_parameter/read_inp_estruc.cpp | 2 +- .../source_lcao/module_dftu/dftu_lcao_op.cpp | 2 +- .../module_dftu/test/dftu_core_test.cpp | 134 +++++++++--------- .../module_dftu/test/dftu_pw_test.cpp | 94 ++++++------ 5 files changed, 117 insertions(+), 117 deletions(-) diff --git a/source/source_io/module_parameter/input_parameter.h b/source/source_io/module_parameter/input_parameter.h index c5890b4dc3..96189eadf9 100644 --- a/source/source_io/module_parameter/input_parameter.h +++ b/source/source_io/module_parameter/input_parameter.h @@ -112,7 +112,7 @@ struct Input_para double mixing_gg0_min = 0.1; double mixing_angle = -10.0; bool mixing_tau = false; ///< whether to mix tau in mgga - bool mixing_dftu = false; ///< whether to mix locale in DFT+U + bool mixing_dftu = false; ///< whether to mix occ_mat in DFT+U bool mixing_dmr = false; ///< whether to mix real space density matrix bool gamma_only = false; ///< for plane wave. diff --git a/source/source_io/module_parameter/read_inp_estruc.cpp b/source/source_io/module_parameter/read_inp_estruc.cpp index 463ea6e47f..ff6a5a7b57 100644 --- a/source/source_io/module_parameter/read_inp_estruc.cpp +++ b/source/source_io/module_parameter/read_inp_estruc.cpp @@ -757,7 +757,7 @@ This setting takes effect only when the selected exchange-correlation functional } { Input_Item item("mixing_dftu"); - item.annotation = "whether to mix locale in DFT+U calculation"; + item.annotation = "whether to mix occ_mat in DFT+U calculation"; item.category = "Electronic structure"; item.type = "Boolean"; item.description = R"(Whether to mix the occupation matrices. diff --git a/source/source_lcao/module_dftu/dftu_lcao_op.cpp b/source/source_lcao/module_dftu/dftu_lcao_op.cpp index 1c53437e71..c657bbd1cf 100644 --- a/source/source_lcao/module_dftu/dftu_lcao_op.cpp +++ b/source/source_lcao/module_dftu/dftu_lcao_op.cpp @@ -189,7 +189,7 @@ void hamilt::DFTU>::cal_nlm_all(const Parallel_Orbi * Case 2: Occ_mat IS initialized (is_occ_mat_initialized, i.e., read from dm_onsite.txt file) * - First electronic iteration: uses pre-read occ_mat directly without DMR calculation * * Skips DMR-based occ calculation entirely - * * Reads locale from stored data via get_occ_mat() + * * Reads occ_mat from stored data via get_occ_mat() * * Different indexing for nspin=4 vs nspin=1/2 (see below) * - After first iteration: mark_occ_mat_dirty() is called to force recomputation * diff --git a/source/source_lcao/module_dftu/test/dftu_core_test.cpp b/source/source_lcao/module_dftu/test/dftu_core_test.cpp index 4a26654f74..60500ac5f0 100644 --- a/source/source_lcao/module_dftu/test/dftu_core_test.cpp +++ b/source/source_lcao/module_dftu/test/dftu_core_test.cpp @@ -104,81 +104,81 @@ struct Matrix2D { }; static void copy_occ_mat_to_flat( - const std::vector& locale_up, - const std::vector& locale_dn, + const std::vector& occ_mat_up, + const std::vector& occ_mat_dn, std::vector& uom_save, const std::vector& pot_uterm_pw_index, int nspin) { if (nspin == 4) { - for (size_t iat = 0; iat < locale_up.size(); iat++) + for (size_t iat = 0; iat < occ_mat_up.size(); iat++) { - int size = locale_up[iat].nr * locale_up[iat].nc; + int size = occ_mat_up[iat].nr * occ_mat_up[iat].nc; for (int mm = 0; mm < size; mm++) - uom_save[pot_uterm_pw_index[iat] + mm] = locale_up[iat].data[mm]; + uom_save[pot_uterm_pw_index[iat] + mm] = occ_mat_up[iat].data[mm]; } } else if (nspin == 2) // split layout: [up | dn] { int half_size = uom_save.size() / 2; - for (size_t iat = 0; iat < locale_up.size(); iat++) + for (size_t iat = 0; iat < occ_mat_up.size(); iat++) { - int size = locale_up[iat].nr * locale_up[iat].nc; + int size = occ_mat_up[iat].nr * occ_mat_up[iat].nc; for (int mm = 0; mm < size; mm++) { - uom_save[pot_uterm_pw_index[iat] + mm] = locale_up[iat].data[mm]; - uom_save[half_size + pot_uterm_pw_index[iat] + mm] = locale_dn[iat].data[mm]; + uom_save[pot_uterm_pw_index[iat] + mm] = occ_mat_up[iat].data[mm]; + uom_save[half_size + pot_uterm_pw_index[iat] + mm] = occ_mat_dn[iat].data[mm]; } } } else // nspin=1: single spin channel { - for (size_t iat = 0; iat < locale_up.size(); iat++) + for (size_t iat = 0; iat < occ_mat_up.size(); iat++) { - int size = locale_up[iat].nr * locale_up[iat].nc; + int size = occ_mat_up[iat].nr * occ_mat_up[iat].nc; for (int mm = 0; mm < size; mm++) - uom_save[pot_uterm_pw_index[iat] + mm] = locale_up[iat].data[mm]; + uom_save[pot_uterm_pw_index[iat] + mm] = occ_mat_up[iat].data[mm]; } } } static void set_occ_mat_from_flat( const std::vector& uom_array, - std::vector& locale_up, - std::vector& locale_dn, + std::vector& occ_mat_up, + std::vector& occ_mat_dn, const std::vector& pot_uterm_pw_index, int nspin) { if (nspin == 4) { - for (size_t iat = 0; iat < locale_up.size(); iat++) + for (size_t iat = 0; iat < occ_mat_up.size(); iat++) { - int size = locale_up[iat].nr * locale_up[iat].nc; + int size = occ_mat_up[iat].nr * occ_mat_up[iat].nc; for (int mm = 0; mm < size; mm++) - locale_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; + occ_mat_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; } } else if (nspin == 2) { int half_size = uom_array.size() / 2; - for (size_t iat = 0; iat < locale_up.size(); iat++) + for (size_t iat = 0; iat < occ_mat_up.size(); iat++) { - int size = locale_up[iat].nr * locale_up[iat].nc; + int size = occ_mat_up[iat].nr * occ_mat_up[iat].nc; for (int mm = 0; mm < size; mm++) { - locale_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; - locale_dn[iat].data[mm] = uom_array[half_size + pot_uterm_pw_index[iat] + mm]; + occ_mat_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; + occ_mat_dn[iat].data[mm] = uom_array[half_size + pot_uterm_pw_index[iat] + mm]; } } } else // nspin=1 { - for (size_t iat = 0; iat < locale_up.size(); iat++) + for (size_t iat = 0; iat < occ_mat_up.size(); iat++) { - int size = locale_up[iat].nr * locale_up[iat].nc; + int size = occ_mat_up[iat].nr * occ_mat_up[iat].nc; for (int mm = 0; mm < size; mm++) - locale_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; + occ_mat_up[iat].data[mm] = uom_array[pot_uterm_pw_index[iat] + mm]; } } } @@ -195,38 +195,38 @@ TEST_F(OccMatRoundtripTest, Nspin1and2_SingleAndSplitLayout) const int l = 2; const int size = (2 * l + 1) * (2 * l + 1); // 25 - std::vector locale_up(1, Matrix2D(2 * l + 1, 2 * l + 1)); - std::vector locale_dn(1, Matrix2D(2 * l + 1, 2 * l + 1)); + std::vector occ_mat_up(1, Matrix2D(2 * l + 1, 2 * l + 1)); + std::vector occ_mat_dn(1, Matrix2D(2 * l + 1, 2 * l + 1)); for (int i = 0; i < size; i++) - locale_up[0].data[i] = static_cast(i + 1); + occ_mat_up[0].data[i] = static_cast(i + 1); std::vector pot_uterm_pw_index = {0}; std::vector uom_save(size, 0.0); - copy_occ_mat_to_flat(locale_up, locale_dn, uom_save, pot_uterm_pw_index, 1); - set_occ_mat_from_flat(uom_save, locale_up, locale_dn, pot_uterm_pw_index, 1); + copy_occ_mat_to_flat(occ_mat_up, occ_mat_dn, uom_save, pot_uterm_pw_index, 1); + set_occ_mat_from_flat(uom_save, occ_mat_up, occ_mat_dn, pot_uterm_pw_index, 1); for (int i = 0; i < size; i++) - EXPECT_DOUBLE_EQ(locale_up[0].data[i], static_cast(i + 1)); + EXPECT_DOUBLE_EQ(occ_mat_up[0].data[i], static_cast(i + 1)); // nspin=2: split layout [up | dn] with distinct values const int total = size * 2; for (int i = 0; i < size; i++) { - locale_up[0].data[i] = static_cast(i + 1); - locale_dn[0].data[i] = static_cast(i + 100); + occ_mat_up[0].data[i] = static_cast(i + 1); + occ_mat_dn[0].data[i] = static_cast(i + 100); } uom_save.assign(total, 0.0); - copy_occ_mat_to_flat(locale_up, locale_dn, uom_save, pot_uterm_pw_index, 2); + copy_occ_mat_to_flat(occ_mat_up, occ_mat_dn, uom_save, pot_uterm_pw_index, 2); // Verify split layout for (int i = 0; i < size; i++) { EXPECT_DOUBLE_EQ(uom_save[i], static_cast(i + 1)); EXPECT_DOUBLE_EQ(uom_save[size + i], static_cast(i + 100)); } - set_occ_mat_from_flat(uom_save, locale_up, locale_dn, pot_uterm_pw_index, 2); + set_occ_mat_from_flat(uom_save, occ_mat_up, occ_mat_dn, pot_uterm_pw_index, 2); for (int i = 0; i < size; i++) { - EXPECT_DOUBLE_EQ(locale_up[0].data[i], static_cast(i + 1)); - EXPECT_DOUBLE_EQ(locale_dn[0].data[i], static_cast(i + 100)); + EXPECT_DOUBLE_EQ(occ_mat_up[0].data[i], static_cast(i + 1)); + EXPECT_DOUBLE_EQ(occ_mat_dn[0].data[i], static_cast(i + 100)); } } @@ -253,39 +253,39 @@ TEST_F(OccMatRoundtripTest, Nspin4_PauliBlocks) offset += sizes[i]; } - std::vector locale(specs.size()); + std::vector occ_mat(specs.size()); for (size_t i = 0; i < specs.size(); i++) { int dim = (2 * specs[i].l + 1) * npol; - locale[i] = Matrix2D(dim, dim); + occ_mat[i] = Matrix2D(dim, dim); for (int j = 0; j < sizes[i]; j++) - locale[i].data[j] = static_cast(i * 1000 + j + 1); + occ_mat[i].data[j] = static_cast(i * 1000 + j + 1); } std::vector uom_array(total, 0.0); - std::vector locale_dn(specs.size()); // unused for nspin=4 + std::vector occ_mat_dn(specs.size()); // unused for nspin=4 - copy_occ_mat_to_flat(locale, locale_dn, uom_array, pot_uterm_pw_index, 4); - set_occ_mat_from_flat(uom_array, locale, locale_dn, pot_uterm_pw_index, 4); + copy_occ_mat_to_flat(occ_mat, occ_mat_dn, uom_array, pot_uterm_pw_index, 4); + set_occ_mat_from_flat(uom_array, occ_mat, occ_mat_dn, pot_uterm_pw_index, 4); for (size_t i = 0; i < specs.size(); i++) for (int j = 0; j < sizes[i]; j++) - EXPECT_DOUBLE_EQ(locale[i].data[j], static_cast(i * 1000 + j + 1)); + EXPECT_DOUBLE_EQ(occ_mat[i].data[j], static_cast(i * 1000 + j + 1)); } // ===================================================================== // 3. pot_onsite effective potential formula (cal_type=3, FLL) // -// pot_onsite[m0,m1] = U * (0.5*delta(m0,m1) - locale[m0,m1]) (diagonal) -// pot_onsite[m0,m1] = -U * locale[m0,m1] (off-diagonal) +// pot_onsite[m0,m1] = U * (0.5*delta(m0,m1) - occ_mat[m0,m1]) (diagonal) +// pot_onsite[m0,m1] = -U * occ_mat[m0,m1] (off-diagonal) // ===================================================================== -static double compute_pot_onsite(double U_val, int m0, int m1, double locale_val) +static double compute_pot_onsite(double U_val, int m0, int m1, double occ_mat_val) { if (m0 == m1) - return U_val * (0.5 - locale_val); + return U_val * (0.5 - occ_mat_val); else - return -U_val * locale_val; + return -U_val * occ_mat_val; } class PotOnsitePotentialTest : public ::testing::Test @@ -297,25 +297,25 @@ class PotOnsitePotentialTest : public ::testing::Test TEST_F(PotOnsitePotentialTest, Diagonal_HalfFilled) { double U = 4.0; - double locale = 0.5; // half-filled - double pot_onsite = compute_pot_onsite(U, 0, 0, locale); + double occ_mat = 0.5; // half-filled + double pot_onsite = compute_pot_onsite(U, 0, 0, occ_mat); EXPECT_DOUBLE_EQ(pot_onsite, 0.0); // U * (0.5 - 0.5) = 0 } TEST_F(PotOnsitePotentialTest, Diagonal_FullyOccupied) { double U = 4.0; - double locale = 1.0; // fully occupied - double pot_onsite = compute_pot_onsite(U, 0, 0, locale); + double occ_mat = 1.0; // fully occupied + double pot_onsite = compute_pot_onsite(U, 0, 0, occ_mat); EXPECT_DOUBLE_EQ(pot_onsite, -2.0); // U * (0.5 - 1.0) = -2.0 } TEST_F(PotOnsitePotentialTest, OffDiagonal) { double U = 5.0; - double locale = 0.3; - double pot_onsite = compute_pot_onsite(U, 0, 1, locale); - EXPECT_DOUBLE_EQ(pot_onsite, -1.5); // -U * locale = -1.5 + double occ_mat = 0.3; + double pot_onsite = compute_pot_onsite(U, 0, 1, occ_mat); + EXPECT_DOUBLE_EQ(pot_onsite, -1.5); // -U * occ_mat = -1.5 } // ===================================================================== @@ -327,14 +327,14 @@ TEST_F(PotOnsitePotentialTest, OffDiagonal) class EnergyCorrectionTest : public ::testing::Test { protected: - static double compute_energy(const std::vector& locale_flat, int m_size, double U) + static double compute_energy(const std::vector& occ_mat_flat, int m_size, double U) { double nm_trace = 0.0, nm2_trace = 0.0; for (int m0 = 0; m0 < m_size; m0++) { - nm_trace += locale_flat[m0 * m_size + m0]; + nm_trace += occ_mat_flat[m0 * m_size + m0]; for (int m1 = 0; m1 < m_size; m1++) - nm2_trace += locale_flat[m0 * m_size + m1] * locale_flat[m1 * m_size + m0]; + nm2_trace += occ_mat_flat[m0 * m_size + m1] * occ_mat_flat[m1 * m_size + m0]; } return 0.5 * U * (nm_trace - nm2_trace); } @@ -343,11 +343,11 @@ class EnergyCorrectionTest : public ::testing::Test TEST_F(EnergyCorrectionTest, HalfFilled_DOrbital) { const int m_size = 5; - std::vector locale(m_size * m_size, 0.0); + std::vector occ_mat(m_size * m_size, 0.0); for (int m = 0; m < m_size; m++) - locale[m * m_size + m] = 0.5; + occ_mat[m * m_size + m] = 0.5; - double energy = compute_energy(locale, m_size, 4.0); + double energy = compute_energy(occ_mat, m_size, 4.0); // Tr(n) = 2.5, Tr(n^2) = 1.25, E = 0.5 * 4 * 1.25 = 2.5 EXPECT_DOUBLE_EQ(energy, 2.5); } @@ -355,12 +355,12 @@ TEST_F(EnergyCorrectionTest, HalfFilled_DOrbital) TEST_F(EnergyCorrectionTest, OffDiagonal_Contribution) { const int m_size = 2; - std::vector locale = { + std::vector occ_mat = { 0.3, 0.1, 0.1, 0.3 }; - double energy = compute_energy(locale, m_size, 4.0); + double energy = compute_energy(occ_mat, m_size, 4.0); // Tr(n) = 0.6, Tr(n^2) = 0.3^2 + 0.1^2 + 0.1^2 + 0.3^2 = 0.20 // E = 0.5 * 4 * (0.6 - 0.20) = 0.8 EXPECT_DOUBLE_EQ(energy, 0.8); @@ -371,7 +371,7 @@ TEST_F(EnergyCorrectionTest, DoubleCounting_Energy) // E_dc = sum_{m1,m2,spin} pot_onsite[m1,m2] * n[m2,m1] const int m_size = 3; double U = 4.0; - std::vector locale = { + std::vector occ_mat = { 0.5, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.2 @@ -381,9 +381,9 @@ TEST_F(EnergyCorrectionTest, DoubleCounting_Energy) for (int m1 = 0; m1 < m_size; m1++) for (int m2 = 0; m2 < m_size; m2++) { - double pot_onsite = (m1 == m2) ? U * (0.5 - locale[m1 * m_size + m2]) - : -U * locale[m1 * m_size + m2]; - e_dc += pot_onsite * locale[m2 * m_size + m1]; + double pot_onsite = (m1 == m2) ? U * (0.5 - occ_mat[m1 * m_size + m2]) + : -U * occ_mat[m1 * m_size + m2]; + e_dc += pot_onsite * occ_mat[m2 * m_size + m1]; } // Only diagonal: m=0: 0*0.5=0, m=1: 0.8*0.3=0.24, m=2: 1.2*0.2=0.24 diff --git a/source/source_lcao/module_dftu/test/dftu_pw_test.cpp b/source/source_lcao/module_dftu/test/dftu_pw_test.cpp index dc838e1db2..bea2662642 100644 --- a/source/source_lcao/module_dftu/test/dftu_pw_test.cpp +++ b/source/source_lcao/module_dftu/test/dftu_pw_test.cpp @@ -72,18 +72,18 @@ TEST_F(DftuPwTest, BecpIndexNspin12vs4) TEST_F(DftuPwTest, PotOnsitePotNspin1_DiagonalLocale) { - // For nspin=1: pot_onsite[m1,m2] = U * (0.5*delta(m1,m2) - locale[m2*m_size+m1]) - // With diagonal locale: locale[m,m] = 0.3 + // For nspin=1: pot_onsite[m1,m2] = U * (0.5*delta(m1,m2) - occ_mat[m2*m_size+m1]) + // With diagonal occ_mat: occ_mat[m,m] = 0.3 const double U_val = 4.0; const int m_size = 5; // d-orbital: 2*2+1 const int size = m_size * m_size; - std::vector locale_c(size, 0.0); + std::vector occ_mat_c(size, 0.0); for (int m = 0; m < m_size; m++) - locale_c[m * m_size + m] = 0.3; // diagonal + occ_mat_c[m * m_size + m] = 0.3; // diagonal std::vector> pot_onsite(size, {0.0, 0.0}); - dftu_pw::compute_pot_onsite_scalar(pot_onsite.data(), locale_c.data(), U_val, 0.5, 1.0, m_size); + dftu_pw::compute_pot_onsite_scalar(pot_onsite.data(), occ_mat_c.data(), U_val, 0.5, 1.0, m_size); // diagonal: U*(0.5 - 0.3) = 4.0*0.2 = 0.8 for (int m = 0; m < m_size; m++) @@ -95,20 +95,20 @@ TEST_F(DftuPwTest, PotOnsitePotNspin1_DiagonalLocale) TEST_F(DftuPwTest, PotOnsitePotNspin2_TwoSpinChannels) { - // nspin=2: two independent spin channels with same formula pot_onsite = U*(0.5*delta - locale) + // nspin=2: two independent spin channels with same formula pot_onsite = U*(0.5*delta - occ_mat) const double U_val = 5.0; const int m_size = 3; const int size = m_size * m_size; - std::vector locale_up(size, 0.0); - std::vector locale_dn(size, 0.0); - locale_up[0] = 0.4; // locale_up(0,0) = 0.4 - locale_dn[0] = 0.1; // locale_dn(0,0) = 0.1 + std::vector occ_mat_up(size, 0.0); + std::vector occ_mat_dn(size, 0.0); + occ_mat_up[0] = 0.4; // occ_mat_up(0,0) = 0.4 + occ_mat_dn[0] = 0.1; // occ_mat_dn(0,0) = 0.1 std::vector> pot_onsite_up(size, {0.0, 0.0}); std::vector> pot_onsite_dn(size, {0.0, 0.0}); - dftu_pw::compute_pot_onsite_scalar(pot_onsite_up.data(), locale_up.data(), U_val, 0.5, 0.5, m_size); - dftu_pw::compute_pot_onsite_scalar(pot_onsite_dn.data(), locale_dn.data(), U_val, 0.5, 0.5, m_size); + dftu_pw::compute_pot_onsite_scalar(pot_onsite_up.data(), occ_mat_up.data(), U_val, 0.5, 0.5, m_size); + dftu_pw::compute_pot_onsite_scalar(pot_onsite_dn.data(), occ_mat_dn.data(), U_val, 0.5, 0.5, m_size); // pot_onsite_up[0,0] = U*(0.5 - 0.4) = 0.5 EXPECT_DOUBLE_EQ(pot_onsite_up[0].real(), 0.5); @@ -151,33 +151,33 @@ TEST_F(DftuPwTest, PotOnsitePotNspin4_PauliTransform) TEST_F(DftuPwTest, EnergyNspin12_DiagonalLocale) { - // E_U = sum_{m1,m2} U * weight_eu * locale[m2,m1] * locale[m1,m2] + // E_U = sum_{m1,m2} U * weight_eu * occ_mat[m2,m1] * occ_mat[m1,m2] // nspin=1: weight_eu = 1.0, nspin=2: weight_eu = 0.5 const double U_val = 4.0; const int m_size = 3; const int size = m_size * m_size; - std::vector locale_c(size, 0.0); - locale_c[0 * m_size + 0] = 0.5; - locale_c[1 * m_size + 1] = 0.3; - locale_c[2 * m_size + 2] = 0.2; + std::vector occ_mat_c(size, 0.0); + occ_mat_c[0 * m_size + 0] = 0.5; + occ_mat_c[1 * m_size + 1] = 0.3; + occ_mat_c[2 * m_size + 2] = 0.2; // nspin=1: E = U * 1.0 * (0.5^2 + 0.3^2 + 0.2^2) = 4 * 0.38 = 1.52 std::vector> pot_onsite_nspin1(size, {0.0, 0.0}); double energy_u = dftu_pw::compute_pot_onsite_scalar( - pot_onsite_nspin1.data(), locale_c.data(), U_val, 0.5, 1.0, m_size); + pot_onsite_nspin1.data(), occ_mat_c.data(), U_val, 0.5, 1.0, m_size); EXPECT_DOUBLE_EQ(energy_u, 1.52); // nspin=2: two spin channels, weight_eu = 0.5 - std::vector locale_up(size, 0.0), locale_dn(size, 0.0); - locale_up[0] = 0.4; locale_dn[0] = 0.6; + std::vector occ_mat_up(size, 0.0), occ_mat_dn(size, 0.0); + occ_mat_up[0] = 0.4; occ_mat_dn[0] = 0.6; std::vector> pot_onsite_up(size, {0.0, 0.0}); std::vector> pot_onsite_dn(size, {0.0, 0.0}); energy_u = 0.0; energy_u += dftu_pw::compute_pot_onsite_scalar( - pot_onsite_up.data(), locale_up.data(), U_val, 0.5, 0.5, m_size); + pot_onsite_up.data(), occ_mat_up.data(), U_val, 0.5, 0.5, m_size); energy_u += dftu_pw::compute_pot_onsite_scalar( - pot_onsite_dn.data(), locale_dn.data(), U_val, 0.5, 0.5, m_size); + pot_onsite_dn.data(), occ_mat_dn.data(), U_val, 0.5, 0.5, m_size); // E = U*0.5*(0.4^2 + 0.6^2) = 4*0.5*(0.16+0.36) = 1.04 EXPECT_DOUBLE_EQ(energy_u, 1.04); } @@ -191,17 +191,17 @@ TEST_F(DftuPwTest, EnergyNspin4_WithOffDiagonal) const double weight_eu = 0.25; // 4 Pauli components stored contiguously - std::vector locale_c(size * 4, 0.0); + std::vector occ_mat_c(size * 4, 0.0); // charge channel (is=0) - locale_c[0] = 0.5; locale_c[1] = 0.1; - locale_c[2] = 0.1; locale_c[3] = 0.5; + occ_mat_c[0] = 0.5; occ_mat_c[1] = 0.1; + occ_mat_c[2] = 0.1; occ_mat_c[3] = 0.5; // sigma_x (is=1) - locale_c[size + 0] = 0.2; locale_c[size + 1] = 0.0; - locale_c[size + 2] = 0.0; locale_c[size + 3] = 0.2; + occ_mat_c[size + 0] = 0.2; occ_mat_c[size + 1] = 0.0; + occ_mat_c[size + 2] = 0.0; occ_mat_c[size + 3] = 0.2; std::vector> pot_onsite(size * 4, {0.0, 0.0}); double energy_u = dftu_pw::compute_pot_onsite_spinor( - pot_onsite.data(), locale_c.data(), U_val, 1.0, weight_eu, m_size); + pot_onsite.data(), occ_mat_c.data(), U_val, 1.0, weight_eu, m_size); // is=0: 2*0.25*(0.5*0.5 + 0.1*0.1 + 0.1*0.1 + 0.5*0.5) = 0.26 // is=1: 2*0.25*(0.2*0.2 + 0 + 0 + 0.2*0.2) = 0.04 @@ -215,7 +215,7 @@ TEST_F(DftuPwTest, EnergyNspin4_WithOffDiagonal) TEST_F(DftuPwTest, LocaleAccumNspin12) { - // nspin=1/2: locale[m1*m_size+m2] += weight * real(conj(becp[m1]) * becp[m2]) + // nspin=1/2: occ_mat[m1*m_size+m2] += weight * real(conj(becp[m1]) * becp[m2]) const int m_size = 3, nkb = 5, begin_ih = 0, m_begin = 0, nbands = 2, ik = 0; std::vector> becp(nbands * nkb, {0.0, 0.0}); @@ -226,17 +226,17 @@ TEST_F(DftuPwTest, LocaleAccumNspin12) wg(0, 0) = 1.0; wg(0, 1) = 0.5; - std::vector locale_c(m_size * m_size, 0.0); + std::vector occ_mat_c(m_size * m_size, 0.0); dftu_pw::accumulate_occ_scalar( - locale_c.data(), becp.data(), nbands, nkb, + occ_mat_c.data(), becp.data(), nbands, nkb, begin_ih, m_begin, m_size, wg, ik); - // band0, w=1.0: locale[0,0] = 1.0*|1|^2 = 1.0 - // band1, w=0.5: locale[0,0] = 0.5*|0.5|^2 = 0.125 - EXPECT_DOUBLE_EQ(locale_c[0], 1.125); + // band0, w=1.0: occ_mat[0,0] = 1.0*|1|^2 = 1.0 + // band1, w=0.5: occ_mat[0,0] = 0.5*|0.5|^2 = 0.125 + EXPECT_DOUBLE_EQ(occ_mat_c[0], 1.125); - // locale[1,1]: band0 = 1.0*|i|^2 = 1.0, band1 = 0.5*|(0.5,-0.5)|^2 = 0.25 - EXPECT_DOUBLE_EQ(locale_c[4], 1.25); + // occ_mat[1,1]: band0 = 1.0*|i|^2 = 1.0, band1 = 0.5*|(0.5,-0.5)|^2 = 0.25 + EXPECT_DOUBLE_EQ(occ_mat_c[4], 1.25); } TEST_F(DftuPwTest, LocaleAccumNspin4_PauliComponents) @@ -246,10 +246,10 @@ TEST_F(DftuPwTest, LocaleAccumNspin4_PauliComponents) // occ[1] = w * conj(becp_up[m1]) * becp_dn[m2] // occ[2] = w * conj(becp_dn[m1]) * becp_up[m2] // occ[3] = w * conj(becp_dn[m1]) * becp_dn[m2] - // locale[ind] += (occ[0]+occ[3]).real() -- charge - // locale[ind+size] += (occ[1]+occ[2]).real() -- sigma_x - // locale[ind+2*size] += (occ[1]-occ[2]).imag() -- sigma_y - // locale[ind+3*size] += (occ[0]-occ[3]).real() -- sigma_z + // occ_mat[ind] += (occ[0]+occ[3]).real() -- charge + // occ_mat[ind+size] += (occ[1]+occ[2]).real() -- sigma_x + // occ_mat[ind+2*size] += (occ[1]-occ[2]).imag() -- sigma_y + // occ_mat[ind+3*size] += (occ[0]-occ[3]).real() -- sigma_z const int m_size = 1, nkb = 2, nbands = 1, npol = 2, ik = 0; std::vector> becp(nbands * 2 * nkb, {0.0, 0.0}); @@ -257,20 +257,20 @@ TEST_F(DftuPwTest, LocaleAccumNspin4_PauliComponents) becp[nkb] = {0.0, 0.6}; // becp_dn[m=0] const int size = m_size * m_size; - std::vector locale_c(size * 4, 0.0); + std::vector occ_mat_c(size * 4, 0.0); ModuleBase::matrix wg(1, nbands); wg(0, 0) = 1.0; dftu_pw::accumulate_occ_spinor( - locale_c.data(), becp.data(), nbands, npol, nkb, + occ_mat_c.data(), becp.data(), nbands, npol, nkb, 0, 0, m_size, wg, ik); // becp_up = (0.8, 0), becp_dn = (0, 0.6) // occ[0] = 0.64, occ[1] = (0, 0.48), occ[2] = (0, -0.48), occ[3] = 0.36 - EXPECT_DOUBLE_EQ(locale_c[0], 1.0); // charge: (0.64+0.36).real = 1.0 - EXPECT_DOUBLE_EQ(locale_c[1], 0.0); // sigma_x: (occ1+occ2).real = 0 - EXPECT_DOUBLE_EQ(locale_c[2], 0.96); // sigma_y: (occ1-occ2).imag = 0.96 - EXPECT_DOUBLE_EQ(locale_c[3], 0.28); // sigma_z: (occ0-occ3).real = 0.28 + EXPECT_DOUBLE_EQ(occ_mat_c[0], 1.0); // charge: (0.64+0.36).real = 1.0 + EXPECT_DOUBLE_EQ(occ_mat_c[1], 0.0); // sigma_x: (occ1+occ2).real = 0 + EXPECT_DOUBLE_EQ(occ_mat_c[2], 0.96); // sigma_y: (occ1-occ2).imag = 0.96 + EXPECT_DOUBLE_EQ(occ_mat_c[3], 0.28); // sigma_z: (occ0-occ3).real = 0.28 } // ===================================================================== @@ -288,7 +288,7 @@ TEST_F(DftuPwTest, MultiAtomSplitLayout_Nspin2) // pot_uterm_pw_index: split layout, each atom gets `size` entries std::vector pot_uterm_pw_index = {0, size}; - // Simulate locale values for both atoms + // Simulate occ_mat values for both atoms std::vector loc_up[2], loc_dn[2]; for (int i = 0; i < 2; i++) { loc_up[i].assign(size, 0.0); loc_dn[i].assign(size, 0.0); From 342a8c621c561281aaa5cb40c2cf8aee017122c3 Mon Sep 17 00:00:00 2001 From: abacus_fixer Date: Wed, 26 Aug 2026 18:10:57 +0800 Subject: [PATCH 23/23] refactor(dftu): remove redundant includes in module_pwdft dftu files - dftu_base.h: drop klist.h (UnitCell from unitcell.h, matrix via charge_mixing.h) - dftu_base.cpp: drop // (no usage) - dftu_output.cpp: drop / (no usage); replace parameter.h with global_variable.h (GlobalV source, PARAM unused) - dftu_cal_occ_pw.cpp: replace parameter.h with global_variable.h (GlobalV source, PARAM unused) --- source/source_pw/module_pwdft/dftu_base.cpp | 3 --- source/source_pw/module_pwdft/dftu_base.h | 1 - source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp | 2 +- source/source_pw/module_pwdft/dftu_output.cpp | 4 +--- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/source/source_pw/module_pwdft/dftu_base.cpp b/source/source_pw/module_pwdft/dftu_base.cpp index 8290c7fec4..d54b8dc30e 100644 --- a/source/source_pw/module_pwdft/dftu_base.cpp +++ b/source/source_pw/module_pwdft/dftu_base.cpp @@ -6,11 +6,8 @@ #include "source_base/timer.h" #include "source_io/module_parameter/parameter.h" -#include -#include #include #include -#include #include #include diff --git a/source/source_pw/module_pwdft/dftu_base.h b/source/source_pw/module_pwdft/dftu_base.h index 29561e1235..8aa9d455d9 100644 --- a/source/source_pw/module_pwdft/dftu_base.h +++ b/source/source_pw/module_pwdft/dftu_base.h @@ -1,7 +1,6 @@ #ifndef DFTU_BASE_H #define DFTU_BASE_H -#include "source_cell/klist.h" #include "source_cell/unitcell.h" #include "source_estate/module_charge/charge_mixing.h" diff --git a/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp b/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp index 35fb8922c0..54848f456c 100644 --- a/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp +++ b/source/source_pw/module_pwdft/dftu_cal_occ_pw.cpp @@ -2,7 +2,7 @@ #include "source_pw/module_pwdft/dftu_tools_pw.h" #include "source_pw/module_pwdft/onsite_proj.h" #include "source_base/parallel_reduce.h" -#include "source_io/module_parameter/parameter.h" +#include "source_base/global_variable.h" #include "source_base/timer.h" #include "source_base/parallel_global.h" diff --git a/source/source_pw/module_pwdft/dftu_output.cpp b/source/source_pw/module_pwdft/dftu_output.cpp index 7236804449..0f2aee7615 100644 --- a/source/source_pw/module_pwdft/dftu_output.cpp +++ b/source/source_pw/module_pwdft/dftu_output.cpp @@ -3,14 +3,12 @@ #include "source_pw/module_pwdft/dftu_base.h" #include "source_base/constants.h" #include "source_base/global_function.h" +#include "source_base/global_variable.h" #include "source_base/timer.h" -#include "source_io/module_parameter/parameter.h" #include -#include #include #include -#include #include // local inline helpers for eigenvalue calculation