TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
tight_binding.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2013-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2016 Igor Krivenko
4// Copyright (c) 2018-2023 Simons Foundation
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: Michel Ferrero, Igor Krivenko, Olivier Parcollet, Nils Wentzell, Thomas Ayral
20
25
26#pragma once
27
28#include "./brillouin_zone.hpp"
29#include "../gfs/gf/gf.hpp"
30#include "../mesh/brzone.hpp"
31#include "../utility/macros.hpp"
32
33#include <h5/h5.hpp>
34#include <itertools/itertools.hpp>
35#include <nda/linalg.hpp>
36#include <nda/nda.hpp>
37#include <nda/stdutil/complex.hpp>
38
39#include <cmath>
40#include <iostream>
41#include <string>
42#include <utility>
43#include <vector>
44
45namespace triqs::lattice {
46
51
60 struct C2PY_IGNORE hopping_dict {
62 std::vector<nda::vector<long>> displ_vec;
63
65 std::vector<nda::matrix<dcomplex>> overlap_mat_vec;
66 };
67
84
86 std::vector<nda::vector<long>> displ_vec_;
87 std::vector<nda::matrix<dcomplex>> overlap_mat_vec_;
88
89 void check_hoppings();
90
91 public:
104 tight_binding(bravais_lattice bl, std::vector<nda::vector<long>> displ_vec, std::vector<nda::matrix<dcomplex>> overlap_mat_vec);
105
113
115 bravais_lattice const &lattice() const { return bl_; }
116
118 auto const &displ_vec() const { return displ_vec_; }
119
121 auto const &overlap_mat_vec() const { return overlap_mat_vec_; }
122
131 template <typename R> r_t lattice_to_real_coordinates(R const &x) const { return bl_.lattice_to_real_coordinates(x); }
132
134 long n_orbitals() const { return bl_.n_orbitals(); }
135
142 template <typename F> friend void foreach (tight_binding const &tb, F f) {
143 int n = static_cast<int>(tb.displ_vec_.size());
144 for (int i = 0; i < n; ++i) f(tb.displ_vec_[i], tb.overlap_mat_vec_[i]);
145 }
146
161 template <typename K>
162 requires(nda::ArrayOfRank<K, 1> or nda::ArrayOfRank<K, 2>)
163 auto fourier(K const &k) const {
164 // Make sure to account for ndim in lattice
165 auto k_ndim = make_regular(k(nda::ellipsis(), range(lattice().ndim())));
166
167 auto vals = [&](int j) {
168 if constexpr (nda::ArrayOfRank<K, 1>) {
169 return std::exp(2i * M_PI * nda::linalg::dot_generic(k_ndim, displ_vec_[j])) * overlap_mat_vec_[j];
170 } else { // Rank==2
171 auto k_mat = nda::make_matrix_view(k_ndim);
172 auto exp = [](auto d) { return std::exp(d); };
173 auto exp_j = make_regular(nda::map(exp)(2i * M_PI * k_mat * displ_vec_[j]));
174 return nda::linalg::outer_product(exp_j, overlap_mat_vec_[j]);
175 }
176 };
177 auto res = make_regular(vals(0));
178 for (int i = 1; i < displ_vec_.size(); ++i) res += vals(i);
179 return res;
180 }
181
189 inline auto fourier(mesh::brzone const &k_mesh) const {
190 auto kvecs = nda::matrix<double>(k_mesh.size(), 3);
191 for (auto [n, k] : itertools::enumerate(k_mesh)) { kvecs(n, range::all) = k.value(); }
192 auto kvecs_rec = make_regular(kvecs * k_mesh.bz().reciprocal_matrix_inv());
194 h_k.data() = fourier(kvecs_rec);
195 return h_k;
196 }
197
205 inline auto fourier(int n_l) const {
206 auto k_mesh = mesh::brzone(brillouin_zone{bl_}, n_l);
207 return fourier(k_mesh);
208 }
209
218 template <typename K>
219 auto dispersion(K const &k) const
220 requires(nda::ArrayOfRank<K, 1> or nda::ArrayOfRank<K, 2>)
221 {
222 if constexpr (nda::ArrayOfRank<K, 1>) {
223 return nda::linalg::eigvalsh(fourier(k));
224 } else { // Rank==2
225 auto h_k = fourier(k);
226 auto n_k = h_k.shape()[0];
227 auto res = nda::array<double, 2>(n_k, n_orbitals());
228 for (auto l : range(n_k)) res(l, range::all) = nda::linalg::eigvalsh(h_k(l, nda::ellipsis()));
229 return res;
230 }
231 }
232
240 inline auto dispersion(mesh::brzone const &k_mesh) const {
241 auto h_k = fourier(k_mesh);
243 for (auto k : k_mesh) e_k[k] = nda::linalg::eigvalsh(h_k[k]);
244 return e_k;
245 }
246
254 inline auto dispersion(int n_l) const {
255 auto k_mesh = mesh::brzone(brillouin_zone{bl_}, n_l);
256 return dispersion(k_mesh);
257 }
258
259 // ------------------- Comparison -------------------
260
262 bool operator==(tight_binding const &tb) const { return bl_ == tb.bl_ && overlap_mat_vec_ == tb.overlap_mat_vec_ && displ_vec_ == tb.displ_vec_; }
263
265 bool operator!=(tight_binding const &tb) const { return !(operator==(tb)); }
266
267 // -------------------- print -------------------
268
276 friend std::ostream &operator<<(std::ostream &sout, tight_binding const &tb) {
277 sout << "Tight Binding Hamiltonian on " << tb.lattice() << "\nwith hoppings [";
278 for (auto const &[displ, overlap_mat] : itertools::zip(tb.displ_vec(), tb.overlap_mat_vec())) sout << "\n " << displ << " : " << overlap_mat;
279 return sout << " ]";
280 }
281
282 // ------------------- HDF5 Read / Write -------------------
283
285 [[nodiscard]] static std::string hdf5_format() { return "tight_binding"; }
286
294 friend void h5_write(h5::group fg, std::string subgroup_name, tight_binding const &tb) {
295 auto grp = fg.create_group(subgroup_name);
296 write_hdf5_format(grp, tb); // NOLINT
297 h5_write(grp, "bravais_lattice", tb.bl_);
298 h5_write(grp, "displ_vec", tb.displ_vec_);
299 h5_write(grp, "overlap_mat_vec", tb.overlap_mat_vec_);
300 }
301
309 CPP2PY_IGNORE
310 static tight_binding h5_read_construct(h5::group g, std::string subgroup_name) {
311 auto grp = g.open_group(subgroup_name);
312 auto bl = h5::h5_read<bravais_lattice>(grp, "bravais_lattice");
313 auto displ_vec = h5::h5_read<std::vector<nda::vector<long>>>(grp, "displ_vec");
314 auto overlap_mat_vec = h5::h5_read<std::vector<nda::matrix<dcomplex>>>(grp, "overlap_mat_vec");
316 }
317
318 }; // tight_binding
319
333 std::pair<nda::array<double, 1>, nda::array<double, 2>> dos(tight_binding const &TB, int nkpts, int neps);
334
348 std::pair<nda::array<double, 1>, nda::array<double, 1>> dos_patch(tight_binding const &TB, const nda::array<double, 2> &triangles, int neps,
349 int ndiv);
350
352
353} // namespace triqs::lattice
Provides a Brillouin zone class.
Provides a mesh type for Brillouin zones.
The owning Green's function container.
Definition gf.hpp:194
data_t & data() &
Get the data array.
Definition gf.hpp:280
A Brillouin zone class.
Tight-binding Hamiltonian on a Bravais lattice with fully localised orbitals.
static tight_binding h5_read_construct(h5::group g, std::string subgroup_name)
Construct a tight-binding Hamiltonian by reading it from HDF5.
auto fourier(K const &k) const
Compute the Fourier transform for a given momentum vector (or array of momentum vectors).
friend void h5_write(h5::group fg, std::string subgroup_name, tight_binding const &tb)
Write a tight-binding Hamiltonian to HDF5.
r_t lattice_to_real_coordinates(R const &x) const
Transform a vector from the lattice basis to the standard basis.
long n_orbitals() const
Number of orbitals (also the size of the Bloch Hamiltonian matrix ).
bravais_lattice const & lattice() const
Get the underlying Bravais lattice.
auto dispersion(mesh::brzone const &k_mesh) const
Compute the dispersion on a given Brillouin zone mesh.
auto fourier(mesh::brzone const &k_mesh) const
Compute the Fourier transform on a given Brillouin zone mesh.
auto dispersion(K const &k) const
Compute the dispersion, i.e. the eigenvalue spectrum of , for a given momentum vector (or array of mo...
tight_binding(bravais_lattice bl, std::vector< nda::vector< long > > displ_vec, std::vector< nda::matrix< dcomplex > > overlap_mat_vec)
Construct a tight-binding Hamiltonian on a given Bravais lattice from explicit displacement and overl...
auto const & displ_vec() const
Get the list of displacement vectors, in units of the lattice basis vectors.
auto dispersion(int n_l) const
Compute the dispersion on a regular Brillouin zone mesh with n_l points per dimension.
bool operator!=(tight_binding const &tb) const
Not-equal-to comparison operator (negation of operator==()).
friend std::ostream & operator<<(std::ostream &sout, tight_binding const &tb)
Write a tight-binding Hamiltonian to a std::ostream.
auto const & overlap_mat_vec() const
Get the list of overlap (hopping) matrices, aligned with the displacement vectors.
static std::string hdf5_format()
Get the HDF5 format tag.
bool operator==(tight_binding const &tb) const
Equal-to comparison operator. True if the underlying lattice, displacements and overlap matrices all ...
auto fourier(int n_l) const
Compute the Fourier transform on a regular Brillouin zone mesh with n_l points per dimension.
Brillouin zone mesh type.
Definition brzone.hpp:104
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
auto const & bz() const noexcept
Get the underlying Brillouin zone.
Definition brzone.hpp:383
Provides the Green's function class.
std::pair< array< double, 1 >, array< double, 2 > > dos(tight_binding const &TB, int nkpts, int neps)
Compute the density of states of a tight-binding Hamiltonian on a regular k-grid.
nda::vector< double > r_t
Real space vector type.
Common macros used in TRIQS.
Ordered dictionary mapping lattice displacements to hopping (overlap) matrices.
std::vector< nda::matrix< dcomplex > > overlap_mat_vec
std::vector of nda::matrix<dcomplex> overlap (hopping) matrices, one per displacement.
std::vector< nda::vector< long > > displ_vec
std::vector of nda::vector<long> displacement vectors, in units of the lattice basis vectors.