Skip to content

Commit cf078bd

Browse files
author
abacus_fixer
committed
fix bugs
1 parent 1d3dded commit cf078bd

2 files changed

Lines changed: 72 additions & 1 deletion

File tree

source/source_lcao/force_stress_lcao.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,32 @@ void Force_Stress_LCAO<T>::getForceStress(UnitCell& ucell,
426426
}
427427
if (PARAM.inp.dft_plus_u == 2)
428428
{
429-
// Old DFT+U implementation (dft_plus_u==2) still needs ForceStressArrays
429+
// The legacy dft_plus_u==2 force/stress path is currently broken.
430+
//
431+
// Background: Plus_U::force_stress relies on ForceStressArrays
432+
// members DSloc_x/y/z (gamma_only) or DSloc_Rx/Ry/Rz (multik)
433+
// and DH_r being pre-allocated and filled with dS/dR data by the
434+
// main force flow (formerly ForceLcaoGamma::ftable). The DFT+U
435+
// step 2 refactor (commit 70c54c9d5a, 2026-01-23) removed the
436+
// main-flow ForceStressArrays because the operator-based force
437+
// calculation no longer needs it, but the legacy dft_plus_u==2
438+
// path still depends on it. The local fsr_dftu below is declared
439+
// without allocating those arrays, so any call into
440+
// cal_force_gamma / cal_stress_gamma / folding_matrix_k would
441+
// pass nullptr to pdgemm_ and crash with SIGSEGV.
442+
//
443+
// Until the legacy path is restored or re-implemented, we
444+
// explicitly reject dft_plus_u==2 with cal_force or cal_stress
445+
// enabled. SCF-only runs (no force/stress) are unaffected
446+
// because the energy is computed in cal_energy_correction,
447+
// which does not touch DSloc arrays. Use dft_plus_u=1 for
448+
// force/stress calculations.
449+
if (isforce || isstress)
450+
{
451+
ModuleBase::WARNING_QUIT("Force_Stress_LCAO::getForceStress",
452+
"dft_plus_u==2 with cal_force or cal_stress is currently broken; "
453+
"please use dft_plus_u=1 instead. See notes in source/source_lcao/force_stress_lcao.cpp.");
454+
}
430455
ForceStressArrays fsr_dftu;
431456
std::vector<std::vector<double>>* dmk_d = nullptr;
432457
std::vector<std::vector<std::complex<double>>>* dmk_c = nullptr;

source/source_lcao/module_dftu/dftu_force.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,52 @@ void Plus_U::force_stress(const UnitCell& ucell,
3636
ModuleBase::TITLE("Plus_U", "force_stress");
3737
ModuleBase::timer::start("Plus_U", "force_stress");
3838

39+
// Defensive null check: the legacy dft_plus_u==2 force/stress path
40+
// requires fsr.DSloc_x/y/z (gamma_only) or fsr.DSloc_Rx/Ry/Rz (multik)
41+
// and fsr.DH_r to be allocated and filled by the caller. If the caller
42+
// forgot to allocate them (as in force_stress_lcao.cpp where the local
43+
// fsr_dftu is created without allocation), we fail early with a clear
44+
// message instead of letting pdgemm_ dereference nullptr and crash.
45+
// See force_stress_lcao.cpp for the historical background.
46+
if (this->gamma_only_local)
47+
{
48+
if (this->cal_force
49+
&& (fsr.DSloc_x == nullptr || fsr.DSloc_y == nullptr || fsr.DSloc_z == nullptr))
50+
{
51+
ModuleBase::WARNING_QUIT("Plus_U::force_stress",
52+
"fsr.DSloc_x/y/z are nullptr in gamma_only path; the caller must allocate and fill them. "
53+
"See notes in source/source_lcao/force_stress_lcao.cpp.");
54+
}
55+
if (this->cal_stress
56+
&& (fsr.DSloc_x == nullptr || fsr.DSloc_y == nullptr || fsr.DSloc_z == nullptr
57+
|| fsr.DH_r == nullptr))
58+
{
59+
ModuleBase::WARNING_QUIT("Plus_U::force_stress",
60+
"fsr.DSloc_x/y/z or fsr.DH_r is nullptr in gamma_only path; "
61+
"the caller must allocate and fill them. "
62+
"See notes in source/source_lcao/force_stress_lcao.cpp.");
63+
}
64+
}
65+
else
66+
{
67+
if (this->cal_force
68+
&& (fsr.DSloc_Rx == nullptr || fsr.DSloc_Ry == nullptr || fsr.DSloc_Rz == nullptr))
69+
{
70+
ModuleBase::WARNING_QUIT("Plus_U::force_stress",
71+
"fsr.DSloc_Rx/Ry/Rz are nullptr in multik path; the caller must allocate and fill them. "
72+
"See notes in source/source_lcao/force_stress_lcao.cpp.");
73+
}
74+
if (this->cal_stress
75+
&& (fsr.DSloc_Rx == nullptr || fsr.DSloc_Ry == nullptr || fsr.DSloc_Rz == nullptr
76+
|| fsr.DH_r == nullptr))
77+
{
78+
ModuleBase::WARNING_QUIT("Plus_U::force_stress",
79+
"fsr.DSloc_Rx/Ry/Rz or fsr.DH_r is nullptr in multik path; "
80+
"the caller must allocate and fill them. "
81+
"See notes in source/source_lcao/force_stress_lcao.cpp.");
82+
}
83+
}
84+
3985
const int nlocal = this->nlocal;
4086

4187
if (this->cal_force)

0 commit comments

Comments
 (0)