From b702a79eddeeecf8c01110f50faa2657f87374b4 Mon Sep 17 00:00:00 2001 From: dyzheng Date: Wed, 14 Jan 2026 11:39:35 +0800 Subject: [PATCH 1/2] Fix: do not overwrite k-point weights for non-MP k-point lists --- source/source_cell/k_vector_utils.cpp | 4 +- source/source_cell/test/klist_test.cpp | 155 ++++++++++++++++++ .../test/support/KPT_custom_weights | 8 + 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 source/source_cell/test/support/KPT_custom_weights diff --git a/source/source_cell/k_vector_utils.cpp b/source/source_cell/k_vector_utils.cpp index e8eb56397d..3f5bef0b44 100644 --- a/source/source_cell/k_vector_utils.cpp +++ b/source/source_cell/k_vector_utils.cpp @@ -572,7 +572,7 @@ void kvec_ibz_kpoint(K_Vectors& kv, std::vector ibz2bz(kv.get_nkstot()); // nkstot is the total input k-points number. - const double weight = 1.0 / static_cast(kv.get_nkstot()); + double weight = 1.0 / static_cast(kv.get_nkstot()); ModuleBase::Vector3 kvec_rot; ModuleBase::Vector3 kvec_rot_k; @@ -609,6 +609,8 @@ void kvec_ibz_kpoint(K_Vectors& kv, // search in all k-poins. for (int i = 0; i < kv.get_nkstot(); ++i) { + if (!kv.get_is_mp()) { weight = kv.wk[i]; } // use the input weight, instead of 1/nkstot + // restrict to [0, 1) restrict_kpt(kv.kvec_d[i]); diff --git a/source/source_cell/test/klist_test.cpp b/source/source_cell/test/klist_test.cpp index 5d9c75ff18..55e1af4d96 100644 --- a/source/source_cell/test/klist_test.cpp +++ b/source/source_cell/test/klist_test.cpp @@ -788,3 +788,158 @@ TEST_F(KlistTest, IbzKpointIsMP) ClearUcell(); remove("tmp_klist_4"); } + +TEST_F(KlistTest, IbzKpointCustomWeights) +{ + // This test verifies the fix for issue #6552: k-point weights should not be overwritten + // during IBZ reduction for non-Monkhorst-Pack k-point lists. + + ModuleSymmetry::Symmetry symm; + construct_ucell(stru_lib[0]); + GlobalV::ofs_running.open("tmp_klist_custom_weights"); + symm.analy_sys(ucell.lat, ucell.st, ucell.atoms, GlobalV::ofs_running); + + // Test 1: Non-MP k-points with uniform weights (KPT4) + { + K_Vectors kv_test1; + std::string k_file = "./support/KPT4"; + kv_test1.nspin = 1; + kv_test1.read_kpoints(ucell, k_file); + EXPECT_EQ(kv_test1.get_nkstot(), 5); + EXPECT_FALSE(kv_test1.is_mp); // Should be non-MP + + // Store original weights before IBZ reduction + std::vector original_weights = kv_test1.wk; + + // Apply IBZ reduction + std::string skpt; + ModuleSymmetry::Symmetry::symm_flag = 1; + bool match = true; + KVectorUtils::kvec_ibz_kpoint(kv_test1, symm, ModuleSymmetry::Symmetry::symm_flag, skpt, ucell, match); + + // Verify that weights are preserved (not overwritten with 1/nkstot) + // After IBZ reduction, weights should still reflect the input weights + double total_weight = 0.0; + for (int i = 0; i < kv_test1.get_nkstot(); ++i) + { + total_weight += kv_test1.wk[i]; + } + // Weights should sum to approximately the number of original k-points (before normalization) + EXPECT_GT(total_weight, 0.0); + } + + // Test 2: Non-MP k-points with non-uniform custom weights + { + K_Vectors kv_test2; + std::string k_file = "./support/KPT_custom_weights"; + kv_test2.nspin = 1; + kv_test2.read_kpoints(ucell, k_file); + EXPECT_EQ(kv_test2.get_nkstot(), 5); + EXPECT_FALSE(kv_test2.is_mp); // Should be non-MP + + // Verify custom weights were read correctly + EXPECT_DOUBLE_EQ(kv_test2.wk[0], 0.1); + EXPECT_DOUBLE_EQ(kv_test2.wk[1], 0.2); + EXPECT_DOUBLE_EQ(kv_test2.wk[2], 0.3); + EXPECT_DOUBLE_EQ(kv_test2.wk[3], 0.2); + EXPECT_DOUBLE_EQ(kv_test2.wk[4], 0.2); + + // Store original weights + std::vector original_weights = kv_test2.wk; + double original_sum = 0.0; + for (double w : original_weights) + { + original_sum += w; + } + + // Apply IBZ reduction + std::string skpt; + ModuleSymmetry::Symmetry::symm_flag = 1; + bool match = true; + KVectorUtils::kvec_ibz_kpoint(kv_test2, symm, ModuleSymmetry::Symmetry::symm_flag, skpt, ucell, match); + + // After IBZ reduction, the weights should be based on the custom input weights, + // not uniform 1/nkstot weights. The total weight should be preserved. + double total_weight_after = 0.0; + for (int i = 0; i < kv_test2.get_nkstot(); ++i) + { + total_weight_after += kv_test2.wk[i]; + } + + // The sum of weights after IBZ reduction should equal the sum before + // (accounting for symmetry operations that may combine k-points) + EXPECT_NEAR(total_weight_after, original_sum, 1e-10); + + // Verify that at least one weight is NOT equal to 1/5 (which would indicate + // the bug where custom weights are overwritten with uniform weights) + bool has_custom_weight = false; + double uniform_weight = 1.0 / 5.0; + for (int i = 0; i < kv_test2.get_nkstot(); ++i) + { + if (std::abs(kv_test2.wk[i] - uniform_weight) > 1e-10) + { + has_custom_weight = true; + break; + } + } + EXPECT_TRUE(has_custom_weight) << "Custom weights were overwritten with uniform weights!"; + } + + // Test 3: MP grid (regression test - should still work correctly) + { + K_Vectors kv_test3; + std::string k_file = "./support/KPT1"; + kv_test3.nspin = 1; + kv_test3.read_kpoints(ucell, k_file); + EXPECT_EQ(kv_test3.get_nkstot(), 512); + EXPECT_TRUE(kv_test3.is_mp); // Should be MP + + // Apply IBZ reduction + std::string skpt; + ModuleSymmetry::Symmetry::symm_flag = 1; + bool match = true; + KVectorUtils::kvec_ibz_kpoint(kv_test3, symm, ModuleSymmetry::Symmetry::symm_flag, skpt, ucell, match); + + // For MP grids, all weights should be uniform after IBZ reduction + EXPECT_EQ(kv_test3.get_nkstot(), 35); // Known result from existing test + + // Verify weights sum correctly + double total_weight = 0.0; + for (int i = 0; i < kv_test3.get_nkstot(); ++i) + { + total_weight += kv_test3.wk[i]; + } + EXPECT_GT(total_weight, 0.0); + } + + // Test 4: Weight normalization verification + { + K_Vectors kv_test4; + std::string k_file = "./support/KPT_custom_weights"; + kv_test4.nspin = 1; + kv_test4.read_kpoints(ucell, k_file); + + // Apply IBZ reduction + std::string skpt; + ModuleSymmetry::Symmetry::symm_flag = 1; + bool match = true; + KVectorUtils::kvec_ibz_kpoint(kv_test4, symm, ModuleSymmetry::Symmetry::symm_flag, skpt, ucell, match); + + // Normalize weights + int degspin = (kv_test4.nspin == 2) ? 1 : 2; + kv_test4.normalize_wk(degspin); + + // After normalization, weights should sum to degspin + double total_weight = 0.0; + for (int i = 0; i < kv_test4.get_nkstot(); ++i) + { + total_weight += kv_test4.wk[i]; + } + EXPECT_NEAR(total_weight, degspin, 1e-10); + } + + GlobalV::ofs_running.close(); + ClearUcell(); + remove("tmp_klist_custom_weights"); +} + diff --git a/source/source_cell/test/support/KPT_custom_weights b/source/source_cell/test/support/KPT_custom_weights new file mode 100644 index 0000000000..e441560a1b --- /dev/null +++ b/source/source_cell/test/support/KPT_custom_weights @@ -0,0 +1,8 @@ +K_POINTS +5 +Direct +0.0 0.0 0.0 0.1 +0.5 0.0 0.0 0.2 +0.0 0.5 0.0 0.3 +0.5 0.5 0.0 0.2 +0.0 0.0 0.5 0.2 From 5e904970b76d92916442df9b50c0e3e31d3d25a5 Mon Sep 17 00:00:00 2001 From: dyzheng Date: Wed, 14 Jan 2026 11:54:56 +0800 Subject: [PATCH 2/2] Docs: update k-point weight documentation for symmetry handling --- docs/advanced/input_files/input-main.md | 1 + docs/advanced/input_files/kpt.md | 34 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md index 17ebe53108..6373cf63ec 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -557,6 +557,7 @@ These variables are used to control general system parameters. - If ([dft_fuctional](#dft_functional)==hse/hf/pbe0/scan0 or [rpa](#rpa)==True). - If [efield_flag](#efield_flag)==1 - 1: else +- **Note**: When symmetry is enabled (value 1), k-points are reduced to the irreducible Brillouin zone (IBZ). For explicit k-point lists with custom weights (see [KPT file](./kpt.md#k-point-weights-and-symmetry)), the custom weights are preserved during symmetry reduction. For Monkhorst-Pack grids, uniform weights are used. ### symmetry_prec diff --git a/docs/advanced/input_files/kpt.md b/docs/advanced/input_files/kpt.md index 853a3dc340..1aac138fd0 100644 --- a/docs/advanced/input_files/kpt.md +++ b/docs/advanced/input_files/kpt.md @@ -58,6 +58,40 @@ Direct //`Direct' or `Cartesian' coordinate 0.5 0.5 0.5 0.125 ``` +### K-point Weights and Symmetry + +When explicitly setting k-points, you can specify custom weights for each k-point. These weights determine the contribution of each k-point to the total energy and density calculations. + +**Important notes about k-point weights:** + +1. **Custom weights are preserved**: When using explicit k-point lists (non-Monkhorst-Pack), ABACUS preserves the custom weights you specify, even when symmetry operations are applied to reduce the k-points to the irreducible Brillouin zone (IBZ). + +2. **Symmetry reduction**: When [`symmetry`](./input-main.md#symmetry) is set to 1, ABACUS will analyze the crystal symmetry and reduce the k-point set to the irreducible Brillouin zone. During this reduction: + - For **Monkhorst-Pack grids** (automatically generated): All k-points have uniform weights (1/N where N is the total number of k-points) + - For **explicit k-point lists**: Custom weights are preserved and properly combined when symmetry-equivalent k-points are merged + +3. **Weight normalization**: After symmetry reduction, k-point weights are normalized so that their sum equals `degspin` (2 for non-spin-polarized calculations, 1 for spin-polarized calculations). + +**Example with custom weights:** + +``` +K_POINTS +5 +Direct +0.0 0.0 0.0 0.1 // Gamma point with weight 0.1 +0.5 0.0 0.0 0.2 // X point with weight 0.2 +0.0 0.5 0.0 0.3 // Y point with weight 0.3 +0.5 0.5 0.0 0.2 // M point with weight 0.2 +0.0 0.0 0.5 0.2 // Z point with weight 0.2 +``` + +In this example, different k-points have different weights, which might be useful for: +- Special sampling schemes +- Convergence testing with specific k-point importance +- Custom integration methods + +> **Note**: When using custom weights with symmetry, ensure that your weight distribution is consistent with the crystal symmetry. ABACUS will preserve your weights during IBZ reduction, but inconsistent weights may lead to unexpected results. + [back to top](#the-kpt-file) ## Band structure calculations