Loading...
Searching...
No Matches
kpoints_grid.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * KPointsGrid: Monkhorst-Pack k-point mesh generator.
5 *
6 * Generates a uniform k-point grid with configurable dimensions, offsets,
7 * and weights. Supports adding individual k-points for irreducible Brillouin
8 * zone reduction.
9 *
10 * Implements the uniform meshes of H. J. Monkhorst & J. D. Pack, Phys. Rev. B
11 * 13, 5188 (1976).
12 */
13
14#include <cmath>
15#include <string>
16#include <vector>
17
20
21namespace q3 {
22
23/**
24 * Generates and stores Monkhorst-Pack k-point meshes.
25 */
27 public:
28 KPointsGrid() = default;
29
30 /**
31 * Generate Monkhorst-Pack mesh with dimensions and offsets.
32 * Offsets are 0 or 1 (as in QE input).
33 */
34 void generate(int grid_dimension_x,
35 int grid_dimension_y,
36 int grid_dimension_z,
37 int shift_x,
38 int shift_y,
39 int shift_z) {
40 grid_dimensions_ = {grid_dimension_x, grid_dimension_y, grid_dimension_z};
41 grid_shifts_ = {shift_x, shift_y, shift_z};
42 kpoints_.clear();
43 int total_grid_points = grid_dimension_x * grid_dimension_y * grid_dimension_z;
44 Real weight = 2.0 / total_grid_points; // weight per k-point (factor 2 for spin degeneracy)
45
46 for (int x_index = 0; x_index < grid_dimension_x; x_index++) {
47 for (int y_index = 0; y_index < grid_dimension_y; y_index++) {
48 for (int z_index = 0; z_index < grid_dimension_z; z_index++) {
49 Vector3D coordinates;
50 coordinates.x = static_cast<Real>(x_index) / grid_dimension_x +
51 (shift_x ? 0.5 : 0.0) / grid_dimension_x;
52 coordinates.y = static_cast<Real>(y_index) / grid_dimension_y +
53 (shift_y ? 0.5 : 0.0) / grid_dimension_y;
54 coordinates.z = static_cast<Real>(z_index) / grid_dimension_z +
55 (shift_z ? 0.5 : 0.0) / grid_dimension_z;
56
57 // Fold back to [-0.5, 0.5)
58 coordinates.x -= std::floor(coordinates.x + 0.5);
59 coordinates.y -= std::floor(coordinates.y + 0.5);
60 coordinates.z -= std::floor(coordinates.z + 0.5);
61
62 KPoint kpoint;
63 kpoint.coordinates = coordinates;
64 kpoint.weight = weight;
65 kpoints_.push_back(kpoint);
66 }
67 }
68 }
69 }
70
71 [[nodiscard]] int number_of_kpoints() const {
72 return static_cast<int>(kpoints_.size());
73 }
74 [[nodiscard]] const std::vector<KPoint>& kpoints() const {
75 return kpoints_;
76 }
77 [[nodiscard]] const KPoint& operator[](int index) const {
78 return kpoints_[index];
79 }
80
81 /**
82 * Add a single k-point (used by IBZ reduction).
83 */
84 void add_kpoint(const KPoint& kpoint) {
85 kpoints_.push_back(kpoint);
86 }
87
88 /**
89 * Scale every k-point weight by a constant factor.
90 *
91 * Generated weights embed the spin degeneracy of 2 (they sum to 2 over the
92 * grid). Spin-polarized (LSDA) calculations enumerate the two spin channels
93 * as explicit k-point states, so each state carries half of that weight:
94 * scale by 0.5 once, right after the grid (and any IBZ reduction) is built.
95 */
96 void scale_weights(Real factor) {
97 for (auto& kpoint : kpoints_) {
98 kpoint.weight *= factor;
99 }
100 }
101
102 /**
103 * Access the grid dimensions (x, y, z).
104 */
105 [[nodiscard]] const std::array<int, 3>& grid_dimensions() const {
106 return grid_dimensions_;
107 }
108
109 /**
110 * Access the grid shifts (x, y, z).
111 */
112 [[nodiscard]] const std::array<int, 3>& grid_shifts() const {
113 return grid_shifts_;
114 }
115
116 /**
117 * Log the k-point grid contents with coordinates and weights.
118 */
119 void pretty_print() const {
120 for (int kpoint_index = 0; kpoint_index < number_of_kpoints(); kpoint_index++) {
121 const auto& kpoint = kpoints_[kpoint_index];
122 log::info(" k({}) = ({:.7f}, {:.7f}, {:.7f}), weight = {:.7f}",
123 kpoint_index + 1,
124 kpoint.coordinates.x,
125 kpoint.coordinates.y,
126 kpoint.coordinates.z,
127 kpoint.weight);
128 }
129 }
130
131 /**
132 * Set the Monkhorst-Pack grid metadata (dimensions and shifts).
133 *
134 * Used by symmetry reduction and k-point distribution to preserve the
135 * requested generated-grid parameters. Explicit k-point lists retain the
136 * default zero dimensions and remain distinguishable from generated grids.
137 */
138 void set_grid_metadata(const std::array<int, 3>& dimensions, const std::array<int, 3>& shifts) {
139 grid_dimensions_ = dimensions;
140 grid_shifts_ = shifts;
141 }
142
143 private:
144 std::vector<KPoint> kpoints_;
145 std::array<int, 3> grid_dimensions_ = {0, 0, 0};
146 std::array<int, 3> grid_shifts_ = {0, 0, 0};
147};
148
149} // namespace q3
void set_grid_metadata(const std::array< int, 3 > &dimensions, const std::array< int, 3 > &shifts)
void scale_weights(Real factor)
int number_of_kpoints() const
void add_kpoint(const KPoint &kpoint)
void generate(int grid_dimension_x, int grid_dimension_y, int grid_dimension_z, int shift_x, int shift_y, int shift_z)
const std::vector< KPoint > & kpoints() const
KPointsGrid()=default
void pretty_print() const
const std::array< int, 3 > & grid_dimensions() const
const KPoint & operator[](int index) const
const std::array< int, 3 > & grid_shifts() const
void info(spdlog::format_string_t< Args... > fmt, Args &&... args)
Definition logger.hpp:183
double Real
Vector3D coordinates