From ed964fc696e4079d69a9a29c77996b4aee511a2f Mon Sep 17 00:00:00 2001 From: Jiacheng Xu <13862180016@163.com> Date: Tue, 20 Oct 2026 17:24:30 +0800 Subject: [PATCH] fix(input): preserve explicit magnetic mixing parameters --- .../module_parameter/read_inp_estruc.cpp | 8 +-- .../test_serial/read_input_item_test.cpp | 66 +++++++++++++++++-- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/source/source_io/module_parameter/read_inp_estruc.cpp b/source/source_io/module_parameter/read_inp_estruc.cpp index b5841a81e3..a5054cb2b0 100644 --- a/source/source_io/module_parameter/read_inp_estruc.cpp +++ b/source/source_io/module_parameter/read_inp_estruc.cpp @@ -611,14 +611,10 @@ For spin-polarized calculations (nspin=2 or nspin=4) that are difficult to conve else if (para.input.nspin == 2) { para.input.mixing_beta = 0.4; - para.input.mixing_beta_mag = 1.6; - para.input.mixing_gg0_mag = 0.0; } else if (para.input.nspin == 4) // I will add this { para.input.mixing_beta = 0.4; - para.input.mixing_beta_mag = 1.6; - para.input.mixing_gg0_mag = 0.0; } } }; @@ -631,6 +627,8 @@ For spin-polarized calculations (nspin=2 or nspin=4) that are difficult to conve item.type = "Real"; item.description = R"(Mixing parameter of magnetic density. +An explicit nonnegative value is preserved even when mixing_beta is omitted. + If SCF convergence is difficult with spin polarization (nspin=2 or nspin=4), try reducing both mixing_beta and mixing_beta_mag simultaneously, e.g., mixing_beta=0.1 and mixing_beta_mag=0.1 or lower.)"; item.default_value = "4*mixing_beta, but the maximum value is 1.6."; @@ -725,6 +723,8 @@ For systems that are difficult to converge, particularly metallic systems, enabl item.type = "Real"; item.description = R"(Controls the Kerker preconditioner for magnetic-density mixing. It is disabled by default and is generally only recommended for systems whose magnetic density is difficult to converge. +An explicit value is preserved even when mixing_beta is omitted. + The magnetic-density Kerker preconditioner is bypassed when mixing_beta_mag <= 0.1, so mixing_gg0_mag has no effect in that regime. It is also unavailable when the charge-density Kerker preconditioner itself is bypassed.)"; item.default_value = "0.0"; item.unit = ""; 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 096b5c4515..13e5c77702 100644 --- a/source/source_io/test_serial/read_input_item_test.cpp +++ b/source/source_io/test_serial/read_input_item_test.cpp @@ -1357,6 +1357,62 @@ TEST_F(InputTest, HsOutputAliases) EXPECT_EQ(TestParameters::input(param).out_hsk[0], 1); } } +TEST_F(InputTest, PreserveExplicitMagneticMixing) +{ + const std::string filename = testing::TempDir() + "abacus_magnetic_mixing_INPUT"; + for (const int nspin : {1, 2, 4}) + { + const double expected_beta = nspin == 1 ? 0.8 : 0.4; + for (const bool explicit_beta : {false, true}) + { + SCOPED_TRACE(nspin); + SCOPED_TRACE(explicit_beta); + { + std::ofstream input(filename.c_str()); + input << "INPUT_PARAMETERS\nnspin " << nspin + << "\nmixing_beta_mag 0.2\nmixing_gg0_mag 0.7\n"; + if (explicit_beta) + { + input << "mixing_beta " << expected_beta << "\n"; + } + } + ModuleIO::ReadInput reader(0); + reader.check_ntype_flag = false; + Parameter param; + reader.read_parameters(param, filename); + EXPECT_DOUBLE_EQ(param.inp.mixing_beta, expected_beta); + EXPECT_DOUBLE_EQ(param.inp.mixing_beta_mag, 0.2); + EXPECT_DOUBLE_EQ(param.inp.mixing_gg0_mag, 0.7); + EXPECT_EQ(std::remove(filename.c_str()), 0); + } + } +} + +TEST_F(InputTest, DefaultMagneticMixing) +{ + const std::string filename = testing::TempDir() + "abacus_default_mixing_INPUT"; + for (const int nspin : {1, 2, 4}) + { + SCOPED_TRACE(nspin); + { + std::ofstream input(filename.c_str()); + input << "INPUT_PARAMETERS\nnspin " << nspin << "\n"; + } + ModuleIO::ReadInput reader(0); + reader.check_ntype_flag = false; + Parameter param; + reader.read_parameters(param, filename); + const double expected_beta = nspin == 1 ? 0.8 : 0.4; + EXPECT_DOUBLE_EQ(param.inp.mixing_beta, expected_beta); + EXPECT_DOUBLE_EQ(param.inp.mixing_gg0_mag, 0.0); + if (nspin != 1) + { + EXPECT_DOUBLE_EQ(param.inp.mixing_beta_mag, 1.6); + } + EXPECT_EQ(std::remove(filename.c_str()), 0); + } +} + TEST_F(InputTest, Item_test2) { ModuleIO::ReadInput readinput(0); @@ -1452,6 +1508,8 @@ TEST_F(InputTest, Item_test2) } { // mixing_beta auto it = find_label("mixing_beta", readinput.input_lists); + TestParameters::input(param).mixing_beta_mag = 0.2; + TestParameters::input(param).mixing_gg0_mag = 0.7; TestParameters::input(param).mixing_beta = -1; TestParameters::input(param).nspin = 1; it->second.reset_value(it->second, param); @@ -1461,15 +1519,15 @@ TEST_F(InputTest, Item_test2) TestParameters::input(param).nspin = 2; it->second.reset_value(it->second, param); EXPECT_EQ(TestParameters::input(param).mixing_beta, 0.4); - EXPECT_EQ(TestParameters::input(param).mixing_beta_mag, 1.6); - EXPECT_EQ(TestParameters::input(param).mixing_gg0_mag, 0.0); + EXPECT_DOUBLE_EQ(TestParameters::input(param).mixing_beta_mag, 0.2); + EXPECT_DOUBLE_EQ(TestParameters::input(param).mixing_gg0_mag, 0.7); TestParameters::input(param).mixing_beta = -1; TestParameters::input(param).nspin = 4; it->second.reset_value(it->second, param); EXPECT_EQ(TestParameters::input(param).mixing_beta, 0.4); - EXPECT_EQ(TestParameters::input(param).mixing_beta_mag, 1.6); - EXPECT_EQ(TestParameters::input(param).mixing_gg0_mag, 0.0); + EXPECT_DOUBLE_EQ(TestParameters::input(param).mixing_beta_mag, 0.2); + EXPECT_DOUBLE_EQ(TestParameters::input(param).mixing_gg0_mag, 0.7); } { // mixing_beta_mag auto it = find_label("mixing_beta_mag", readinput.input_lists);