Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion source/source_io/module_parameter/read_inp_sys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -998,11 +998,30 @@ Available options are:
item.type = "String";
item.description = R"(Specifies the precision when performing scf calculation.
* single: single precision
* double: double precision)";
* double: double precision
PW DFT+U and DeltaSpin onsite corrections require double precision.)";
item.default_value = "double";
item.set_availability("basis_type==pw");
read_sync_string(input.precision);
item.check_value = [](const Input_Item& item, const Parameter& para) {
const Input_para& inp = para.inp;
const bool pw_onsite_solver = inp.basis_type == "pw"
&& (inp.esolver_type == "ksdft" || inp.esolver_type == "tddft");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: For esolver_type=tddft, switching to double precision still leaves DFT+U and spin constraints unsupported (pw::check_td_input). Please identify that solver restriction in this diagnostic while preserving early rejection.

if (pw_onsite_solver && inp.precision == "single")
{
if (inp.dft_plus_u != 0)
{
ModuleBase::WARNING_QUIT(
"ReadInput",
"PW DFT+U requires precision = double; single precision onsite corrections are not supported.");
}
if (inp.sc_mag_switch)
{
ModuleBase::WARNING_QUIT(
"ReadInput",
"PW DeltaSpin requires precision = double; single precision onsite corrections are not supported.");
}
}
// cpu single precision is not supported while float_fftw lib is not available
if (para.inp.device == "cpu" && para.inp.precision == "single")
{
Expand Down
38 changes: 38 additions & 0 deletions source/source_io/test_serial/read_input_item_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,44 @@ class InputTest : public testing::Test
}
};

TEST_F(InputTest, PwOnsiteRequiresDoublePrecision)
{
ModuleIO::ReadInput readinput(0);
auto item = find_label("precision", readinput.input_lists);
ASSERT_NE(item, readinput.input_lists.end());

Parameter param;
Input_para& inp = TestParameters::input(param);
inp.basis_type = "pw";
inp.esolver_type = "ksdft";
inp.device = "gpu";
inp.precision = "single";

inp.dft_plus_u = 1;
testing::internal::CaptureStdout();
EXPECT_EXIT(check_item(item->second, param), ::testing::ExitedWithCode(1), "");
EXPECT_THAT(testing::internal::GetCapturedStdout(), testing::HasSubstr("PW DFT+U requires precision = double"));

inp.dft_plus_u = 0;
inp.sc_mag_switch = true;
testing::internal::CaptureStdout();
EXPECT_EXIT(check_item(item->second, param), ::testing::ExitedWithCode(1), "");
EXPECT_THAT(testing::internal::GetCapturedStdout(), testing::HasSubstr("PW DeltaSpin requires precision = double"));

inp.esolver_type = "tddft";
testing::internal::CaptureStdout();
EXPECT_EXIT(check_item(item->second, param), ::testing::ExitedWithCode(1), "");
EXPECT_THAT(testing::internal::GetCapturedStdout(), testing::HasSubstr("PW DeltaSpin requires precision = double"));

inp.precision = "double";
inp.dft_plus_u = 1;
check_item(item->second, param);
inp.dft_plus_u = 0;
inp.sc_mag_switch = false;
inp.precision = "single";
check_item(item->second, param);
}

TEST_F(InputTest, InvalidExplicitDomainDoesNotReachReadOrResetHooks)
{
ModuleIO::ReadInput reader(0);
Expand Down
1 change: 1 addition & 0 deletions source/source_pw/module_pwdft/hamilt_pw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ HamiltPW<T, Device>::HamiltPW(elecstate::Potential* pot_in,
Operator<T, Device>* onsite_proj = new OnsiteProj<OperatorPW<T, Device>>(isk,
ucell,
p_dftu,
PARAM.inp.nspin,
PARAM.inp.sc_mag_switch,
(PARAM.inp.dft_plus_u > 0));
this->ops->add(onsite_proj);
Expand Down
10 changes: 6 additions & 4 deletions source/source_pw/module_pwdft/op_pw_proj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ template<typename T, typename Device>
OnsiteProj<OperatorPW<T, Device>>::OnsiteProj(const int* isk_in,
const UnitCell* ucell_in,
Plus_U_Base* p_dftu,
const int nspin_in,
const bool cal_delta_spin,
const bool cal_dftu)
{
Expand All @@ -25,6 +26,7 @@ OnsiteProj<OperatorPW<T, Device>>::OnsiteProj(const int* isk_in,
this->has_delta_spin = cal_delta_spin;
this->has_dftu = cal_dftu;
this->dftu = p_dftu; // mohan add 2025-11-08
this->nspin = nspin_in;
}

template<typename T, typename Device>
Expand Down Expand Up @@ -149,7 +151,7 @@ void OnsiteProj<OperatorPW<T, Device>>::cal_ps_delta_spin(const int npol, const
if (npol == 1)
{
int spin_sign = 1;
if (PARAM.inp.nspin == 2)
if (this->nspin == 2)
{
spin_sign = (this->isk[this->ik] == 0) ? 1 : -1;
}
Expand Down Expand Up @@ -290,9 +292,9 @@ void OnsiteProj<OperatorPW<T, Device>>::cal_ps_dftu(
this->setup_pw_dftu_indices();
}

const int isk_val = (PARAM.inp.nspin == 2) ? this->isk[this->ik] : 0;
const std::complex<double>* pot_onsite_host = dftu->get_uterm_mat_spin(PARAM.inp.nspin, isk_val);
const int pot_onsite_size = dftu->get_size_uterm_mat_spin(PARAM.inp.nspin);
const int isk_val = (this->nspin == 2) ? this->isk[this->ik] : 0;
const std::complex<double>* pot_onsite_host = dftu->get_uterm_mat_spin(this->nspin, isk_val);
const int pot_onsite_size = dftu->get_size_uterm_mat_spin(this->nspin);
syncmem_complex_h2d_op()(this->pot_onsite_device, pot_onsite_host, pot_onsite_size);
hamilt::onsite_ps_op<Real, Device>()(
this->ctx,
Expand Down
3 changes: 3 additions & 0 deletions source/source_pw/module_pwdft/op_pw_proj.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class OnsiteProj<OperatorPW<T, Device>> : public OperatorPW<T, Device>
OnsiteProj(const int* isk_in,
const UnitCell* ucell_in,
Plus_U_Base* p_dftu,
const int nspin_in,
const bool cal_delta_spin,
const bool cal_dftu);

Expand Down Expand Up @@ -67,6 +68,8 @@ class OnsiteProj<OperatorPW<T, Device>> : public OperatorPW<T, Device>

Plus_U_Base* dftu = nullptr;

int nspin = 1;

mutable int* ip_iat = nullptr;
mutable T* lambda_coeff = nullptr;
mutable int* orb_l_iat = nullptr;
Expand Down
Loading