@@ -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