Loading...
Searching...
No Matches
kpoint_distributor.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * K-point distributor for pool-based parallelism.
5 *
6 * Given the global IBZ k-point grid and the pool topology (pool index and
7 * total number of pools), produces the local subset of k-points assigned
8 * to this pool using a round-robin distribution.
9 *
10 * Round-robin assignment: pool p owns global k-point indices
11 * { p, p + number_of_pools, p + 2*number_of_pools, ... }
12 *
13 * Serial by construction — no MPI headers. Used by PlanewaveMPIExecutionPolicy
14 * to compute each pool's k-point subset; trivially usable in single-process
15 * builds (one pool owning everything).
16 */
17
19#include <stdexcept>
20#include <vector>
21
22namespace q3 {
23namespace parallel {
24
26 public:
27 /**
28 * Distribute k-points across pools.
29 *
30 * @param global_kpoint_grid The full IBZ k-point grid.
31 * @param pool_index Zero-based index of this pool.
32 * @param number_of_pools Total number of pools.
33 */
34 KPointDistributor(const KPointsGrid& global_kpoint_grid, int pool_index, int number_of_pools)
35 : pool_index_(pool_index), number_of_pools_(number_of_pools) {
36 if (number_of_pools < 1) {
37 throw std::invalid_argument("KPointDistributor: number_of_pools must be at least 1.");
38 }
39 if (pool_index < 0 || pool_index >= number_of_pools) {
40 throw std::invalid_argument(
41 "KPointDistributor: pool_index must be in [0, number_of_pools).");
42 }
43
44 const int total_kpoints = global_kpoint_grid.number_of_kpoints();
45
46 // Round-robin: pool p owns global indices { p, p+N, p+2N, ... }
47 for (int global_index = pool_index; global_index < total_kpoints;
48 global_index += number_of_pools) {
49 local_kpoint_grid_.add_kpoint(global_kpoint_grid[global_index]);
50 local_to_global_kpoint_map_.push_back(global_index);
51 }
52
53 /**
54 * Preserve the original grid metadata (dimensions and shifts) so that
55 * downstream gamma-only detection (grid == 1×1×1, no shift) still works
56 * on the distributed local grid.
57 */
58 local_kpoint_grid_.set_grid_metadata(global_kpoint_grid.grid_dimensions(),
59 global_kpoint_grid.grid_shifts());
60 }
61
62 /**
63 * The local k-point grid assigned to this pool.
64 *
65 * Weights are preserved from the global grid. The sum of weights
66 * across all pools equals the sum of global weights.
67 */
68 [[nodiscard]] const KPointsGrid& local_kpoint_grid() const {
69 return local_kpoint_grid_;
70 }
71
72 /**
73 * Maps local k-point index → global k-point index.
74 *
75 * Used to reassemble eigenvalues from all pools into the global ordering
76 * expected by results.json.
77 */
78 [[nodiscard]] const std::vector<int>& local_to_global_kpoint_map() const {
79 return local_to_global_kpoint_map_;
80 }
81
82 [[nodiscard]] int number_of_local_kpoints() const {
83 return static_cast<int>(local_to_global_kpoint_map_.size());
84 }
85
86 [[nodiscard]] int pool_index() const {
87 return pool_index_;
88 }
89 [[nodiscard]] int number_of_pools() const {
90 return number_of_pools_;
91 }
92
93 private:
94 KPointsGrid local_kpoint_grid_;
95 std::vector<int> local_to_global_kpoint_map_;
96 int pool_index_;
97 int number_of_pools_;
98};
99
100} // namespace parallel
101} // namespace q3
void set_grid_metadata(const std::array< int, 3 > &dimensions, const std::array< int, 3 > &shifts)
int number_of_kpoints() const
void add_kpoint(const KPoint &kpoint)
const std::array< int, 3 > & grid_dimensions() const
const std::array< int, 3 > & grid_shifts() const
KPointDistributor(const KPointsGrid &global_kpoint_grid, int pool_index, int number_of_pools)
const KPointsGrid & local_kpoint_grid() const
const std::vector< int > & local_to_global_kpoint_map() const