TRIQS/triqs_modest 3.3.0
Modular Electronic Structure Toolkit
Loading...
Searching...
No Matches
obe_tb.hpp
Go to the documentation of this file.
1// Copyright (c) 2025--present, The Simons Foundation
2// This file is part of TRIQS/modest and is licensed under the terms of GPLv3 or later.
3// SPDX-License-Identifier: GPL-3.0-or-later
4// See LICENSE in the root of this distribution for details.
5
6#pragma once
7#include <mpi/mpi.hpp>
8#include <nda/nda.hpp>
9
10#include <triqs/experimental.hpp>
11#include <triqs/mesh/imfreq.hpp>
12#include <triqs/gfs.hpp>
13#include <triqs/experimental/utility/root_finder.hpp>
14#include <triqs/utility/macros.hpp>
15
16#include "downfolding.hpp"
17#include "loaders.hpp"
19
20namespace triqs::modest {
21
22 using namespace triqs::experimental::lattice;
23 using namespace triqs::experimental::utility;
24
31 std::vector<tb_hk> H;
32 // downfolding_projector P;
33 // C2PY_IGNORE std::optional<ibz_symmetry_ops> ibz_symm_ops = {}; //< IBZ symmetrizer after a k-sum
34
43 one_body_elements_tb(std::vector<tb_hk> H_sigma, local_space ls) : C_space{std::move(ls)}, H{std::move(H_sigma)} {};
44
54 one_body_elements_tb(std::vector<tb_hk> H_sigma, spin_kind_e spin_kind, std::vector<atomic_orbs> atomic_shells);
55
57 bool operator==(one_body_elements_tb const &) const = default;
58
60 C2PY_IGNORE friend void mpi_broadcast(one_body_elements_tb &x, mpi::communicator c = {}, int root = 0) {
61 mpi::broadcast(x.C_space, c, root);
62 mpi::broadcast(x.H, c, root);
63 }
64 };
65
70
81 one_body_elements_tb one_body_elements_from_wannier90(std::string const &wannier_file_path, spin_kind_e spin_kind,
82 std::vector<atomic_orbs> atomic_shells);
83
96 one_body_elements_tb one_body_elements_from_wannier90(std::string const &wannier_file_path_up, std::string const &wannier_file_path_dn,
97 spin_kind_e spin_kind, std::vector<atomic_orbs> atomic_shells);
98 // tb factories
100
109 nda::array<nda::matrix<dcomplex>, 2> Hloc(std::vector<tb_hk> const &H_sigma, std::vector<atomic_orbs> const &atomic_shells);
110
118 nda::array<nda::matrix<dcomplex>, 2> impurity_levels(one_body_elements_tb const &obe);
119
127 one_body_elements_tb fold(superlattice const &sl, one_body_elements_tb const &obe);
128
138 one_body_elements_tb rotate(one_body_elements_tb const &obe, nda::matrix<dcomplex> const &U);
139
140 one_body_elements_tb extend_to_spin(one_body_elements_tb const &obe);
141 one_body_elements_tb add_local_term(one_body_elements_tb const &obe, nda::matrix<dcomplex> const &local_term);
142
143 // -----------------------------------------------------------------------
144
148
165 template <typename Mesh>
166 block2_gf<Mesh, matrix_valued> gloc(one_body_elements_tb const &obe, double mu, block2_gf<Mesh, matrix_valued> const &Sigma_dynamic,
167 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static, bz_int_options const &opt) {
168
169 auto &mesh = Sigma_dynamic(0, 0).mesh();
170 auto n_sigma = obe.C_space.n_sigma();
171 auto gloc_result = make_block2_gf(mesh, obe.C_space.Gc_block_shape());
172 if (n_sigma != Sigma_static.shape(1)) { throw std::runtime_error("Mismatch between the spin channels in Sigma_Static and Sigma_Dynamic"); }
173 if (n_sigma != obe.H.size()) { throw std::runtime_error("Mismatch between the spin channels in Sigma and spin channels in Hamiltonian."); }
174
175 // Embedding decomposition from structure of Sigma -- provides a list of block names
176 auto embedding_decomp = get_struct(Sigma_dynamic).dims(r_all, 0) | tl::to<std::vector>();
177
178 for (auto sigma : range(n_sigma)) {
179
180 // spin index
181 auto Sigma_full_space = gfs::gf(mesh, {obe.H[sigma].n_orbitals(), obe.H[sigma].n_orbitals()}); //
182 for (auto &&[block, R] : enumerated_sub_slices(embedding_decomp)) {
183 for (auto [n, w] : enumerate(mesh)) {
184 Sigma_full_space.data()(n, R, R) = Sigma_dynamic(block, sigma).data()(n, r_all, r_all) + Sigma_static(block, sigma);
185 }
186 }
187 // Call the TRIQS version of this function
188 gloc_result(0, sigma) = gloc(obe.H[sigma], mu, Sigma_full_space, opt);
189 }
190 return gloc_result;
191 }
192
206 template <typename Mesh>
207 block2_gf<Mesh, matrix_valued> gloc(Mesh const &mesh, one_body_elements_tb const &obe, double mu, bz_int_options const &opt) {
208 auto result = make_block2_gf(mesh, obe.C_space.Gc_block_shape());
209 for (auto sigma : range(obe.C_space.n_sigma())) { result(0, sigma) = gloc(mesh, obe.H[sigma], mu, opt); }
210 return result;
211 }
212
214
215 // -----------------------------------------------------------------------
216
229 template <typename Mesh>
230 double density(one_body_elements_tb const &obe, double mu, block2_gf<Mesh, matrix_valued> const &Sigma_dynamic,
231 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static, bz_int_options const &opt) {
232
233 // auto n_blocks = Sigma_dynamic.size1();
234 auto n_sigma = obe.C_space.n_sigma();
235
236 double n = 0;
237 auto Gloc = gloc(obe, mu, Sigma_dynamic, Sigma_static, opt); // returns block2gf (1, nsigma, {norb, norb})
238 // return type of Gloc is a B2GF with dimensions (1, nspin, {norb, norb})
239 for (auto sigma : range(n_sigma)) { // spin index
240 n += real(nda::trace(density(Gloc(0, sigma))));
241 }
242 return n;
243 }
244
256 template <typename Mesh> double density(one_body_elements_tb const &obe, double mu, Mesh const &mesh, bz_int_options const &opt) {
257
258 auto Sigma_dynamic = make_block2_gf(mesh, obe.C_space.Gc_block_shape());
259 auto Sigma_static = nda::array<nda::matrix<dcomplex>, 2>(1, obe.C_space.n_sigma());
260 for (auto [i, j] : Sigma_static.indices()) { Sigma_static(i, j) = nda::zeros<dcomplex>(obe.C_space.dim(), obe.C_space.dim()); }
261 return density(obe, mu, Sigma_dynamic, Sigma_static, opt);
262 }
263
264 // -----------------------------------------------------------------------
280 template <typename Mesh>
281 double find_chemical_potential(double const target_density, one_body_elements_tb const &obe, block2_gf<Mesh, matrix_valued> const &Sigma_dynamic,
282 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static, bz_int_options const &opt,
283 std::string method = "dichotomy", double precision = 1.e-5, bool verbosity = true) {
284 std::function<double(double)> f = [&obe, &Sigma_dynamic, &Sigma_static, &opt](double x) {
285 return density(obe, x, Sigma_dynamic, Sigma_static, opt);
286 };
287 return std::get<0>(
288 root_finder(method, f, 0.0, target_density, precision, 0.5, 1000, "Chemical Potential", "Total Density", verbosity));
289 }
290
305 template <typename Mesh>
306 double find_chemical_potential(double const target_density, one_body_elements_tb const &obe, Mesh const &mesh, bz_int_options const &opt,
307 std::string method = "dichotomy", double precision = 1.e-5, bool verbosity = true) {
308
309 auto Sigma_dynamic = make_block2_gf(mesh, obe.C_space.Gc_block_shape());
310 auto Sigma_static = nda::array<nda::matrix<dcomplex>, 2>(1, obe.C_space.n_sigma());
311 for (auto [i, j] : Sigma_static.indices()) { Sigma_static(i, j) = nda::zeros<dcomplex>(obe.C_space.dim(), obe.C_space.dim()); }
312 return find_chemical_potential(target_density, obe, Sigma_dynamic, Sigma_static, opt, method, precision, verbosity);
313 }
314
315 // -------- instantiations --------------
316
318 template block2_gf<mesh::imfreq, matrix_valued> gloc(one_body_elements_tb const &obe, double mu,
319 block2_gf<mesh::imfreq, matrix_valued> const &Sigma_dynamic,
320 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static, bz_int_options const &opt);
321
322 template block2_gf<mesh::imfreq, matrix_valued> gloc(mesh::imfreq const &mesh, one_body_elements_tb const &obe, double mu,
323 bz_int_options const &opt);
324
325 template double density(one_body_elements_tb const &obe, double mu, block2_gf<mesh::imfreq, matrix_valued> const &Sigma_dynamic,
326 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static, bz_int_options const &opt);
327
328 template double density(one_body_elements_tb const &obe, double mu, mesh::imfreq const &mesh, bz_int_options const &opt);
329
330 template double find_chemical_potential(double const target_density, one_body_elements_tb const &obe,
331 block2_gf<mesh::imfreq, matrix_valued> const &Sigma_dynamic,
332 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static, bz_int_options const &opt, std::string method,
333 double precision, bool verbosity);
334
335 template double find_chemical_potential(double const target_density, one_body_elements_tb const &obe, mesh::imfreq const &mesh,
336 bz_int_options const &opt, std::string method, double precision, bool verbosity);
337
339
340} // namespace triqs::modest
Describe the atomic orbitals within downfolded space.
long n_sigma() const
Dimension of the index.
long dim() const
Dimension of the correlated space.
C2PY_IGNORE gf_struct2_t Gc_block_shape() const
Shape of the Green function in the correlated space, without block decomposition.
block2_gf< Mesh, matrix_valued > gloc(one_body_elements_on_grid const &obe, double mu, block2_gf< Mesh, matrix_valued > const &Sigma_dynamic, nda::array< nda::matrix< dcomplex >, 2 > const &Sigma_static)
Compute local Green's function on a mesh.
nda::array< nda::matrix< dcomplex >, 2 > impurity_levels(one_body_elements_on_grid const &obe)
Compute the local impurity levels from the single-particle dispersion.
double find_chemical_potential(double const target_density, one_body_elements_on_grid const &obe, double beta, std::string method="dichotomy", double precision=1.e-5, bool verbosity=true)
Find the chemical potenital from the local Green's function given a target density.
Definition density.hpp:199
double density(one_body_elements_on_grid const &obe, double mu, block2_gf< Mesh, matrix_valued > const &Sigma_dynamic, nda::array< nda::matrix< dcomplex >, 2 > const &Sigma_static)
Compute the density of the lattice Green's function with a self-energy using Woodbury.
Definition density.hpp:92
one_body_elements_tb(std::vector< tb_hk > H_sigma, local_space ls)
Construct a one-body elements TB object from a list of tb_hk objects.
Definition obe_tb.hpp:43
one_body_elements_tb one_body_elements_from_wannier90(std::string const &wannier_file_path, spin_kind_e spin_kind, std::vector< atomic_orbs > atomic_shells)
Construct a one-body elements TB object from Wannier90 in the case of a single spin index.
Definition obe_tb.cpp:24
gf_struct2_t get_struct(block2_gf< Mesh, matrix_valued > const &g)
Definition gf_supp.hpp:52
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
Definition gf_supp.hpp:41
one_body_elements_tb rotate(one_body_elements_tb const &obe, nda::matrix< dcomplex > const &U)
Rotate a tight-binding Hamiltonian by a unitary matrix .
Definition obe_tb.cpp:142
spin_kind_e
Kind of σ index.
nda::array< nda::matrix< dcomplex >, 2 > Hloc(std::vector< tb_hk > const &H_sigma, std::vector< atomic_orbs > const &atomic_shells)
Compute given tight binding Hamiltonians.
Definition obe_tb.cpp:82
one_body_elements_tb extend_to_spin(one_body_elements_tb const &obe)
Definition obe_tb.cpp:161
one_body_elements_tb add_local_term(one_body_elements_tb const &obe, nda::matrix< dcomplex > const &local_term)
Definition obe_tb.cpp:196
one_body_elements_tb fold(superlattice const &sl, one_body_elements_tb const &obe)
Convert a tight binding Hamiltonian to its superlattice equivalent.
Definition obe_tb.cpp:125
static constexpr auto r_all
Definition defs.hpp:33
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
nda::array< long, 2 > dims
Definition gf_supp.hpp:37
A one-body elements using a tight-binding Hamiltonian.
Definition obe_tb.hpp:29
bool operator==(one_body_elements_tb const &) const =default
Equality comparison operator.
C2PY_IGNORE friend void mpi_broadcast(one_body_elements_tb &x, mpi::communicator c={}, int root=0)
MPI broadcast.
Definition obe_tb.hpp:60
std::vector< tb_hk > H
List of TB Hamiltonians.
Definition obe_tb.hpp:31
local_space C_space
Local space.
Definition obe_tb.hpp:30