37 BlochOverlaps(
const std::vector<std::vector<std::vector<Complex>>>& blocks,
41 throw std::invalid_argument(
"BlochOverlaps: no k-points");
43 const std::size_t directions = blocks.front().size();
44 blocks_.reserve(blocks.size());
45 for (std::size_t kpoint = 0; kpoint < blocks.size(); kpoint++) {
46 if (blocks[kpoint].size() != directions) {
47 throw std::invalid_argument(
"BlochOverlaps: k-point " + std::to_string(kpoint) +
48 " carries " + std::to_string(blocks[kpoint].size()) +
49 " overlap blocks where k-point 0 carries " +
50 std::to_string(directions));
52 std::vector<DenseMatrix<Complex>> row;
53 row.reserve(directions);
54 for (std::size_t direction = 0; direction < directions; direction++) {
55 const std::vector<Complex>& block = blocks[kpoint][direction];
57 static_cast<std::size_t
>(rows) *
static_cast<std::size_t
>(columns)) {
58 throw std::invalid_argument(
59 "BlochOverlaps: the overlap block at k-point " + std::to_string(kpoint) +
60 ", direction " + std::to_string(direction) +
" holds " +
61 std::to_string(block.size()) +
" entries, not the " +
62 std::to_string(
static_cast<std::size_t
>(rows) * columns) +
" a " +
63 std::to_string(rows) +
" x " + std::to_string(columns) +
" block requires");
65 row.emplace_back(rows, columns, block);
67 blocks_.push_back(std::move(row));
73 square(
const std::vector<std::vector<std::vector<Complex>>>& blocks,
int dimension) {
79 : blocks_(std::move(blocks)) {
80 if (blocks_.empty()) {
81 throw std::invalid_argument(
"BlochOverlaps: no k-points");
86 return static_cast<int>(blocks_.size());
89 return static_cast<int>(blocks_.front().size());
93 return blocks_[
static_cast<std::size_t
>(kpoint)][
static_cast<std::size_t
>(direction)];
105 require_stencil(stencil);
107 throw std::invalid_argument(
"BlochOverlaps: the classification covers " +
108 std::to_string(classification.size()) +
109 " k-points, the overlaps " +
112 std::vector<std::vector<DenseMatrix<Complex>>> restricted(blocks_.size());
114 const std::vector<int>& rows =
115 classification[
static_cast<std::size_t
>(kpoint)].kept_bands;
116 require_bands_within(rows, kpoint);
118 const int neighbor = stencil.
neighbor(kpoint, direction);
119 const std::vector<int>& columns =
120 classification[
static_cast<std::size_t
>(neighbor)].kept_bands;
121 require_bands_within(columns, neighbor);
122 restricted[
static_cast<std::size_t
>(kpoint)].push_back(
133 require_stencil(stencil);
136 throw std::invalid_argument(
"BlochOverlaps: one left and one right matrix per k-point "
139 std::to_string(left.size()) +
" and " +
140 std::to_string(right.size()));
142 std::vector<std::vector<DenseMatrix<Complex>>> transformed(blocks_.size());
145 const int neighbor = stencil.
neighbor(kpoint, direction);
146 transformed[
static_cast<std::size_t
>(kpoint)].push_back(
148 left[
static_cast<std::size_t
>(kpoint)],
151 at(kpoint, direction),
153 right[
static_cast<std::size_t
>(neighbor)])));
163 throw std::invalid_argument(
164 "BlochOverlaps: the stencil covers " + std::to_string(stencil.
number_of_kpoints()) +
171 void require_bands_within(
const std::vector<int>& bands,
int kpoint)
const {
172 const int captured = blocks_.front().front().rows();
173 for (
const int band : bands) {
174 if (band < 0 || band >= captured) {
175 throw std::invalid_argument(
"BlochOverlaps: k-point " + std::to_string(kpoint) +
176 " keeps band " + std::to_string(band) +
177 ", outside the " + std::to_string(captured) +
178 " captured bands the overlaps are indexed by");
184 std::vector<std::vector<DenseMatrix<Complex>>> blocks_;
static BlochOverlaps square(const std::vector< std::vector< std::vector< Complex > > > &blocks, int dimension)
The square case: N x N at every (k, b).
int number_of_kpoints() const
BlochOverlaps transformed_by(const std::vector< DenseMatrix< Complex > > &left, const std::vector< DenseMatrix< Complex > > &right, const KPointStencil &stencil) const
left(k)^dagger M(k, b) right(k + b) at every (k, b).
BlochOverlaps(const std::vector< std::vector< std::vector< Complex > > > &blocks, int rows, int columns)
BlochOverlaps(std::vector< std::vector< DenseMatrix< Complex > > > blocks)
From matrices already built, one row of directions per k-point.
int number_of_directions() const
BlochOverlaps restricted_to(const std::vector< KPointBandClassification > &classification, const KPointStencil &stencil) const
const DenseMatrix< Complex > & at(int kpoint, int direction) const
DenseMatrix submatrix(const std::vector< int > &row_indices, const std::vector< int > &column_indices) const
The rows and columns named, in the order named; an index outside the matrix is refused.
int number_of_directions() const
int number_of_kpoints() const
int neighbor(int kpoint, int direction) const
The k-point that k + b lands on.
DenseMatrix< Complex > multiply(MatrixOperation left_operation, const DenseMatrix< Complex > &left, MatrixOperation right_operation, const DenseMatrix< Complex > &right, Complex alpha=Complex(1.0, 0.0))
alpha * op(left) * op(right), as a new matrix of the product's shape.