From 7df13fa89513e8227924262bf1541a46c987b14e Mon Sep 17 00:00:00 2001 From: lanshuyue <2000011337@stu.pku.edu.cn> Date: Thu, 29 Oct 2026 00:55:24 +0800 Subject: [PATCH 1/2] Reject single-precision PW onsite corrections --- .../module_parameter/read_inp_sys.cpp | 21 +++++++++- .../test_serial/read_input_item_test.cpp | 38 +++++++++++++++++++ source/source_pw/module_pwdft/hamilt_pw.cpp | 1 + source/source_pw/module_pwdft/op_pw_proj.cpp | 10 +++-- source/source_pw/module_pwdft/op_pw_proj.h | 3 ++ 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/source/source_io/module_parameter/read_inp_sys.cpp b/source/source_io/module_parameter/read_inp_sys.cpp index 43adbfc8169..8d83f3edb1e 100644 --- a/source/source_io/module_parameter/read_inp_sys.cpp +++ b/source/source_io/module_parameter/read_inp_sys.cpp @@ -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"); + 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") { diff --git a/source/source_io/test_serial/read_input_item_test.cpp b/source/source_io/test_serial/read_input_item_test.cpp index b1221ff0b77..f6f2e886370 100644 --- a/source/source_io/test_serial/read_input_item_test.cpp +++ b/source/source_io/test_serial/read_input_item_test.cpp @@ -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); diff --git a/source/source_pw/module_pwdft/hamilt_pw.cpp b/source/source_pw/module_pwdft/hamilt_pw.cpp index d3d284643f5..ffb2c1f63ad 100644 --- a/source/source_pw/module_pwdft/hamilt_pw.cpp +++ b/source/source_pw/module_pwdft/hamilt_pw.cpp @@ -175,6 +175,7 @@ HamiltPW::HamiltPW(elecstate::Potential* pot_in, Operator* onsite_proj = new OnsiteProj>(isk, ucell, p_dftu, + PARAM.inp.nspin, PARAM.inp.sc_mag_switch, (PARAM.inp.dft_plus_u > 0)); this->ops->add(onsite_proj); diff --git a/source/source_pw/module_pwdft/op_pw_proj.cpp b/source/source_pw/module_pwdft/op_pw_proj.cpp index fd469e7ce53..008b1a616f8 100644 --- a/source/source_pw/module_pwdft/op_pw_proj.cpp +++ b/source/source_pw/module_pwdft/op_pw_proj.cpp @@ -15,6 +15,7 @@ template OnsiteProj>::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) { @@ -25,6 +26,7 @@ OnsiteProj>::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 @@ -149,7 +151,7 @@ void OnsiteProj>::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; } @@ -290,9 +292,9 @@ void OnsiteProj>::cal_ps_dftu( this->setup_pw_dftu_indices(); } - const int isk_val = (PARAM.inp.nspin == 2) ? this->isk[this->ik] : 0; - const std::complex* 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* 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()( this->ctx, diff --git a/source/source_pw/module_pwdft/op_pw_proj.h b/source/source_pw/module_pwdft/op_pw_proj.h index 9a07a561ac0..1c781458bad 100644 --- a/source/source_pw/module_pwdft/op_pw_proj.h +++ b/source/source_pw/module_pwdft/op_pw_proj.h @@ -28,6 +28,7 @@ class OnsiteProj> : public OperatorPW 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); @@ -67,6 +68,8 @@ class OnsiteProj> : public OperatorPW Plus_U_Base* dftu = nullptr; + int nspin = 1; + mutable int* ip_iat = nullptr; mutable T* lambda_coeff = nullptr; mutable int* orb_l_iat = nullptr; From e958bea03e81ee773bf16159a26b1573cb2d3297 Mon Sep 17 00:00:00 2001 From: lanshuyue <2000011337@stu.pku.edu.cn> Date: Mon, 2 Nov 2026 00:58:11 +0800 Subject: [PATCH 2/2] Clarify RT-TDDFT onsite precision diagnostics --- .../module_parameter/read_inp_sys.cpp | 18 +++++++++++++++++- .../test_serial/read_input_item_test.cpp | 10 +++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/source/source_io/module_parameter/read_inp_sys.cpp b/source/source_io/module_parameter/read_inp_sys.cpp index 8d83f3edb1e..3262537af6f 100644 --- a/source/source_io/module_parameter/read_inp_sys.cpp +++ b/source/source_io/module_parameter/read_inp_sys.cpp @@ -999,7 +999,8 @@ Available options are: item.description = R"(Specifies the precision when performing scf calculation. * single: single precision * double: double precision -PW DFT+U and DeltaSpin onsite corrections require 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); @@ -1009,6 +1010,21 @@ PW DFT+U and DeltaSpin onsite corrections require double precision.)"; && (inp.esolver_type == "ksdft" || inp.esolver_type == "tddft"); 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( diff --git a/source/source_io/test_serial/read_input_item_test.cpp b/source/source_io/test_serial/read_input_item_test.cpp index f6f2e886370..55c8f80743a 100644 --- a/source/source_io/test_serial/read_input_item_test.cpp +++ b/source/source_io/test_serial/read_input_item_test.cpp @@ -90,7 +90,15 @@ TEST_F(InputTest, PwOnsiteRequiresDoublePrecision) 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")); + 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;