6#include <nda/layout/range.hpp>
7#include <nda/matrix_functions.hpp>
8#include <triqs/gfs.hpp>
9#include <triqs/utility/exceptions.hpp>
12#include <triqs/tb/wannier_loader.hpp>
24 std::vector<atomic_orbs> atomic_shells) {
26 throw std::runtime_error(
"If performing a spin-polarized calculation, you need to supply two Wannier file paths for up and down channels.\n");
30 auto [R, HR, _] = read_wannier90_tb_data(wannier_file_path);
31 std::vector<tb_hamiltonian> tb_H;
32 tb_H.emplace_back(R, HR);
36 return make_obe_from_tb(std::move(tb_H), spin_kind, std::move(atomic_shells));
40 spin_kind_e spin_kind, std::vector<atomic_orbs> atomic_shells) {
41 std::vector<tb_hamiltonian> tb_H = {tb_hamiltonian(Rs, HR)};
43 return make_obe_from_tb(std::move(tb_H), spin_kind, std::move(atomic_shells));
47 std::vector<nda::array<dcomplex, 2>>
const &HR_dn,
spin_kind_e spin_kind,
48 std::vector<atomic_orbs> atomic_shells) {
49 std::vector<tb_hamiltonian> tb_H = {tb_hamiltonian(Rs, HR_up), tb_hamiltonian(Rs, HR_dn)};
50 return make_obe_from_tb(std::move(tb_H), spin_kind, std::move(atomic_shells));
54 spin_kind_e spin_kind, std::vector<atomic_orbs> atomic_shells) {
56 throw std::runtime_error(
"For a non-spin polarized calculation, you should specify only one Wannier Hamiltonian.\n");
60 std::vector<tb_hamiltonian> tb_H;
61 for (
auto file : {wannier_file_path_up, wannier_file_path_dn}) {
62 auto [R, HR, _] = read_wannier90_tb_data(file);
63 tb_H.emplace_back(R, HR);
65 if (tb_H[0].n_orbitals() != tb_H[1].n_orbitals()) {
66 throw std::runtime_error(
67 "Cannot construct a one_body_elements "
68 "using up and down H_k that have a different number of orbtials.");
70 return make_obe_from_tb(std::move(tb_H), spin_kind, std::move(atomic_shells));
75 nda::array<nda::matrix<dcomplex>, 2>
Hloc(std::vector<tb_hamiltonian>
const &H_sigma, std::vector<atomic_orbs>
const &atomic_shells) {
82 nda::array<nda::matrix<dcomplex>, 2> Hloc_result(atomic_shells.size(), H_sigma.size());
84 for (
auto [isigma, H] : enumerate(H_sigma)) {
89 for (
auto shell : atomic_shells) { n_orb += shell.dim; }
90 if (H.n_orbitals() != n_orb) {
91 throw std::runtime_error(
"Wannier Hamiltonian does not have the same number of orbitals as the provided atomic shells: HR "
92 + std::to_string(H.n_orbitals()) +
" , atomic_shells total " + std::to_string(n_orb));
96 auto iR0 = H.get_R_idx(std::array<long, 3>{0, 0, 0});
102 for (
auto &&[ishell, shell] : enumerate(atomic_shells)) {
103 auto Hloc0_ab = nda::zeros<dcomplex>(shell.dim, shell.dim);
105 for (
auto iorb : nda::range(shell.dim)) {
106 for (
auto jorb : nda::range(shell.dim)) { Hloc0_ab(iorb, jorb) = H.hoppings()[iR0](start_orb + iorb, start_orb + jorb); }
107 start_orb += shell.dim;
109 Hloc_result(ishell, isigma) = Hloc0_ab;
116 nda::array<nda::matrix<dcomplex>, 2> Hloc_result(1, obe.
C_space.
n_sigma());
117 for (
auto sigma : range(obe.
C_space.
n_sigma())) { Hloc_result(0, sigma) = obe.
H[sigma].hoppings()[obe.
H[sigma].get_R_idx({0, 0, 0})]; }
126 nda::array<nda::matrix<dcomplex>, 2> hloc =
Hloc(H_sigma, atomic_shells);
129 double block_threshold = 1e-6;
130 bool diagonalize_hloc =
false;
131 auto [decomposition, U] =
discover_symmetries(hloc, atomic_shells, block_threshold, diagonalize_hloc);
134 auto LS =
local_space(spin_kind, atomic_shells, decomposition, U, {});
143 auto new_H = obe.
H | stdv::transform([&](
auto x) {
return fold(sl, x); }) | tl::to<std::vector>();
145 decltype(sh) new_atomic_shells;
147 nda::array<std::vector<long>, 2> new_dec(dec.extent(0) * sl.n_cluster_sites(), dec.extent(1));
148 for (
auto i : nda::range(sl.n_cluster_sites())) {
149 for (
auto &&[j, shell] : enumerate(sh)) {
150 new_atomic_shells.emplace_back(shell);
151 new_dec(i * sh.size() + j,
r_all) = dec(j,
r_all);
161 auto rotate = [](tb_hamiltonian
const &H, nda::matrix<dcomplex>
const &U) {
162 if (U.extent(0) != H.n_orbitals()) {
163 throw std::runtime_error(
164 "Cannot rotate a tb_hamiltonian with a unitary matrix that has a different number of rows than the number of orbitals in the Hamiltonian.");
167 auto const &Rs = H.get_R_list();
168 std::vector<nda::array<dcomplex, 2>> rotated_hoppings;
169 for (
auto const &tR : H.hoppings()) { rotated_hoppings.emplace_back(U * nda::matrix<dcomplex>(tR) * dagger(U)); }
170 return tb_hamiltonian{Rs, std::move(rotated_hoppings)};
173 auto new_H = obe.
H | stdv::transform([&](
auto x) {
return rotate(x, U); }) | tl::to<std::vector>();
175 return {.C_space = obe.
C_space, .H = std::move(new_H)};
181 throw std::runtime_error(
"Can only extend to spin a non-spin-polarized one_body_elements_tb.");
184 auto const &Rs = obe.
H[0].get_R_list();
185 auto const &hoppings = obe.
H[0].hoppings();
187 auto new_orb = 2 * n_orb;
189 auto extend_matrix = [&new_orb, &n_orb](
auto const &mat) {
190 auto ext_mat = nda::array<dcomplex, 2>(new_orb, new_orb);
191 for (
auto const &i : nda::range(n_orb)) {
192 for (
auto const &j : nda::range(n_orb)) {
193 ext_mat(i, j) = mat(i, j);
194 ext_mat(i + n_orb, j + n_orb) = mat(i, j);
200 auto new_hoppings = hoppings | stdv::transform([&](
auto const &tR) {
return extend_matrix(tR); }) | tl::to<std::vector>();
201 auto new_tb_H = std::vector<tb_hamiltonian>{{std::move(Rs), std::move(new_hoppings)}};
204 auto new_atomic_shells = sh
205 | stdv::transform([](
auto const &s) {
return atomic_orbs{.
dim = 2 * s.dim, .l = s.l, .cls_idx = s.cls_idx, .dft_idx = s.dft_idx}; })
206 | tl::to<std::vector>();
212 if (local_term.extent(0) != obe.
C_space.
dim()) {
213 throw std::runtime_error(
"Cannot add a local term with a different dimension than the one_body_elements_tb.");
216 std::vector<tb_hamiltonian> new_tb_H;
217 for (
auto H : obe.
H) {
218 auto hoppings = H.hoppings();
219 auto const &Rs = H.get_R_list();
220 hoppings[H.get_R_idx({0, 0, 0})] += local_term;
221 new_tb_H.emplace_back(Rs, hoppings);
Describe the atomic orbitals within downfolded space.
spin_kind_e spin_kind() const
Spin kind of index.
long n_sigma() const
Dimension of the index.
nda::array< std::vector< long >, 2 > const & atoms_block_decomposition() const
2-dim array of all blocks spanning space -> atoms_block_decomposition.
long dim() const
Dimension of the correlated space.
std::vector< atomic_orbs > const & atomic_shells() const
List of all atomic shells spanning the space.
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.
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.
one_body_elements_tb make_obe_from_tb(std::vector< tb_hamiltonian > H_sigma, spin_kind_e spin_kind, std::vector< atomic_orbs > atomic_shells)
Helper to contruct and return an OBE_tb object given a list of tb_Hamiltonians of length n_sigma.
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 .
one_body_elements_tb fold(tb::superlattice const &sl, one_body_elements_tb const &obe)
spin_kind_e
Kind of σ index.
std::pair< nda::array< std::vector< long >, 2 >, nda::array< nda::matrix< dcomplex >, 2 > > discover_symmetries(nda::array< nda::matrix< dcomplex >, 2 > const &Hloc0, std::vector< atomic_orbs > const &atomic_shells, double block_threshold, bool diagonalize_hloc)
Find symmetries of the component of a Hamiltonian to determine a GF block structure.
nda::array< nda::matrix< dcomplex >, 2 > Hloc(std::vector< tb_hamiltonian > const &H_sigma, std::vector< atomic_orbs > const &atomic_shells)
Compute given tight binding Hamiltonians.
one_body_elements_tb one_body_elements_from_model(std::vector< std::array< long, 3 > > const &Rs, std::vector< nda::array< dcomplex, 2 > > const &HR, spin_kind_e spin_kind, std::vector< atomic_orbs > atomic_shells)
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)
static constexpr auto r_all
long dim
Dimension of the orbital space.
A one-body elements using a tight-binding Hamiltonian.
std::vector< tb_hamiltonian > H
List of TB Hamiltonians.
local_space C_space
Local space.