TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
brzone.hpp
Go to the documentation of this file.
1// Copyright (c) 2016-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2016-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2023 Simons Foundation
4// Copyright (c) 2023 Hugo U.R. Strand
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You may obtain a copy of the License at
17// https://www.gnu.org/licenses/gpl-3.0.txt
18//
19// Authors: Thomas Ayral, Philipp Dumitrescu, Dominik Kiese, Olivier Parcollet, Hugo U. R. Strand, Nils Wentzell
20
25
26#pragma once
27
28#include "./k_expr.hpp"
29#include "./mesh_iterator.hpp"
30#include "./utils.hpp"
32#include "../utility/macros.hpp"
33
34#include <fmt/ranges.h>
35#include <h5/h5.hpp>
36#include <nda/nda.hpp>
37
38#include <array>
39#include <cmath>
40#include <cstdint>
41#include <concepts>
42#include <iostream>
43#include <limits>
44#include <mutex>
45#include <optional>
46#include <ranges>
47#include <string>
48#include <tuple>
49#include <type_traits>
50#include <utility>
51
52namespace triqs::mesh {
53
58 using lattice::brillouin_zone;
59
64
104 class C2PY_RENAME(MeshBrZone) brzone {
105 public:
108
110 using index_t = std::array<long, 3>;
111
113 using data_index_t = long;
114
121 class C2PY_IGNORE mesh_point_t {
122 public:
124 using mesh_t = brzone;
125
127 mesh_point_t() = default;
128
137 mesh_point_t(std::array<long, 3> const &n, brzone const *m_ptr, long d)
138 : index_(n), m_ptr_(m_ptr), data_index_(d), mesh_hash_(m_ptr->mesh_hash()) {}
139
142 : index_(mp.index_), m_ptr_(mp.m_ptr_), data_index_(mp.data_index_), mesh_hash_(mp.mesh_hash_), value_(mp.value_) {}
143
145 [[nodiscard]] mesh_t::index_t index() const { return index_; }
146
148 [[nodiscard]] long data_index() const { return data_index_; }
149
151 [[nodiscard]] value_t const &value() const {
152 if (value_)
153 return *value_;
154 else {
155 auto guard = std::lock_guard{value_mutex_};
156 return *(value_ = m_ptr_->to_value(index_));
157 }
158 }
159
161 [[nodiscard]] uint64_t mesh_hash() const noexcept { return mesh_hash_; }
162
164 [[nodiscard]] operator value_t() const { return value(); }
165
172 [[deprecated("() is deprecated for a brzone::mesh_point_t. Use [] instead")]] double operator()(int d) const { return value()[d]; }
173
181 [[nodiscard]] double operator[](int i) const { return value()[i]; }
182
190 friend std::ostream &operator<<(std::ostream &sout, mesh_point_t const &mp) { return sout << mp.value(); }
191
192 private:
193 std::array<long, 3> index_ = {0, 0, 0};
194 brzone const *m_ptr_ = nullptr;
195 long data_index_ = 0;
196 uint64_t mesh_hash_ = 0;
197 mutable std::optional<value_t> value_ = {};
198 mutable std::mutex value_mutex_ = {};
199 };
200
201 public:
203 brzone() = default;
204
211 brzone(brillouin_zone const &bz, std::array<long, 3> const &dims)
212 : bz_(bz),
213 dims_(dims),
214 size_(nda::stdutil::product(dims)),
215 s2_(dims_[2]),
216 s1_(dims_[1] * dims_[2]),
217 units_(nda::linalg::inv(1.0 * nda::diag(dims)) * bz.units()),
218 units_inv_(nda::linalg::inv(units_)),
219 mesh_hash_(hash(nda::sum(bz.units()), dims[0], dims[1], dims[2])) {
220 EXPECTS(dims_[0] > 0 and dims_[1] > 0 and dims_[2] > 0);
221 }
222
232 C2PY_IGNORE brzone(brillouin_zone const &bz, nda::matrix<long> const &M) : brzone(bz, std::array{M(0, 0), M(1, 1), M(2, 2)}) {
233 EXPECTS((M.shape() == std::array{3l, 3l}));
234 EXPECTS(nda::is_matrix_diagonal(M));
235 }
236
243 brzone(brillouin_zone const &bz, long n_k) : brzone(bz, std::array{n_k, (bz.ndim() >= 2 ? n_k : 1l), (bz.ndim() >= 3 ? n_k : 1)}) {}
244
252 [[nodiscard]] bool is_index_valid(index_t const &n) const noexcept {
253 for (auto i : nda::range(3))
254 if (n[i] < 0 or n[i] >= dims_[i]) return false;
255 return true;
256 }
257
264 [[nodiscard]] data_index_t to_data_index(index_t const &n) const {
265 EXPECTS(is_index_valid(n));
266 return n[0] * s1_ + n[1] * s2_ + n[2];
267 }
268
277 template <typename V> [[nodiscard]] data_index_t to_data_index(closest_mesh_point_t<V> const &cmp) const {
278 return to_data_index(closest_index(cmp.value));
279 }
280
290 template <char OP, typename L> [[nodiscard]] data_index_t to_data_index(k_expr_unary<OP, L> const &ex) const {
291 EXPECTS(mesh_hash_ == ex.mesh_hash());
292 return to_data_index(index_modulo(ex.index()));
293 }
294
305 template <char OP, typename L, typename R> [[nodiscard]] data_index_t to_data_index(k_expr<OP, L, R> const &ex) const {
306 EXPECTS(mesh_hash_ == ex.mesh_hash());
307 return to_data_index(index_modulo(ex.index()));
308 }
309
317 [[nodiscard]] index_t to_index(data_index_t d) const {
318 EXPECTS(0 <= d and d < size());
319 long const r0 = d % s1_;
320 return {d / s1_, r0 / s2_, r0 % s2_};
321 }
322
331 template <typename V> [[nodiscard]] index_t to_index(closest_mesh_point_t<V> const &cmp) const { return closest_index(cmp.value); }
332
340 [[nodiscard]] mesh_point_t operator[](long d) const { return {to_index(d), this, d}; }
341
350 [[nodiscard]] C2PY_IGNORE mesh_point_t operator[](closest_mesh_point_t<value_t> const &cmp) const { return (*this)[this->to_data_index(cmp)]; }
351
359 [[nodiscard]] mesh_point_t operator()(index_t const &n) const { return {n, this, to_data_index(n)}; }
360
368 [[nodiscard]] value_t to_value(index_t const &n) const {
369 EXPECTS(is_index_valid(n));
370 return nda::transpose(units_)(nda::range::all, nda::range(bz_.ndim())) * nda::basic_array_view{n}(nda::range(bz_.ndim()));
371 }
372
374 [[nodiscard]] C2PY_PROPERTY_GET(dims) auto const &dims() const { return dims_; }
375
377 [[nodiscard]] C2PY_PROPERTY_GET(units) auto units() const { return nda::matrix_const_view<double>{units_}; }
378
380 [[nodiscard]] C2PY_PROPERTY_GET(units_inv) auto units_inv() const { return nda::matrix_const_view<double>{units_inv_}; }
381
383 [[nodiscard]] C2PY_PROPERTY_GET(bz) auto const &bz() const noexcept { return bz_; }
384
386 [[nodiscard]] C2PY_PROPERTY_GET(mesh_hash) uint64_t mesh_hash() const { return mesh_hash_; }
387
389 [[nodiscard]] long size() const { return size_; }
390
398 [[nodiscard]] index_t index_modulo(index_t const &n_tilde) const {
399 return {positive_modulo(n_tilde[0], dims_[0]), positive_modulo(n_tilde[1], dims_[1]), positive_modulo(n_tilde[2], dims_[2])};
400 }
401
410 template <typename V>
411 requires(is_k_expr<V> or std::ranges::contiguous_range<V> or nda::ArrayOfRank<V, 1>)
412 [[nodiscard]] index_t closest_index(V const &k) const {
413 if constexpr (is_k_expr<V>) {
414 return closest_index(k.value());
415 } else {
416 // calculate k in the brzone basis
417 auto ks = nda::stack_vector<double, 3>{k[0], k[1], k[2]};
418 auto k_units = nda::transpose(units_inv_) * ks;
419 auto n = nda::stack_vector<long, 3>(nda::floor(k_units));
420
421 // calculate position relative to neighbors in mesh
422 auto w = k_units - n;
423
424 // prepare result container and distance measure
425 auto dst = std::numeric_limits<double>::infinity();
426
427 // check flatness along mesh dimensions
428 long r1 = std::min(dims_[0], 2l);
429 long r2 = std::min(dims_[1], 2l);
430 long r3 = std::min(dims_[2], 2l);
431
432 // find nearest neighbor by comparing distances
433 nda::stack_vector<long, 3> res;
434 for (auto const &[i1, i2, i3] : itertools::product_range(r1, r2, r3)) {
435 auto iv = nda::stack_vector<long, 3>{i1, i2, i3};
436 auto dstp = nda::linalg::norm(nda::transpose(units_) * (w - iv));
437
438 // update result when distance is smaller than current
439 if (dstp < dst) {
440 dst = dstp;
441 res = n + iv;
442 }
443 }
444
445 // fold back to brzone mesh (nearest neighbor could be out of bounds)
446 return index_modulo({res[0], res[1], res[2]});
447 }
448 }
449
451 [[nodiscard]] auto begin() const { return mesh_iterator<brzone>{.mesh_ptr = this, .data_index = 0}; }
452
454 [[nodiscard]] auto cbegin() const { return begin(); }
455
457 [[nodiscard]] auto end() const { return mesh_iterator<brzone>{.mesh_ptr = this, .data_index = size()}; }
458
460 [[nodiscard]] auto cend() const { return end(); }
461
466 bool operator==(brzone const &m) const { return bz_ == m.bz() && dims_ == m.dims(); }
467
475 friend std::ostream &operator<<(std::ostream &sout, brzone const &m) {
476 return sout << "Brillouin zone mesh with " << m.dims() << " k-points and an underlying " << m.bz();
477 }
478
483 void serialize(auto &ar) const { ar & bz_ & dims_ & size_ & s2_ & s1_ & units_ & units_inv_ & mesh_hash_; }
484
489 void deserialize(auto &ar) { ar & bz_ & dims_ & size_ & s2_ & s1_ & units_ & units_inv_ & mesh_hash_; }
490
492 [[nodiscard]] static std::string hdf5_format() { return "MeshBrillouinZone"; }
493
501 friend void h5_write(h5::group g, std::string const &name, brzone const &m) {
502 h5::group gr = g.create_group(name);
503 h5::write_hdf5_format(gr, m); // NOLINT (downcasting to base class)
504 h5::write(gr, "dims", m.dims_);
505 h5::write(gr, "brillouin_zone", m.bz_);
506 }
507
515 friend void h5_read(h5::group g, std::string const &name, brzone &m) {
516 h5::group gr = g.open_group(name);
517 h5::assert_hdf5_format(gr, m, true); // NOLINT (downcasting to base class)
518
519 std::array<long, 3> dims{};
520 if (gr.has_key("dims")) {
521 h5::read(gr, "dims", dims);
522 } else {
523 // for backward compatibility
524 auto M = h5::read<matrix<long>>(gr, "periodization_matrix");
525 dims = {M(0, 0), M(1, 1), M(2, 2)};
526 }
527
529 if (gr.has_key("brillouin_zone")) {
530 h5::read(gr, "brillouin_zone", bz);
531 } else if (gr.has_key("bz")) {
532 // for backward compatibility
533 h5::read(gr, "bz", bz);
534 } else {
535 std::cout << "WARNING: Reading old MeshBrillouinZone without BrillouinZone\n";
536 }
537
538 m = brzone(bz, dims);
539 }
540
541 private:
542 brillouin_zone bz_ = {};
543 std::array<long, 3> dims_ = {0, 0, 0};
544 long size_ = 0;
545 long s2_ = 1;
546 long s1_ = 1;
547 nda::matrix<double> units_ = nda::eye<double>(3);
548 nda::matrix<double> units_inv_ = nda::eye<double>(3);
549 uint64_t mesh_hash_ = 0;
550 };
551
552 namespace detail {
553
554 // Helper struct to evaluate a function at an arbitrary k-vector.
555 struct brzone1d {
556 long dim;
557 };
558
559 } // namespace detail
560
561 // Helper function to do linear interpolation between k-points.
562 auto evaluate(detail::brzone1d const &m, auto const &f, double vi) {
563 long i = static_cast<long>(std::floor(vi));
564 double w = vi - double(i);
565 return (1 - w) * f(positive_modulo(i, m.dim)) + w * f(m.dim == 1 ? 0 : positive_modulo(i + 1, m.dim));
566 }
567
581 auto evaluate(brzone const &m, auto const &f, brzone::index_t const &n_tilde) { return f(m.index_modulo(n_tilde)); }
582
598 template <typename V>
599 requires(std::ranges::contiguous_range<V> or nda::ArrayOfRank<V, 1> or is_k_expr<V>)
600 auto evaluate(brzone const &m, auto const &f, V const &k) {
601 if constexpr (is_k_expr<V>) {
602 return evaluate(m, f, k.value());
603 } else {
604 auto v_index = nda::make_regular(nda::transpose(m.units_inv()) * nda::basic_array_view{k});
605 auto g = [&f](long x, long y, long z) { return f(typename brzone::index_t{x, y, z}); };
606 auto [d0, d1, d2] = m.dims();
607 return evaluate(std::tuple{detail::brzone1d{d0}, detail::brzone1d{d1}, detail::brzone1d{d2}}, g, v_index[0], v_index[1], v_index[2]);
608 }
609 }
610
612
617
627 template <typename T>
628 concept BzMeshPoint = is_k_expr<std::decay_t<T>> or std::is_same_v<std::decay_t<T>, brzone::mesh_point_t>;
629
637 template <BzMeshPoint L> k_expr_unary<'-', L> operator-(L &&l) { return {std::forward<L>(l)}; }
638
648 template <BzMeshPoint L, BzMeshPoint R> k_expr<'+', L, R> operator+(L &&l, R &&r) { return {std::forward<L>(l), std::forward<R>(r)}; }
649
659 template <BzMeshPoint L, BzMeshPoint R> k_expr<'-', L, R> operator-(L &&l, R &&r) { return {std::forward<L>(l), std::forward<R>(r)}; }
660
670 template <std::integral Int, BzMeshPoint R> k_expr<'*', long, R> operator*(Int l, R &&r) { return {static_cast<long>(l), std::forward<R>(r)}; }
671
673
674} // namespace triqs::mesh
iterator end()
Get an iterator past the last block.
iterator begin()
Get an iterator to the first block.
int size() const
Get the total number of blocks.
Provides a Brillouin zone class.
mesh_point_t()=default
Default constructor leaves the mesh point uninitialized.
brzone()=default
Default constructor constructs an empty mesh.
A Brillouin zone class.
k_t value_t
Value type of a Brillouin Zone.
Mesh point of a triqs::mesh::brzone mesh.
Definition brzone.hpp:121
mesh_point_t(mesh_point_t const &mp)
Copy constructor to handle the presence of the std::mutex object correctly.
Definition brzone.hpp:141
friend std::ostream & operator<<(std::ostream &sout, mesh_point_t const &mp)
Write triqs::mesh::brzone::mesh_point_t to a std::ostream.
Definition brzone.hpp:190
mesh_point_t()=default
Default constructor leaves the mesh point uninitialized.
double operator()(int d) const
Get the coordinate of the corresponding reciprocal vector .
Definition brzone.hpp:172
double operator[](int i) const
Get the coordinate of the corresponding reciprocal vector .
Definition brzone.hpp:181
uint64_t mesh_hash() const noexcept
Get the hash value of the parent mesh.
Definition brzone.hpp:161
value_t const & value() const
Get the reciprocal vector corresponding to the mesh point.
Definition brzone.hpp:151
brzone mesh_t
Parent mesh type.
Definition brzone.hpp:124
mesh_t::index_t index() const
Get the index of the mesh point.
Definition brzone.hpp:145
long data_index() const
Get the data index of the mesh point.
Definition brzone.hpp:148
mesh_point_t(std::array< long, 3 > const &n, brzone const *m_ptr, long d)
Construct a mesh point with a given index , pointer to the Brillouin zone mesh the mesh point belongs...
Definition brzone.hpp:137
Brillouin zone mesh type.
Definition brzone.hpp:104
mesh_point_t operator()(index_t const &n) const
Function call operator to access a mesh point by its index .
Definition brzone.hpp:359
friend void h5_write(h5::group g, std::string const &name, brzone const &m)
Write a triqs::mesh::brzone mesh to HDF5.
Definition brzone.hpp:501
auto cend() const
Get a const iterator to the end of the mesh.
Definition brzone.hpp:460
value_t to_value(index_t const &n) const
Map an index to its corresponding -point .
Definition brzone.hpp:368
bool is_index_valid(index_t const &n) const noexcept
Check if an index is valid, i.e. corresponds to a in the first BZ.
Definition brzone.hpp:252
long size() const
Get the size of the mesh, i.e. the total number of mesh points in the first BZ.
Definition brzone.hpp:389
brzone(brillouin_zone const &bz, nda::matrix< long > const &M)
Construct a Brillouin zone mesh with the given periodization matrix.
Definition brzone.hpp:232
auto const & dims() const
Get the number of mesh points in each of the three dimensions.
Definition brzone.hpp:374
auto units() const
Get the matrix containing the scaled reciprocal basis vectors in its rows.
Definition brzone.hpp:377
auto end() const
Get an iterator to the end of the mesh.
Definition brzone.hpp:457
index_t to_index(closest_mesh_point_t< V > const &cmp) const
Map a given -vector or expression to the closest in the first BZ and return its index .
Definition brzone.hpp:331
auto units_inv() const
Get the matrix .
Definition brzone.hpp:380
static std::string hdf5_format()
Get the HDF5 format tag.
Definition brzone.hpp:492
index_t closest_index(V const &k) const
Map a given -vector or expression to the closest in the first BZ and return its index .
Definition brzone.hpp:412
auto const & bz() const noexcept
Get the underlying Brillouin zone.
Definition brzone.hpp:383
bool operator==(brzone const &m) const
Equal-to comparison operator compares the underlying Brillouin zone and the number of k-points in eac...
Definition brzone.hpp:466
index_t to_index(data_index_t d) const
Map a data index to the corresponding index .
Definition brzone.hpp:317
data_index_t to_data_index(index_t const &n) const
Map an index to its corresponding data index .
Definition brzone.hpp:264
std::array< long, 3 > index_t
Index type.
Definition brzone.hpp:110
long data_index_t
Data index type.
Definition brzone.hpp:113
mesh_point_t operator[](long d) const
Subscript operator to access a mesh point by its data index .
Definition brzone.hpp:340
brillouin_zone::value_t value_t
Value type.
Definition brzone.hpp:107
data_index_t to_data_index(k_expr_unary< OP, L > const &ex) const
Map an unary -expression to a data index .
Definition brzone.hpp:290
index_t index_modulo(index_t const &n_tilde) const
Map an arbitrary index to the unique index in the first BZ.
Definition brzone.hpp:398
friend void h5_read(h5::group g, std::string const &name, brzone &m)
Read a triqs::mesh::brzone mesh from HDF5.
Definition brzone.hpp:515
mesh_point_t operator[](closest_mesh_point_t< value_t > const &cmp) const
Subscript operator to access a mesh point by a -point contained in a triqs::mesh::closest_mesh_point...
Definition brzone.hpp:350
brzone(brillouin_zone const &bz, long n_k)
Construct a Brillouin zone mesh with the same number of mesh points in each direction.
Definition brzone.hpp:243
uint64_t mesh_hash() const
Get the hash value of the mesh.
Definition brzone.hpp:386
friend std::ostream & operator<<(std::ostream &sout, brzone const &m)
Write a triqs::mesh::brzone mesh to a std::ostream.
Definition brzone.hpp:475
void serialize(auto &ar) const
Serialize the mesh to a generic archive.
Definition brzone.hpp:483
void deserialize(auto &ar)
Deserialize the mesh from a generic archive.
Definition brzone.hpp:489
brzone()=default
Default constructor constructs an empty mesh.
auto cbegin() const
Get a const iterator to the beginning of the mesh.
Definition brzone.hpp:454
data_index_t to_data_index(k_expr< OP, L, R > const &ex) const
Map a binary -expression to a data index .
Definition brzone.hpp:305
auto begin() const
Get an iterator to the beginning of the mesh.
Definition brzone.hpp:451
data_index_t to_data_index(closest_mesh_point_t< V > const &cmp) const
Map a -vector to its data index .
Definition brzone.hpp:277
brzone(brillouin_zone const &bz, std::array< long, 3 > const &dims)
Construct a Brillouin zone mesh with the given number of mesh points.
Definition brzone.hpp:211
Concept for a Brillouin zone mesh point.
Definition brzone.hpp:628
k_expr<'+', L, R > operator+(L &&l, R &&r)
Lazy addition of two triqs::mesh::BzMeshPoint objects.
Definition brzone.hpp:648
k_expr_unary<'-', L > operator-(L &&l)
Lazy unary minus for triqs::mesh::BzMeshPoint objects.
Definition brzone.hpp:637
k_expr<' *', long, R > operator*(Int l, R &&r)
Lazy multiplication of a triqs::mesh::BzMeshPoint object with a scalar.
Definition brzone.hpp:670
constexpr bool is_k_expr
Type trait to check if a type is a triqs::mesh::k_expr or triqs::mesh::k_expr_unary.
Definition k_expr.hpp:129
uint64_t hash(Ts &&...ts)
Generic hash function for multiple arguments.
Definition utils.hpp:70
long positive_modulo(long x, long y)
Calculate the positive modulo of two integer numbers.
Definition utils.hpp:111
Provides expression templates for -vectors.
Common macros used in TRIQS.
Provides various utilities used with Meshes.
Provides a generic random access iterator for 1D meshes.
constexpr nda::clef::placeholder< 3 > w
Placeholder for the frequency .
Lazy struct used in various function overloads as a placeholder for the closest mesh point to a given...
Definition utils.hpp:186
T value
Use the mesh point closest to this value.
Definition utils.hpp:188
Unary minus -vector expression.
Definition k_expr.hpp:46
auto index() const
Get the index of the reciprocal vector (see triqs::mesh::brzone::mesh_point_t::index()).
Definition k_expr.hpp:57
uint64_t mesh_hash() const
Get the hash value of the mesh to which the operand belongs.
Definition k_expr.hpp:51
Binary -vector expression.
Definition k_expr.hpp:67
uint64_t mesh_hash() const
Get the hash value of the mesh to which the right hand side operand belongs.
Definition k_expr.hpp:122
auto index() const
Get the index of the -vector corresponding to the evaluated expression.
Definition k_expr.hpp:109
A generic random access iterator for 1D meshes.