Skip to content
Merged
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
37 changes: 36 additions & 1 deletion source/source_io/module_parameter/read_inp_sys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1032,11 +1032,46 @@ 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 Kohn-Sham DFT+U and DeltaSpin onsite corrections require double precision.
PW RT-TDDFT does not support DFT+U or spin constraints at any 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");
Comment thread
lanshuyue marked this conversation as resolved.
Resolved
if (pw_onsite_solver && inp.precision == "single")
{
if (inp.esolver_type == "tddft")
{
if (inp.dft_plus_u != 0)
{
ModuleBase::WARNING_QUIT(
"ReadInput",
"PW RT-TDDFT does not support DFT+U at any precision; set dft_plus_u=0.");
}
if (inp.sc_mag_switch)
{
ModuleBase::WARNING_QUIT(
"ReadInput",
"PW RT-TDDFT does not support spin constraints at any precision; set sc_mag_switch=false.");
}
}
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
47 changes: 47 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,53 @@ class InputTest : public testing::Test
}
};

TEST_F(InputTest, PwOnsiteRequiresDoublePrecision)
{
ModuleIO::ReadInput readinput(0);
std::vector<std::pair<std::string, ModuleIO::Input_Item>>::iterator 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 RT-TDDFT does not support spin constraints at any precision"));

inp.sc_mag_switch = false;
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 RT-TDDFT does not support DFT+U at any precision"));

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
8 changes: 6 additions & 2 deletions source/source_pw/module_pwdft/hamilt_pw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,14 @@ HamiltPW<T, Device>::HamiltPW(elecstate::Potential* pot_in,
this->ops->add(nonlocal);
}
}
if (PARAM.inp.sc_mag_switch || PARAM.inp.dft_plus_u)
const bool cal_delta_spin = PARAM.inp.sc_mag_switch;
const int dft_plus_u = PARAM.inp.dft_plus_u;
if (cal_delta_spin || dft_plus_u)
{
const int nspin = PARAM.inp.nspin;
const bool cal_dftu = dft_plus_u > 0;
Operator<T, Device>* onsite_proj
= new OnsiteProj<OperatorPW<T, Device>>(isk, ucell, p_dftu, PARAM.inp.sc_mag_switch, (PARAM.inp.dft_plus_u > 0));
= new OnsiteProj<OperatorPW<T, Device>>(isk, ucell, p_dftu, nspin, cal_delta_spin, cal_dftu);
this->ops->add(onsite_proj);
}
if (exx_info && exx_info->cal_exx)
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