Skip to content

Commit bff0e8f

Browse files
author
abacus_fixer
committed
fix(dftu): clear stale YukawaScreening when init_base reruns with yukawa_potential=false
Before the refactor, use_yukawa_ was assigned on every init_base() call, so the state always matched the latest argument. Now the state is inferred from yukawa_, but the pointer was only updated on the true branch; a true -> false re-initialization left a stale object alive. PW's before_scf() -> setup_pot() may call init_base() repeatedly on the same Plus_U object, so clear the pointer in the disabled branch to preserve the old semantics. Add unit tests for both switch directions (reverse-verified: they fail with the stale-object behavior).
1 parent b191c7a commit bff0e8f

3 files changed

Lines changed: 153 additions & 0 deletions

File tree

source/source_pw/module_pwdft/dftu_base.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ void Plus_U_Base::init_base(UnitCell& cell,
131131
this->yukawa_.reset(new YukawaScreening());
132132
this->yukawa_->init(cell, orbital_corr, yukawa_lambda);
133133
}
134+
else
135+
{
136+
// Clear any stale object from a previous init_base() call with
137+
// yukawa_potential == true, preserving the old explicit-flag semantics.
138+
this->yukawa_.reset();
139+
}
134140

135141
if (occ_mat_ctrl != 0)
136142
{

source/source_pw/module_pwdft/test/CMakeLists.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,31 @@ AddTest(
2828
SOURCES radial_proj_test.cpp ../radial_proj.cpp
2929
)
3030

31+
AddTest(
32+
TARGET MODULE_PW_dftu_base_test
33+
LIBS parameter base device
34+
SOURCES dftu_base_test.cpp
35+
../dftu_base.cpp
36+
../dftu_base_io.cpp
37+
../yukawa_screening.cpp
38+
../../../source_estate/occ_matrix.cpp
39+
../../../source_cell/unitcell.cpp
40+
../../../source_cell/atom_spec.cpp
41+
../../../source_cell/atom_pseudo.cpp
42+
../../../source_cell/pseudo.cpp
43+
../../../source_cell/magnetism.cpp
44+
../../../source_cell/sep.cpp
45+
../../../source_cell/sep_cell.cpp
46+
../../../source_cell/read_atom_species.cpp
47+
../../../source_cell/read_atoms.cpp
48+
../../../source_cell/read_atoms_helper.cpp
49+
../../../source_cell/cell_tools.cpp
50+
../../../source_cell/print_cell.cpp
51+
../../../source_cell/read_orb.cpp
52+
../../../source_cell/read_stru.cpp
53+
../../../source_cell/bcast_cell.cpp
54+
)
55+
3156
AddTest(
3257
TARGET MODULE_PW_structure_factor_test
3358
LIBS parameter base device planewave
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/**********************************************
2+
* Unit tests for Plus_U_Base::init_base.
3+
*
4+
* Focus: the Yukawa state must follow the
5+
* yukawa_potential argument on every call,
6+
* including a true -> false re-initialization
7+
* (before_scf() -> setup_pot() may call
8+
* init_base() repeatedly on the same object).
9+
***********************************************/
10+
11+
#include "source_pw/module_pwdft/dftu_base.h"
12+
13+
#include "source_cell/atom_spec.h"
14+
#include "source_cell/unitcell.h"
15+
16+
#include "gtest/gtest.h"
17+
18+
#include <vector>
19+
20+
class DFTUBaseTest : public testing::Test
21+
{
22+
protected:
23+
UnitCell ucell;
24+
25+
void SetUp() override
26+
{
27+
// Minimal one-atom cell: d channel available (nwl = 2),
28+
// one chi for each of s / p / d, so nw = 1 + 3 + 5 = 9.
29+
const int nw = 9;
30+
31+
ucell.ntype = 1;
32+
ucell.nat = 1;
33+
ucell.atoms = new Atom[ucell.ntype];
34+
ucell.iat2it = new int[ucell.nat];
35+
ucell.iat2ia = new int[ucell.nat];
36+
ucell.atoms[0].tau.resize(ucell.nat);
37+
ucell.atoms[0].taud.resize(ucell.nat);
38+
ucell.itia2iat.create(ucell.ntype, ucell.nat);
39+
for (int iat = 0; iat < ucell.nat; iat++)
40+
{
41+
ucell.iat2it[iat] = 0;
42+
ucell.iat2ia[iat] = iat;
43+
ucell.itia2iat(0, iat) = iat;
44+
ucell.atoms[0].tau[iat] = ModuleBase::Vector3<double>(0.0, 0.0, 0.0);
45+
ucell.atoms[0].taud[iat] = ModuleBase::Vector3<double>(0.0, 0.0, 0.0);
46+
}
47+
ucell.atoms[0].na = 1;
48+
ucell.atoms[0].label = "Fe";
49+
ucell.atoms[0].nwl = 2;
50+
ucell.atoms[0].l_nchi = {1, 1, 1};
51+
ucell.atoms[0].nw = nw;
52+
ucell.atoms[0].iw2l.resize(nw);
53+
ucell.atoms[0].iw2n.resize(nw);
54+
ucell.atoms[0].iw2m.resize(nw);
55+
int iw = 0;
56+
for (int l = 0; l <= ucell.atoms[0].nwl; l++)
57+
{
58+
for (int m = 0; m < 2 * l + 1; m++)
59+
{
60+
ucell.atoms[0].iw2l[iw] = l;
61+
ucell.atoms[0].iw2n[iw] = 0;
62+
ucell.atoms[0].iw2m[iw] = m;
63+
iw++;
64+
}
65+
}
66+
ucell.set_iat2iwt(1);
67+
}
68+
69+
void TearDown() override
70+
{
71+
// set_atom_flag is false, so ~UnitCell() skips atoms but frees
72+
// iat2it / iat2ia itself; only atoms must be deleted here.
73+
delete[] ucell.atoms;
74+
}
75+
76+
/// Call init_base with the given Yukawa switch on a fresh d orbital
77+
void init_dftu(Plus_U_Base& dftu, const bool yukawa_potential)
78+
{
79+
const std::vector<int> orbital_corr = {2};
80+
const std::vector<double> hubbard_u = {0.0};
81+
dftu.init_base(ucell,
82+
1, // npol
83+
2, // nspin
84+
orbital_corr,
85+
yukawa_potential,
86+
0.5, // yukawa_lambda
87+
"", // global_readin_dir
88+
"", // global_out_dir
89+
"none", // init_chg
90+
"cpu", // device
91+
1, // kpar
92+
hubbard_u,
93+
0.0, // uramping
94+
0, // occ_mat_ctrl
95+
0); // mixing_dftu
96+
}
97+
};
98+
99+
/// After a true -> false re-initialization the Yukawa object must be
100+
/// released so that use_yukawa() reflects the latest argument.
101+
TEST_F(DFTUBaseTest, InitBaseYukawaTrueThenFalseClearsState)
102+
{
103+
Plus_U_Base dftu;
104+
105+
init_dftu(dftu, true);
106+
EXPECT_TRUE(dftu.use_yukawa());
107+
108+
init_dftu(dftu, false);
109+
EXPECT_FALSE(dftu.use_yukawa());
110+
}
111+
112+
/// A false -> true re-initialization must create the Yukawa object.
113+
TEST_F(DFTUBaseTest, InitBaseYukawaFalseThenTrueCreatesObject)
114+
{
115+
Plus_U_Base dftu;
116+
117+
init_dftu(dftu, false);
118+
EXPECT_FALSE(dftu.use_yukawa());
119+
120+
init_dftu(dftu, true);
121+
EXPECT_TRUE(dftu.use_yukawa());
122+
}

0 commit comments

Comments
 (0)