19 nda::array<std::vector<long>, 2> inject_to_new_space(nda::array<std::vector<long>, 2>
const &T, std::vector<atomic_orbs>
const &old_space,
20 std::vector<atomic_orbs>
const &new_space) {
21 auto n_atoms = new_space.size();
22 auto n_sigma = T.extent(1);
23 auto Tembed = nda::array<std::vector<long>, 2>(n_atoms, n_sigma);
25 auto old_indices = old_space | stdv::transform([](
auto &x) {
return x.dft_idx; }) | tl::to<std::vector>();
26 auto new_indices = new_space | stdv::transform([](
auto &x) {
return x.dft_idx; }) | tl::to<std::vector>();
28 for (
auto const &[n, nidx] : enumerate(new_indices)) {
29 if (
auto it = std::find(begin(old_indices), end(old_indices), nidx); it != end(old_indices)) {
30 auto uidx = std::distance(begin(old_indices), it);
33 Tembed(n,
r_all) = std::vector<long>{long(new_space[n].dim)};
43 std::pair<nda::array<std::vector<long>, 2>, nda::array<nda::matrix<dcomplex>, 2>>
44 discover_symmetries(nda::array<nda::matrix<dcomplex>, 2>
const &Hloc0, std::vector<atomic_orbs>
const &atomic_shells,
double block_threshold,
45 bool diagonalize_hloc) {
47 auto [n_atoms, n_sigma] = Hloc0.shape();
48 auto decomposition = nda::array<std::vector<long>, 2>(n_atoms, n_sigma);
49 auto U_rotation = nda::array<nda::matrix<dcomplex>, 2>(n_atoms, n_sigma);
51 for (
auto const &[atom, shell] : enumerate(atomic_shells)) {
52 for (
auto sigma : nda::range(n_sigma)) {
53 auto D = find_blocks(nda::matrix<double>{abs(Hloc0(atom, sigma))}, block_threshold);
54 U_rotation(atom, sigma) = nda::make_matrix_from_permutation<dcomplex>(
nda::flatten(D));
55 decomposition(atom, sigma) = D | stdv::transform([](
auto &x) {
return long(x.size()); }) | tl::to<std::vector>();
58 if (diagonalize_hloc) {
59 auto U_diag = nda::matrix<dcomplex>(shell.dim, shell.dim);
61 auto hperm = dagger(U_rotation(atom, sigma)) * Hloc0(atom, sigma) * U_rotation(atom, sigma);
62 U_diag(r_idx, r_idx) = std::get<1>(nda::linalg::eigh(hperm(r_idx, r_idx)));
64 U_rotation(atom, sigma) *= U_diag;
68 return {decomposition, U_rotation};
84 auto SO = long(root[
"dft_input"][
"SO"]);
86 auto read_mats = [SO](
auto group,
auto name1,
auto name2) {
87 auto mats = to_vector<cmat_t>(sort_keys_as_int(group[name1]));
88 auto mats_tinv = to_vector<long>(sort_keys_as_int(group[name2]));
89 auto mats_tinv_and_SO = mats_tinv | stdv::transform([SO](
long const &x) {
return (x == 1 && SO == 1) ? 1 : 0; }) | tl::to<std::vector<long>>();
94 auto uv_from_svd = [](
auto const &M) {
95 auto [U, S, V] = nda::linalg::svd(M);
99 return mats | stdv::transform([uv_from_svd, mats_tinv_and_SO, i = 0](
cmat_t const &x)
mutable {
100 return (mats_tinv_and_SO[i++] == 1) ? -conj(uv_from_svd(x)) : uv_from_svd(x);
102 | tl::to<std::vector<cmat_t>>();
104 return (mode ==
ReadMode::Correlated) ? read_mats(root[
"dft_input"],
"rot_mat",
"rot_mat_time_inv") :
106 throw std::runtime_error(
"This should not happen!");
112 std::vector<long>
const &atom_decomp) {
113 auto load_Pks = [](
auto f,
auto m) {
116 return (m ==
ReadMode::Correlated) ? as<nda::array<dcomplex, 5>>(root[
"dft_input"][
"proj_mat"]) :
117 as<nda::array<dcomplex, 5>>(root[
"dft_bands_input"][
"proj_mat"]);
119 auto tmp = as<nda::array<dcomplex, 6>>(root[
"dft_parproj_input"][
"proj_mat_all"]);
123 throw std::runtime_error{
"This should not happen!"};
127 auto P_k_tmp = load_Pks(filename, mode);
128 auto n_atoms = P_k_tmp.extent(2);
129 auto P_k_list = range(n_atoms) | stdv::transform([&](
auto atom) {
return P_k_tmp(
r_all,
r_all, atom,
r_all,
r_all); }) | tl::to<std::vector>();
132 auto [n_k, n_sigma, n_m, n_nu] = P_k_list[0].shape();
133 for (
auto isig : range(n_sigma)) {
134 for (
auto ik : range(n_k)) {
135 for (
auto const &[R, P] : zip(rot_mats, P_k_list)) {
136 P(ik, isig, nda::range(0, R.extent(0)),
r_all) = dagger(R) * nda::matrix<dcomplex>{P(ik, isig, nda::range(0, R.extent(0)),
r_all)};
142 long M = stdr::fold_left(atom_decomp, 0, std::plus<>());
143 auto P_k = nda::zeros<dcomplex>(n_k, n_sigma, M, n_nu);
155 auto g_dft = root[
"dft_input"];
156 return {as<nda::array<dcomplex, 4>>(g_dft[
"hopping"]), as<nda::matrix<long>>(g_dft[
"n_orbitals"]),
157 as<nda::array<double, 1>>(g_dft[
"bz_weights"])};
159 auto g_dft = root[
"dft_bands_input"];
160 return {as<nda::array<dcomplex, 4>>(g_dft[
"hopping"]), as<nda::matrix<long>>(g_dft[
"n_orbitals"]), {}};
162 throw std::runtime_error{
"This should not happen!"};
170 auto g_dft =
h5::proxy{filename,
'r'}[
"dft_input"];
177 auto g_dft =
h5::proxy{filename,
'r'}[
"dft_input"];
178 return ((mode ==
ReadMode::Correlated) ? sort_keys_as_int(g_dft[
"corr_shells"]) : sort_keys_as_int(g_dft[
"shells"]))
179 | stdv::transform([](
auto const &g) {
181 return atomic_orbs{.
dim = long(g[
"dim"]), .l = long(g[
"l"]), .cls_idx = long(g[
"sort"]), .dft_idx = long(g[
"atom"])};
183 | tl::to<std::vector>();
191 auto Ylms = nda::array<nda::matrix<dcomplex>, 1>(atomic_shells.size());
205 auto g_symm = (mode ==
ReadMode::Correlated) ? root[
"dft_symmcorr_input"] : root[
"dft_symmpar_input"];
209 auto symm_ops_mats = sort_keys_as_int(g_symm[
"mat"]) | stdv::transform([](
auto const &g) {
return to_vector<cmat_t>(sort_keys_as_int(g)); })
210 | tl::to<std::vector>();
215 auto perm_table_all =
216 sort_keys_as_int(g_symm[
"perm"]) | stdv::transform([](
auto const &g) {
return to_vector<long>(sort_keys_as_int(g)); }) | tl::to<std::vector>();
219 auto corr_atom_to_alpha = std::unordered_map<long, long>{};
220 for (
auto iatom : range(atomic_shells.size())) corr_atom_to_alpha[atomic_shells[iatom].dft_idx] = iatom;
225 auto perm_table_correlated = perm_table_all | stdv::transform([&](
auto const &sym) {
227 | stdv::transform([&](
auto corr_atom) {
return corr_atom_to_alpha[sym[corr_atom.dft_idx - 1]]; })
228 | tl::to<std::vector>();
230 | tl::to<std::vector>();
233 for (
auto const &[iq, perm] : enumerate(perm_table_correlated)) {
234 for (
auto const &[a, b] : enumerate(perm)) { symm_ops_mats[iq][a] = dagger(rot_mats[b]) * symm_ops_mats[iq][a] * rot_mats[a]; }
238 auto time_inv_op = to_vector<long>(sort_keys_as_int(g_symm[
"time_inv"]));
240 symm_ops.ops = range(perm_table_correlated.size()) | stdv::transform([symm_ops_mats, perm_table_correlated, time_inv_op](
auto const &isym) {
241 return ibz_symmetry_ops::op{symm_ops_mats[isym], perm_table_correlated[isym], time_inv_op[isym]};
243 | tl::to<std::vector>();
249 bool diagonalize_hloc) {
250 auto g_dft =
h5::proxy{filename,
'r'}[
"dft_input"];
252 auto target_density = as<double>(g_dft[
"density_required"]);
256 auto charge_below = (as<std::string>(g_dft[
"dft_code"]) !=
"w90") ? as<double>(g_dft[
"charge_below"]) : as<long>(g_dft[
"charge_below"]);
257 target_density -= charge_below;
272 auto atom_decomp = atomic_shells | stdv::transform([](
auto &x) {
return x.dim; }) | tl::to<std::vector<long>>();
277 auto symm_ops = (long(g_dft[
"symm_op"]) == 0) ? std::optional<ibz_symmetry_ops>{} :
280 auto n_k = H_k.extent(0);
281 auto H_k_is_diagonal =
true;
282 for (
auto ik : range(n_k)) {
284 H_k_is_diagonal =
false;
289 .
spin_kind = spin_kind, .H_k = std::move(H_k), .n_bands_per_k = n_bands_per_k, .k_weights = k_weights, .matrix_valued = !H_k_is_diagonal};
293 auto C_space_no_symm =
local_space{spin_kind, atomic_shells, {}, {}, {}};
300 auto [decomposition, U_rotations] =
discover_symmetries(Hloc0, atomic_shells, threshold, diagonalize_hloc);
315 obe.C_space =
local_space{spin_kind, atomic_shells, decomposition, U_rotations,
324 return {target_density, std::move(obe_final)};
330 bool diagonalize_hloc) {
331 mpi::communicator comm = {};
333 double target_density = 0;
338 mpi::broadcast(target_density, comm, root);
339 mpi::broadcast(obe_final, comm, root);
341 return {target_density, std::move(obe_final)};
347 if (!h5root.has_group(
"dft_parproj_input")) {
348 throw std::runtime_error{fmt::format(
"The hdf5 file {} does not contain the group dft_parproj_input", filename)};
364 auto atom_decomp = W_space.atomic_decomposition() | tl::to<std::vector<long>>();
370 std::optional<ibz_symmetry_ops>{};
378 mpi::communicator comm = {};
384 mpi::broadcast(obe_final, comm, root);
391 if (!h5root.has_group(
"dft_bands_input")) {
392 throw std::runtime_error{fmt::format(
"The hdf5 file {} does not contain the group dft_bands_input", filename)};
407 .
spin_kind = obe.
C_space.
spin_kind(), .H_k = std::move(H_k), .n_bands_per_k = n_bands_per_k, .k_weights = {}, .matrix_valued =
false};
418 mpi::communicator comm;
424 mpi::broadcast(obe_final, comm, root);
Describe the atomic orbitals within downfolded space.
spin_kind_e spin_kind() const
Spin kind of index.
nda::array< nda::matrix< dcomplex >, 2 > const & rotation_from_dft_to_local_basis() const
2-dim array of all local rotation matices that rotate the data.
nda::array< std::vector< long >, 2 > const & atoms_block_decomposition() const
2-dim array of all blocks spanning space -> atoms_block_decomposition.
auto atomic_decomposition() const
Transformed view containing the dimension of each atomic shell.
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_on_grid one_body_elements_on_high_symmetry_path(std::string const &filename, one_body_elements_on_grid const &obe)
Create a one-body elements along specific k-path.
std::pair< double, one_body_elements_on_grid > one_body_elements_from_dft_converter(std::string const &filename, double threshold, bool diagonalize_hloc)
Create a one-body elements with orthonormalized projectors.
one_body_elements_on_grid one_body_elements_with_theta_projectors(std::string const &filename, one_body_elements_on_grid const &obe)
Create a one-body elements with the projectors.
std::vector< T > flatten(const std::vector< std::vector< T > > &nested)
bool is_diagonal(nda::matrix< T > const &M)
nda::array< dcomplex, 4 > load_rotate_and_format_projectors(std::string const &filename, ReadMode mode, std::vector< cmat_t > const &rot_mats, std::vector< long > const &atom_decomp)
one_body_elements_on_grid read_theta_projectors_for_obe(const std::string &filename, const one_body_elements_on_grid &obe)
std::tuple< nda::array< dcomplex, 4 >, nda::matrix< long >, nda::array< double, 1 > > read_bands_and_weights(std::string filename, ReadMode mode)
nda::array< nda::matrix< dcomplex >, 1 > read_spherical_to_dft_basis(std::string dft, std::vector< atomic_orbs > const &atomic_shells)
ibz_symmetry_ops read_ibz_symmetry_ops(auto const &filename, ReadMode mode)
one_body_elements_on_grid rotate_local_basis(nda::array< nda::matrix< dcomplex >, 2 > const &U, one_body_elements_on_grid const &x)
Rotates the local basis of the downfolding projector.
std::pair< double, one_body_elements_on_grid > read_obe_from_dft_converter_hdf5(std::string const &filename, double threshold, bool diagonalize_hloc)
spin_kind_e
Kind of σ index.
one_body_elements_on_grid read_data_on_high_symm_path_for_obe(const std::string &filename, const one_body_elements_on_grid &obe)
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.
std::vector< cmat_t > read_rotation_matrices(std::string const &filename, ReadMode mode)
spin_kind_e read_spin_kind(auto const &filename)
std::vector< atomic_orbs > read_atomic_shells(auto const &filename, ReadMode mode)
static constexpr auto r_all
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
nda::matrix< dcomplex > cmat_t
long dim
Dimension of the orbital space.
The one-body dispersion as a function of momentum.
nda::array< long, 2 > n_bands_per_k
Number of bands for each k-point and .
spin_kind_e spin_kind
Spin kind of the one-body data.
The projector that downfolds the energy bands onto a set of localized atomic-like orbitals.
spin_kind_e spin_kind
Spin kind of the one-body data.
Irreducible Brillouin Zone (IBZ) symmetry operations to symmetrize observables over the entire Brillo...
A one-body elements struct where all of the underlying data exists on a fixed momentum grid.
std::optional< ibz_symmetry_ops > ibz_symm_ops
IBZ symmetrizer after a k-sum.
local_space C_space
Local space.
band_dispersion H
Band dispersion.