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>
22 using namespace triqs::experimental::lattice;
23 using namespace triqs::experimental::utility;
61 mpi::broadcast(x.
C_space, c, root);
62 mpi::broadcast(x.
H, c, root);
82 std::vector<atomic_orbs> atomic_shells);
97 spin_kind_e spin_kind, std::vector<atomic_orbs> atomic_shells);
109 nda::array<nda::matrix<dcomplex>, 2>
Hloc(std::vector<tb_hk>
const &H_sigma, std::vector<atomic_orbs>
const &atomic_shells);
118 nda::array<nda::matrix<dcomplex>, 2>
impurity_levels(one_body_elements_tb
const &obe);
127 one_body_elements_tb
fold(superlattice
const &sl, one_body_elements_tb
const &obe);
138 one_body_elements_tb
rotate(one_body_elements_tb
const &obe, nda::matrix<dcomplex>
const &U);
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);
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) {
169 auto &mesh = Sigma_dynamic(0, 0).mesh();
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."); }
178 for (
auto sigma : range(n_sigma)) {
181 auto Sigma_full_space = gfs::gf(mesh, {obe.
H[sigma].n_orbitals(), obe.
H[sigma].n_orbitals()});
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);
188 gloc_result(0, sigma) =
gloc(obe.
H[sigma], mu, Sigma_full_space, opt);
206 template <
typename Mesh>
209 for (
auto sigma : range(obe.
C_space.
n_sigma())) { result(0, sigma) =
gloc(mesh, obe.
H[sigma], mu, opt); }
229 template <
typename Mesh>
231 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static, bz_int_options
const &opt) {
237 auto Gloc =
gloc(obe, mu, Sigma_dynamic, Sigma_static, opt);
239 for (
auto sigma : range(n_sigma)) {
240 n += real(nda::trace(
density(Gloc(0, sigma))));
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);
280 template <
typename Mesh>
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);
288 root_finder(method, f, 0.0, target_density, precision, 0.5, 1000,
"Chemical Potential",
"Total Density", verbosity));
305 template <
typename Mesh>
307 std::string method =
"dichotomy",
double precision = 1.e-5,
bool verbosity =
true) {
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);
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);
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);
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);
328 template double density(one_body_elements_tb
const &obe,
double mu, mesh::imfreq
const &mesh, bz_int_options
const &opt);
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);
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);
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.
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.
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.
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.
gf_struct2_t get_struct(block2_gf< Mesh, matrix_valued > const &g)
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
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 .
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.
one_body_elements_tb extend_to_spin(one_body_elements_tb const &obe)
one_body_elements_tb add_local_term(one_body_elements_tb const &obe, nda::matrix< dcomplex > const &local_term)
one_body_elements_tb fold(superlattice const &sl, one_body_elements_tb const &obe)
Convert a tight binding Hamiltonian to its superlattice equivalent.
static constexpr auto r_all
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
nda::array< long, 2 > dims
A one-body elements using a tight-binding Hamiltonian.
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.
std::vector< tb_hk > H
List of TB Hamiltonians.
local_space C_space
Local space.