Skip to content

Commit e003d49

Browse files
authored
Fix&Doc: do not overwrite k-point weights for non-MP k-point lists (#6857)
* Fix: do not overwrite k-point weights for non-MP k-point lists * Docs: update k-point weight documentation for symmetry handling
1 parent 48bfcaa commit e003d49

5 files changed

Lines changed: 201 additions & 1 deletion

File tree

docs/advanced/input_files/input-main.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ These variables are used to control general system parameters.
557557
- If ([dft_fuctional](#dft_functional)==hse/hf/pbe0/scan0 or [rpa](#rpa)==True).
558558
- If [efield_flag](#efield_flag)==1
559559
- 1: else
560+
- **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.
560561

561562
### symmetry_prec
562563

docs/advanced/input_files/kpt.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,40 @@ Direct //`Direct' or `Cartesian' coordinate
5858
0.5 0.5 0.5 0.125
5959
```
6060

61+
### K-point Weights and Symmetry
62+
63+
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.
64+
65+
**Important notes about k-point weights:**
66+
67+
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).
68+
69+
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:
70+
- For **Monkhorst-Pack grids** (automatically generated): All k-points have uniform weights (1/N where N is the total number of k-points)
71+
- For **explicit k-point lists**: Custom weights are preserved and properly combined when symmetry-equivalent k-points are merged
72+
73+
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).
74+
75+
**Example with custom weights:**
76+
77+
```
78+
K_POINTS
79+
5
80+
Direct
81+
0.0 0.0 0.0 0.1 // Gamma point with weight 0.1
82+
0.5 0.0 0.0 0.2 // X point with weight 0.2
83+
0.0 0.5 0.0 0.3 // Y point with weight 0.3
84+
0.5 0.5 0.0 0.2 // M point with weight 0.2
85+
0.0 0.0 0.5 0.2 // Z point with weight 0.2
86+
```
87+
88+
In this example, different k-points have different weights, which might be useful for:
89+
- Special sampling schemes
90+
- Convergence testing with specific k-point importance
91+
- Custom integration methods
92+
93+
> **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.
94+
6195
[back to top](#the-kpt-file)
6296

6397
## Band structure calculations

source/source_cell/k_vector_utils.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ void kvec_ibz_kpoint(K_Vectors& kv,
572572
std::vector<int> ibz2bz(kv.get_nkstot());
573573

574574
// nkstot is the total input k-points number.
575-
const double weight = 1.0 / static_cast<double>(kv.get_nkstot());
575+
double weight = 1.0 / static_cast<double>(kv.get_nkstot());
576576

577577
ModuleBase::Vector3<double> kvec_rot;
578578
ModuleBase::Vector3<double> kvec_rot_k;
@@ -609,6 +609,8 @@ void kvec_ibz_kpoint(K_Vectors& kv,
609609
// search in all k-poins.
610610
for (int i = 0; i < kv.get_nkstot(); ++i)
611611
{
612+
if (!kv.get_is_mp()) { weight = kv.wk[i]; } // use the input weight, instead of 1/nkstot
613+
612614
// restrict to [0, 1)
613615
restrict_kpt(kv.kvec_d[i]);
614616

source/source_cell/test/klist_test.cpp

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,3 +814,158 @@ TEST_F(KlistTest, IbzKpointIsMP)
814814
ClearUcell();
815815
remove("tmp_klist_4");
816816
}
817+
818+
TEST_F(KlistTest, IbzKpointCustomWeights)
819+
{
820+
// This test verifies the fix for issue #6552: k-point weights should not be overwritten
821+
// during IBZ reduction for non-Monkhorst-Pack k-point lists.
822+
823+
ModuleSymmetry::Symmetry symm;
824+
construct_ucell(stru_lib[0]);
825+
GlobalV::ofs_running.open("tmp_klist_custom_weights");
826+
symm.analy_sys(ucell.lat, ucell.st, ucell.atoms, GlobalV::ofs_running);
827+
828+
// Test 1: Non-MP k-points with uniform weights (KPT4)
829+
{
830+
K_Vectors kv_test1;
831+
std::string k_file = "./support/KPT4";
832+
kv_test1.nspin = 1;
833+
kv_test1.read_kpoints(ucell, k_file);
834+
EXPECT_EQ(kv_test1.get_nkstot(), 5);
835+
EXPECT_FALSE(kv_test1.is_mp); // Should be non-MP
836+
837+
// Store original weights before IBZ reduction
838+
std::vector<double> original_weights = kv_test1.wk;
839+
840+
// Apply IBZ reduction
841+
std::string skpt;
842+
ModuleSymmetry::Symmetry::symm_flag = 1;
843+
bool match = true;
844+
KVectorUtils::kvec_ibz_kpoint(kv_test1, symm, ModuleSymmetry::Symmetry::symm_flag, skpt, ucell, match);
845+
846+
// Verify that weights are preserved (not overwritten with 1/nkstot)
847+
// After IBZ reduction, weights should still reflect the input weights
848+
double total_weight = 0.0;
849+
for (int i = 0; i < kv_test1.get_nkstot(); ++i)
850+
{
851+
total_weight += kv_test1.wk[i];
852+
}
853+
// Weights should sum to approximately the number of original k-points (before normalization)
854+
EXPECT_GT(total_weight, 0.0);
855+
}
856+
857+
// Test 2: Non-MP k-points with non-uniform custom weights
858+
{
859+
K_Vectors kv_test2;
860+
std::string k_file = "./support/KPT_custom_weights";
861+
kv_test2.nspin = 1;
862+
kv_test2.read_kpoints(ucell, k_file);
863+
EXPECT_EQ(kv_test2.get_nkstot(), 5);
864+
EXPECT_FALSE(kv_test2.is_mp); // Should be non-MP
865+
866+
// Verify custom weights were read correctly
867+
EXPECT_DOUBLE_EQ(kv_test2.wk[0], 0.1);
868+
EXPECT_DOUBLE_EQ(kv_test2.wk[1], 0.2);
869+
EXPECT_DOUBLE_EQ(kv_test2.wk[2], 0.3);
870+
EXPECT_DOUBLE_EQ(kv_test2.wk[3], 0.2);
871+
EXPECT_DOUBLE_EQ(kv_test2.wk[4], 0.2);
872+
873+
// Store original weights
874+
std::vector<double> original_weights = kv_test2.wk;
875+
double original_sum = 0.0;
876+
for (double w : original_weights)
877+
{
878+
original_sum += w;
879+
}
880+
881+
// Apply IBZ reduction
882+
std::string skpt;
883+
ModuleSymmetry::Symmetry::symm_flag = 1;
884+
bool match = true;
885+
KVectorUtils::kvec_ibz_kpoint(kv_test2, symm, ModuleSymmetry::Symmetry::symm_flag, skpt, ucell, match);
886+
887+
// After IBZ reduction, the weights should be based on the custom input weights,
888+
// not uniform 1/nkstot weights. The total weight should be preserved.
889+
double total_weight_after = 0.0;
890+
for (int i = 0; i < kv_test2.get_nkstot(); ++i)
891+
{
892+
total_weight_after += kv_test2.wk[i];
893+
}
894+
895+
// The sum of weights after IBZ reduction should equal the sum before
896+
// (accounting for symmetry operations that may combine k-points)
897+
EXPECT_NEAR(total_weight_after, original_sum, 1e-10);
898+
899+
// Verify that at least one weight is NOT equal to 1/5 (which would indicate
900+
// the bug where custom weights are overwritten with uniform weights)
901+
bool has_custom_weight = false;
902+
double uniform_weight = 1.0 / 5.0;
903+
for (int i = 0; i < kv_test2.get_nkstot(); ++i)
904+
{
905+
if (std::abs(kv_test2.wk[i] - uniform_weight) > 1e-10)
906+
{
907+
has_custom_weight = true;
908+
break;
909+
}
910+
}
911+
EXPECT_TRUE(has_custom_weight) << "Custom weights were overwritten with uniform weights!";
912+
}
913+
914+
// Test 3: MP grid (regression test - should still work correctly)
915+
{
916+
K_Vectors kv_test3;
917+
std::string k_file = "./support/KPT1";
918+
kv_test3.nspin = 1;
919+
kv_test3.read_kpoints(ucell, k_file);
920+
EXPECT_EQ(kv_test3.get_nkstot(), 512);
921+
EXPECT_TRUE(kv_test3.is_mp); // Should be MP
922+
923+
// Apply IBZ reduction
924+
std::string skpt;
925+
ModuleSymmetry::Symmetry::symm_flag = 1;
926+
bool match = true;
927+
KVectorUtils::kvec_ibz_kpoint(kv_test3, symm, ModuleSymmetry::Symmetry::symm_flag, skpt, ucell, match);
928+
929+
// For MP grids, all weights should be uniform after IBZ reduction
930+
EXPECT_EQ(kv_test3.get_nkstot(), 35); // Known result from existing test
931+
932+
// Verify weights sum correctly
933+
double total_weight = 0.0;
934+
for (int i = 0; i < kv_test3.get_nkstot(); ++i)
935+
{
936+
total_weight += kv_test3.wk[i];
937+
}
938+
EXPECT_GT(total_weight, 0.0);
939+
}
940+
941+
// Test 4: Weight normalization verification
942+
{
943+
K_Vectors kv_test4;
944+
std::string k_file = "./support/KPT_custom_weights";
945+
kv_test4.nspin = 1;
946+
kv_test4.read_kpoints(ucell, k_file);
947+
948+
// Apply IBZ reduction
949+
std::string skpt;
950+
ModuleSymmetry::Symmetry::symm_flag = 1;
951+
bool match = true;
952+
KVectorUtils::kvec_ibz_kpoint(kv_test4, symm, ModuleSymmetry::Symmetry::symm_flag, skpt, ucell, match);
953+
954+
// Normalize weights
955+
int degspin = (kv_test4.nspin == 2) ? 1 : 2;
956+
kv_test4.normalize_wk(degspin);
957+
958+
// After normalization, weights should sum to degspin
959+
double total_weight = 0.0;
960+
for (int i = 0; i < kv_test4.get_nkstot(); ++i)
961+
{
962+
total_weight += kv_test4.wk[i];
963+
}
964+
EXPECT_NEAR(total_weight, degspin, 1e-10);
965+
}
966+
967+
GlobalV::ofs_running.close();
968+
ClearUcell();
969+
remove("tmp_klist_custom_weights");
970+
}
971+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
K_POINTS
2+
5
3+
Direct
4+
0.0 0.0 0.0 0.1
5+
0.5 0.0 0.0 0.2
6+
0.0 0.5 0.0 0.3
7+
0.5 0.5 0.0 0.2
8+
0.0 0.0 0.5 0.2

0 commit comments

Comments
 (0)