Skip to content

Commit d49318f

Browse files
committed
add test
1 parent 9359dcc commit d49318f

3 files changed

Lines changed: 146 additions & 4 deletions

File tree

source/source_hamilt/module_xc/test/test_xc3.cpp

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,141 @@ TEST_F(XCTest_GRADCORR, set_xc_type)
152152
}
153153
}
154154

155+
// Regression test for an out-of-bounds read in gradcorr.
156+
// `set_xc_type("HF")` sets func_type = 4 (hybrid) but leaves func_id EMPTY, because pure
157+
// Hartree-Fock has no (semi-)local functional. gradcorr used to index func_id[0]/func_id[1]
158+
// unconditionally (see also the commented-out loop in XC_Functional::gcx_spin), reading back
159+
// whatever the previously selected functional had left in the cleared-but-not-deallocated
160+
// buffer. In the two-level EXX loop that predecessor is PBE (set_xc_first_loop), so a pure-HF
161+
// run silently picked up a PBE gradient correction (issue deepmodeling/abacus-develop#5404)
162+
//
163+
// Setting PBE *before* HF is therefore an essential part of this test: it is what leaves the
164+
// stale ids in the buffer, and without it the regression does not reproduce.
165+
class XCTest_GRADCORR_HF : public XCTest
166+
{
167+
protected:
168+
169+
double et1 = 0, vt1 = 0;
170+
ModuleBase::matrix v1;
171+
std::vector<double> stress1;
172+
173+
double et2 = 0, vt2 = 0;
174+
ModuleBase::matrix v2;
175+
std::vector<double> stress2;
176+
177+
double et4 = 0, vt4 = 0;
178+
ModuleBase::matrix v4;
179+
std::vector<double> stress4;
180+
181+
void SetUp()
182+
{
183+
const int nspin1 = 1;
184+
const int nspin2 = 2;
185+
const int nspin4 = 4;
186+
const bool domag = false;
187+
const bool domag_z = false;
188+
const bool domag_true = true;
189+
190+
ModulePW::PW_Basis rhopw;
191+
UnitCell ucell;
192+
Charge chr;
193+
194+
rhopw.nrxx = 5;
195+
rhopw.npw = 5;
196+
rhopw.nmaxgr = 5;
197+
rhopw.gcar = new ModuleBase::Vector3<double> [5];
198+
199+
ucell.tpiba = 1;
200+
ucell.magnet.lsign_ = true;
201+
unitcell::cal_ux(ucell, 4);
202+
203+
chr.rho = new double*[4];
204+
chr.rho[0] = new double[5];
205+
chr.rho[1] = new double[5];
206+
chr.rho[2] = new double[5];
207+
chr.rho[3] = new double[5];
208+
chr.rhog = new std::complex<double>*[2];
209+
chr.rhog[0] = new std::complex<double>[5];
210+
chr.rhog[1] = new std::complex<double>[5];
211+
212+
chr.rho_core = new double[5];
213+
chr.rhog_core = new std::complex<double>[5];
214+
215+
for(int i=0;i<5;i++)
216+
{
217+
chr.rho[0][i] = double(i);
218+
chr.rho[1][i] = 0.1*double(i);
219+
chr.rho[2][i] = chr.rho[0][i];
220+
chr.rho[3][i] = chr.rho[1][i];
221+
chr.rhog[0][i] = chr.rho[0][i];
222+
chr.rhog[1][i] = chr.rho[1][i];
223+
chr.rho_core[i] = 0;
224+
chr.rhog_core[i] = 0;
225+
rhopw.gcar[i]= 1;
226+
}
227+
228+
v1.create(1,5);
229+
v1.zero_out();
230+
v2.create(2,5);
231+
v2.zero_out();
232+
v4.create(4,5);
233+
v4.zero_out();
234+
235+
// leave PBE ids in func_id's buffer, then switch to pure HF
236+
XC_Functional::set_xc_type("PBE");
237+
XC_Functional::set_xc_type("HF");
238+
239+
const double hybrid_alpha = 1.0;
240+
const double hse_omega = 0.0;
241+
XC_Functional::gradcorr(et1,vt1,v1,&chr,&rhopw,&ucell,stress1,false,nspin1,domag,domag_z, hybrid_alpha, hse_omega);
242+
XC_Functional::gradcorr(et1,vt1,v1,&chr,&rhopw,&ucell,stress1,true, nspin1,domag,domag_z, hybrid_alpha, hse_omega);
243+
244+
XC_Functional::gradcorr(et2,vt2,v2,&chr,&rhopw,&ucell,stress2,false,nspin2,domag,domag_z, hybrid_alpha, hse_omega);
245+
XC_Functional::gradcorr(et2,vt2,v2,&chr,&rhopw,&ucell,stress2,true, nspin2,domag,domag_z, hybrid_alpha, hse_omega);
246+
247+
XC_Functional::gradcorr(et4,vt4,v4,&chr,&rhopw,&ucell,stress4,false,nspin4,domag_true,domag_z, hybrid_alpha, hse_omega);
248+
XC_Functional::gradcorr(et4,vt4,v4,&chr,&rhopw,&ucell,stress4,true, nspin4,domag_true,domag_z, hybrid_alpha, hse_omega);
249+
}
250+
};
251+
252+
TEST_F(XCTest_GRADCORR_HF, no_local_functional)
253+
{
254+
// the state the fixture ran under: hybrid, but with no (semi-)local functional
255+
EXPECT_EQ(XC_Functional::get_func_type(), 4);
256+
EXPECT_TRUE(XC_Functional::get_func_id().empty());
257+
258+
// pure HF must contribute exactly nothing through the gradient correction
259+
EXPECT_DOUBLE_EQ(et1, 0.0);
260+
EXPECT_DOUBLE_EQ(vt1, 0.0);
261+
EXPECT_DOUBLE_EQ(et2, 0.0);
262+
EXPECT_DOUBLE_EQ(vt2, 0.0);
263+
EXPECT_DOUBLE_EQ(et4, 0.0);
264+
EXPECT_DOUBLE_EQ(vt4, 0.0);
265+
266+
for(int i=0;i<5;i++)
267+
{
268+
EXPECT_DOUBLE_EQ(v1(0,i), 0.0);
269+
EXPECT_DOUBLE_EQ(v2(0,i), 0.0);
270+
EXPECT_DOUBLE_EQ(v2(1,i), 0.0);
271+
for(int is=0;is<4;is++)
272+
{
273+
EXPECT_DOUBLE_EQ(v4(is,i), 0.0);
274+
}
275+
}
276+
277+
// `Stress_Func::stress_gga` guards only on func_type, so it reaches this path for HF and
278+
// then reads stress_gga[0..8]: the tensor must come back sized and zeroed, not empty.
279+
ASSERT_EQ(stress1.size(), 9);
280+
ASSERT_EQ(stress2.size(), 9);
281+
ASSERT_EQ(stress4.size(), 9);
282+
for(int i=0;i<9;i++)
283+
{
284+
EXPECT_DOUBLE_EQ(stress1[i], 0.0);
285+
EXPECT_DOUBLE_EQ(stress2[i], 0.0);
286+
EXPECT_DOUBLE_EQ(stress4[i], 0.0);
287+
}
288+
}
289+
155290
class XCTest_GRADWFC : public XCTest
156291
{
157292
protected:

source/source_hamilt/module_xc/xc_grad.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ void XC_Functional::gradcorr(
5757
// buffer (PBE, from set_xc_first_loop), producing a phantom XC energy and potential. (issue deepmodeling/abacus-develop#5404)
5858
if(func_id.empty())
5959
{
60+
// `Stress_Func::stress_gga` only guards on func_type (0/1) and unconditionally reads
61+
// stress_gga[0..8] afterwards, so hand back an explicit zero tensor rather than an
62+
// untouched (empty) vector.
63+
if(is_stress)
64+
{
65+
stress_gga.assign(9, 0.0);
66+
}
6067
return;
6168
}
6269

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
excitationenergyref1 1.500140
2-
excitationenergyref2 1.500670
3-
excitationenergyref3 1.322310
4-
excitationenergyref4 1.323240
1+
excitationenergyref1 1.531730
2+
excitationenergyref2 1.532420
3+
excitationenergyref3 1.353650
4+
excitationenergyref4 1.354670
55
totaltimeref 1.94

0 commit comments

Comments
 (0)