TRIQS/triqs_modest 3.3.0
Brillouin zone summation
Loading...
Searching...
No Matches
loaders.cpp
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#include "loaders.hpp"
8#include "utils/nda_supp.hpp"
9#include "utils/h5_proxy.hpp"
10#include "utils/to_vector.hpp"
11#include "utils/graph_algo.hpp"
12
13namespace triqs::modest {
15
17 nda::matrix<dcomplex> svd(const nda::matrix<dcomplex> &A) {
18 auto Acopy = nda::matrix<dcomplex, nda::F_layout>{transpose(A)};
19 long m = Acopy.extent(0);
20 // auto S = nda::vector<double>(m);
21 auto U = nda::matrix<dcomplex, nda::F_layout>(m, m);
22 auto VT = nda::matrix<dcomplex, nda::F_layout>(m, m);
23 [[maybe_unused]] auto status = nda::lapack::gesvd(Acopy, nda::vector<double>(m), U, VT);
24 return nda::matrix<dcomplex>{transpose(U * VT)};
25 }
26
27 namespace detail {
29 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,
30 std::vector<atomic_orbs> const &new_space) {
31 auto n_atoms = new_space.size();
32 auto n_sigma = T.extent(1);
33 auto Tembed = nda::array<std::vector<long>, 2>(n_atoms, n_sigma);
34
35 auto old_indices = old_space | stdv::transform([](auto &x) { return x.dft_idx; }) | tl::to<std::vector>();
36 auto new_indices = new_space | stdv::transform([](auto &x) { return x.dft_idx; }) | tl::to<std::vector>();
37
38 for (auto const &[n, nidx] : enumerate(new_indices)) {
39 if (auto it = std::find(begin(old_indices), end(old_indices), nidx); it != end(old_indices)) {
40 auto uidx = std::distance(begin(old_indices), it);
41 Tembed(n, r_all) = T(uidx, r_all);
42 } else {
43 Tembed(n, r_all) = std::vector<long>{long(new_space[n].dim)};
44 }
45 }
46 return Tembed;
47 }
48 } // namespace detail
49
50 //-------------------------------------------------------
53 std::pair<nda::array<std::vector<long>, 2>, nda::array<nda::matrix<dcomplex>, 2>>
54 discover_symmetries(nda::array<nda::matrix<dcomplex>, 2> const &Hloc0, std::vector<atomic_orbs> const &atomic_shells, double block_threshold,
55 bool diagonalize_hloc) {
56
57 auto [n_atoms, n_sigma] = Hloc0.shape();
58 auto decomposition = nda::array<std::vector<long>, 2>(n_atoms, n_sigma);
59 auto U_rotation = nda::array<nda::matrix<dcomplex>, 2>(n_atoms, n_sigma);
60
61 for (auto const &[atom, shell] : enumerate(atomic_shells)) {
62 for (auto sigma : nda::range(n_sigma)) {
63 auto D = find_blocks(nda::matrix<double>{abs(Hloc0(atom, sigma))}, block_threshold);
64 U_rotation(atom, sigma) = nda::make_matrix_from_permutation<dcomplex>(nda::flatten(D));
65 decomposition(atom, sigma) = D | stdv::transform([](auto &x) { return long(x.size()); }) | tl::to<std::vector>();
66
67 // diagonalize the hloc0 to find a new basis of orbitals
68 if (diagonalize_hloc) {
69 auto U_diag = nda::matrix<dcomplex>(shell.dim, shell.dim);
70 for (auto &&[idx, r_idx] : enumerated_sub_slices(decomposition(atom, sigma))) {
71 auto hperm = dagger(U_rotation(atom, sigma)) * Hloc0(atom, sigma) * U_rotation(atom, sigma);
72 U_diag(r_idx, r_idx) = std::get<1>(nda::linalg::eigenelements(hperm(r_idx, r_idx)));
73 }
74 U_rotation(atom, sigma) *= U_diag;
75 }
76 }
77 }
78 return {decomposition, U_rotation};
79 }
80
81 //-------------------------------------------------------
83 enum class ReadMode {
84 Correlated, // reads bands, projectors, and correlated shells from "dft_input"
85 ThetaProjectors, // read bands ands shells from "dft_input" and projectors from "dft_parproj_input" ("proj_mat_all")
86 Bands // read bands and projectors from "dft_bands_input"
87 };
88
89 //-------------------------------------------------------
91 std::vector<cmat_t> read_rotation_matrices(std::string const &filename, ReadMode mode) {
92
93 auto root = h5::proxy{filename, 'r'};
94 auto SO = long(root["dft_input"]["SO"]);
95
96 auto read_mats = [SO](auto group, auto name1, auto name2) {
97 auto mats = to_vector<cmat_t>(sort_keys_as_int(group[name1]));
98 auto mats_tinv = to_vector<long>(sort_keys_as_int(group[name2]));
99 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>>();
100
101 // NB: mat = D(R_{\alpaha})
102 // if mat has time inversion symmetry (T), then T*D(R_{\alpha}) = -D(R_{\alpha})
103 return mats
104 | stdv::transform([mats_tinv_and_SO, i = 0](cmat_t const &x) mutable { return (mats_tinv_and_SO[i++] == 1) ? -conj(svd(x)) : svd(x); })
105 | tl::to<std::vector<cmat_t>>();
106 };
107 return (mode == ReadMode::Correlated) ? read_mats(root["dft_input"], "rot_mat", "rot_mat_time_inv") :
108 (mode == ReadMode::ThetaProjectors) ? read_mats(root["dft_parproj_input"], "rot_mat_all", "rot_mat_all_time_inv") :
109 throw std::runtime_error("This should not happen!");
110 }
111
112 //-------------------------------------------------------
114 nda::array<dcomplex, 4> load_rotate_and_format_projectors(std::string const &filename, ReadMode mode, std::vector<cmat_t> const &rot_mats,
115 std::vector<long> const &atom_decomp) {
116 auto load_Pks = [](auto f, auto m) {
117 auto root = h5::proxy{f, 'r'};
118 if (m == ReadMode::Correlated || m == ReadMode::Bands) {
119 return (m == ReadMode::Correlated) ? as<nda::array<dcomplex, 5>>(root["dft_input"]["proj_mat"]) :
120 as<nda::array<dcomplex, 5>>(root["dft_bands_input"]["proj_mat"]);
121 } else if (m == ReadMode::ThetaProjectors) {
122 auto tmp = as<nda::array<dcomplex, 6>>(root["dft_parproj_input"]["proj_mat_all"]);
123 // FIXME: The θ projectors have an extra dimesion called ir. Not sure why it is there...
124 return nda::array<dcomplex, 5>{tmp(r_all, r_all, r_all, 0, r_all, r_all)};
125 } else {
126 throw std::runtime_error{"This should not happen!"};
127 }
128 };
129
130 auto P_k_tmp = load_Pks(filename, mode);
131 auto n_atoms = P_k_tmp.extent(2);
132 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>();
133
134 // Merge the rotation matrices R into the Ps: P <- dagger(R) * P
135 auto [n_k, n_sigma, n_m, n_nu] = P_k_list[0].shape(); // NOLINT
136 for (auto isig : range(n_sigma)) {
137 for (auto ik : range(n_k)) {
138 for (auto const &[R, P] : zip(rot_mats, P_k_list)) {
139 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)};
140 }
141 }
142 }
143
144 // Place the P_k_list into the P_k living in the M x M space.
145 long M = stdr::fold_left(atom_decomp, 0, std::plus<>());
146 auto P_k = nda::zeros<dcomplex>(n_k, n_sigma, M, n_nu);
147 for (auto const &[atom, sli] : enumerated_sub_slices(atom_decomp)) {
148 P_k(r_all, r_all, sli, r_all) = P_k_list[atom](r_all, r_all, nda::range(0, atom_decomp[atom]), r_all);
149 }
150 return P_k;
151 }
152
153 //-------------------------------------------------------
155 std::tuple<nda::array<dcomplex, 4>, nda::matrix<long>, nda::array<double, 1>> read_bands_and_weights(std::string filename, ReadMode mode) {
156 auto root = h5::proxy{filename, 'r'};
157 if (mode == ReadMode::Correlated || mode == ReadMode::ThetaProjectors) {
158 auto g_dft = root["dft_input"];
159 return {as<nda::array<dcomplex, 4>>(g_dft["hopping"]), as<nda::matrix<long>>(g_dft["n_orbitals"]),
160 as<nda::array<double, 1>>(g_dft["bz_weights"])};
161 } else if (mode == ReadMode::Bands) {
162 auto g_dft = root["dft_bands_input"];
163 return {as<nda::array<dcomplex, 4>>(g_dft["hopping"]), as<nda::matrix<long>>(g_dft["n_orbitals"]), {}};
164 } else {
165 throw std::runtime_error{"This should not happen!"};
166 }
167 }
168
169 //-------------------------------------------------------
171 spin_kind_e read_spin_kind(auto const &filename) {
172 // set up spin_type
173 auto g_dft = h5::proxy{filename, 'r'}["dft_input"];
174 return (long(g_dft["SO"]) == 1) ? spin_kind_e::NonColinear : ((long(g_dft["SP"]) == 1) ? spin_kind_e::Polarized : spin_kind_e::NonPolarized);
175 }
176
177 //-------------------------------------------------------
179 std::vector<atomic_orbs> read_atomic_shells(auto const &filename, ReadMode mode) {
180 auto g_dft = h5::proxy{filename, 'r'}["dft_input"];
181 return ((mode == ReadMode::Correlated) ? sort_keys_as_int(g_dft["corr_shells"]) : sort_keys_as_int(g_dft["shells"]))
182 | stdv::transform([](auto const &g) {
183 //NB: as<long>(g["atom"]), as<long>(g["dim"]), as<long>(g["equiv_cls_idx"]) );
184 return atomic_orbs{.dim = long(g["dim"]), .l = long(g["l"]), .cls_idx = long(g["sort"]), .dft_idx = long(g["atom"])};
185 })
186 | tl::to<std::vector>();
187 }
188
189 //-------------------------------------------------------
191 nda::array<nda::matrix<dcomplex>, 1> read_spherical_to_dft_basis(std::string dft, std::vector<atomic_orbs> const &atomic_shells) {
192 //TODO: finish this!
193 auto code = dft_code::dft_code_to_enum(dft);
194 auto Ylms = nda::array<nda::matrix<dcomplex>, 1>(atomic_shells.size());
195 for (auto const &[iatom, atom] : enumerate(atomic_shells)) { Ylms(iatom) = dft_code::get_spherical_to_dft_rotation(code, atom.l); }
196 return Ylms;
197 }
198
199 //-------------------------------------------------------
201 ibz_symmetry_ops read_ibz_symmetry_ops(auto const &filename, ReadMode mode) {
202
203 auto root = h5::proxy{filename, 'r'};
204
205 auto rot_mats = read_rotation_matrices(filename, mode);
206 auto atomic_shells = read_atomic_shells(filename, mode);
207
208 auto g_symm = (mode == ReadMode::Correlated) ? root["dft_symmcorr_input"] : root["dft_symmpar_input"];
209 auto symm_ops = ibz_symmetry_ops{};
210
211 // read the symmetrization matrices (Q) for each symmetry operation S in the space group G.
212 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)); })
213 | tl::to<std::vector>();
214
215 // read the permutation table which contains: for each symmetry op S in space group G,
216 // the permutations of all atoms in the crystal structure under S.
217 // dim(perm_table_all) = [number of sym ops][number of atoms in crystal]
218 auto perm_table_all =
219 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>();
220
221 // The permutation table is written for all atoms in the crystal. We must filter to obtain only the correlated atoms.
222 auto corr_atom_to_alpha = std::unordered_map<long, long>{};
223 for (auto iatom : range(atomic_shells.size())) corr_atom_to_alpha[atomic_shells[iatom].dft_idx] = iatom;
224
225 // The filtered permutation table (perm_table_corr): for each sym S, filter only the correlated atoms
226 // and map their indices from dft_idx correlated idx.
227 // dim(perm_table_correlated) = [number of sym ops][number of correlated atoms in crystal]
228 auto perm_table_correlated = perm_table_all | stdv::transform([&](auto const &sym) {
229 return atomic_shells
230 | stdv::transform([&](auto corr_atom) { return corr_atom_to_alpha[sym[corr_atom.dft_idx - 1]]; })
231 | tl::to<std::vector>();
232 })
233 | tl::to<std::vector>();
234
235 // Merge the rotation matrices R into the symmetrization matrices (Qs).
236 for (auto const &[iq, perm] : enumerate(perm_table_correlated)) {
237 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 }
239
240 // Does this op have time inversion symmetry
241 auto time_inv_op = to_vector<long>(sort_keys_as_int(g_symm["time_inv"]));
242 // save the symmetry ops in to the ibz_symmetrizer
243 symm_ops.ops = range(perm_table_correlated.size()) | stdv::transform([symm_ops_mats, perm_table_correlated, time_inv_op](auto const &isym) {
244 return ibz_symmetry_ops::op{symm_ops_mats[isym], perm_table_correlated[isym], time_inv_op[isym]};
245 })
246 | tl::to<std::vector>();
247
248 return symm_ops;
249 };
250
251 //-------------------------------------------------------
253 std::pair<double, one_body_elements_on_grid> one_body_elements_from_dft_converter(std::string const &filename, double threshold,
254 bool diagonalize_hloc) {
255 //TODO: add verbosity, currently not used.
256 auto g_dft = h5::proxy{filename, 'r'}["dft_input"];
257
258 auto total_density = as<double>(g_dft["density_required"]);
259
260 //TODO: FIXME! hdf5 read to strict on long
261 auto charge_below = (as<std::string>(g_dft["dft_code"]) != "w90" && as<std::string>(g_dft["dft_code"]) != "hk") ?
262 as<double>(g_dft["charge_below"]) :
263 as<long>(g_dft["charge_below"]);
264 total_density -= charge_below;
265
267 auto spin_kind = read_spin_kind(filename);
268
270 auto atomic_shells = read_atomic_shells(filename, ReadMode::Correlated);
271
273 auto [H_k, n_bands_per_k, k_weights] = read_bands_and_weights(filename, ReadMode::Correlated);
274
276 auto rot_mats = read_rotation_matrices(filename, ReadMode::Correlated);
277
279 auto atom_decomp = atomic_shells | stdv::transform([](auto &x) { return x.dim; }) | tl::to<std::vector<long>>();
280 auto P_k = load_rotate_and_format_projectors(filename, ReadMode::Correlated, rot_mats, atom_decomp);
281
283 //FIXME: auto symm_ops = (long(g_dft["symm_op"]) == 0) ? ibz_symmetry_ops{} : read_ibz(root, atomic_shells, Rmats);
284 auto symm_ops = (long(g_dft["symm_op"]) == 0) ? std::optional<ibz_symmetry_ops>{} :
285 std::optional<ibz_symmetry_ops>(read_ibz_symmetry_ops(filename, ReadMode::Correlated));
286 auto H_k_is_diagonal = nda::is_diagonal(nda::matrix<dcomplex>{H_k(1, 0, r_all, r_all)});
287 auto eps_k = band_dispersion{
288 .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};
289 auto proj = downfolding_projector{.spin_kind = spin_kind, .P_k = std::move(P_k), .n_bands_per_k = n_bands_per_k};
290
292 auto C_space_no_symm = local_space{spin_kind, atomic_shells, {}, {}, {}};
293 auto obe = one_body_elements_on_grid{.H = eps_k, .C_space = C_space_no_symm, .P = proj, .ibz_symm_ops = std::move(symm_ops)};
294
295 // TODO: verbosity should report the symmetries found (or at least the result of the symmetries found).
296 // auto out = ostream_with_verbosity(std::cout, verbosity);
297 // FIXME: verbosity reporting of local H0 which is used to analyze the symmetries
298 auto Hloc0 = obe.C_space.atomic_view(impurity_levels(obe));
299 auto [decomposition, U_rotations] = discover_symmetries(Hloc0, atomic_shells, threshold, diagonalize_hloc);
300 // FIXME: printing of the local symmetries discovered: eigenvalues (and eigenvectors of Hloc0)
301 // Should we print the rotation matrices as well?
302 // This is a lot of matrices that will be printed...is there a more compact representation?
303 // FIXME : NORMALLY the rotate_local_basis shuold also rotate the local_basis !!!
304 // FIXME !! ---> @ HL : the question is multiply rotation_from_dft_basis LEFT OR RIGHT ?
305 // update the orbital set with the decomposition
306
307 // FIXME: h5_proxy bug?
308 // if (!g_dft.has_key("dft_code")) {
309 // throw std::runtime_error{fmt::format(
310 // "The dft_input group in the hdf5 {} does not contain the key dft_code.\nMost likely, this hdf5 file generated using a legacy dft_tools converter.",
311 // filename)};
312 // }
313
314 obe.C_space = local_space{spin_kind, atomic_shells, decomposition, U_rotations,
315 read_spherical_to_dft_basis(as<std::string>(g_dft["dft_code"]), atomic_shells)};
316 // rotate to the local basis.
317 auto obe_final = rotate_local_basis(U_rotations, std::move(obe));
318 // FIXME: The dft_tools converters do not write the spherical_to_dft rotation for all cases.
319 // Solution: hard-code the rotations for each dft_code (read from hdf5) and save in the local space.
320 // The only issue is dft_code breaks backward compatibility with older hdf5 files.
321 // Therefore the user can either pass at this stage this rotation or in the function that constructs the
322 // slate hamiltonian.
323 return {total_density, std::move(obe_final)};
324 }
325
326 //-------------------------------------------------------
329 //check for group and throw error
330 auto root = h5::proxy{filename, 'r'};
331 if (!root.has_group("dft_parproj_input")) {
332 throw std::runtime_error{fmt::format("The hdf5 file {} does not contain the group dft_parproj_input", filename)};
333 }
334
336 auto atomic_shells = read_atomic_shells(filename, ReadMode::ThetaProjectors);
337
339 auto new_block_decomposition = detail::inject_to_new_space(obe.C_space.atoms_block_decomposition(), obe.C_space.atomic_shells(), atomic_shells);
340
342 auto W_space = local_space{obe.C_space.spin_kind(), atomic_shells, new_block_decomposition, {}, {}};
343
345 auto rot_mats = read_rotation_matrices(filename, ReadMode::ThetaProjectors);
346
348 auto atom_decomp = W_space.atomic_decomposition() | tl::to<std::vector<long>>();
349 auto P_k = load_rotate_and_format_projectors(filename, ReadMode::ThetaProjectors, rot_mats, atom_decomp);
350 auto theta_proj = downfolding_projector{.spin_kind = obe.C_space.spin_kind(), .P_k = std::move(P_k), .n_bands_per_k = obe.H.n_bands_per_k};
351
353 auto symm_ops = (obe.ibz_symm_ops) ? std::optional<ibz_symmetry_ops>(read_ibz_symmetry_ops(filename, ReadMode::ThetaProjectors)) :
354 std::optional<ibz_symmetry_ops>{};
355
356 return one_body_elements_on_grid{.H = obe.H, .C_space = W_space, .P = theta_proj, .ibz_symm_ops = symm_ops};
357 }
358
359 //-------------------------------------------------------
363 auto root = h5::proxy{filename, 'r'};
364 if (!root.has_group("dft_bands_input")) {
365 throw std::runtime_error{fmt::format("The hdf5 file {} does not contain the group dft_bands_input", filename)};
366 }
367
369 auto [H_k, n_bands_per_k, k_weights] = read_bands_and_weights(filename, ReadMode::Bands);
370
372 auto rot_mats = read_rotation_matrices(filename, ReadMode::Correlated);
373
375 auto atom_decomp = obe.C_space.atomic_decomposition() | tl::to<std::vector<long>>();
376 auto P_k = load_rotate_and_format_projectors(filename, ReadMode::Bands, rot_mats, atom_decomp);
377
379 auto eps_k = band_dispersion{
380 .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};
381 auto proj = downfolding_projector{.spin_kind = obe.C_space.spin_kind(), .P_k = std::move(P_k), .n_bands_per_k = n_bands_per_k};
382 auto obe1 = one_body_elements_on_grid{.H = eps_k, .C_space = obe.C_space, .P = proj, .ibz_symm_ops = {}};
383
385 return rotate_local_basis(obe.C_space.rotation_from_dft_to_local_basis(), std::move(obe1));
386 }
387} // namespace triqs::modest
Describe the atomic orbitals within downfolded space.
spin_kind_e spin_kind() const
nda::array< nda::matrix< dcomplex >, 2 > const & rotation_from_dft_to_local_basis() const
List of all (a, sigma) local rotation matices that rotate the data.
nda::array< std::vector< long >, 2 > const & atoms_block_decomposition() const
List of all blocks spanning 𝓒 space -> atoms_block_decomposition.
auto atomic_decomposition() const
Generates [dimension of the 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.
std::pair< double, one_body_elements_on_grid > one_body_elements_from_dft_converter(std::string const &filename, double threshold, bool diagonalize_hloc)
Prepare one-body elements for a DMFT calculation.
Definition loaders.cpp:253
one_body_elements_on_grid one_body_elements_on_high_symmetry_path(std::string const &filename, one_body_elements_on_grid const &obe)
Prepare one-body elements along high-symmetry k-path.
Definition loaders.cpp:361
one_body_elements_on_grid one_body_elements_with_theta_projectors(std::string const &filename, one_body_elements_on_grid const &obe)
Prepare one-body elements with the Θ projectors.
Definition loaders.cpp:328
std::vector< T > flatten(const std::vector< std::vector< T > > &nested)
Definition nda_supp.hpp:26
bool is_diagonal(nda::matrix< T > const &M)
Definition nda_supp.hpp:32
nda::matrix< dcomplex > get_spherical_to_dft_rotation(DFTCode code, long l)
DFTCode dft_code_to_enum(std::string const &code)
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)
Read projectors using ReadMode, rotate to local frame, and embed them in the M space....
Definition loaders.cpp:114
std::tuple< nda::array< dcomplex, 4 >, nda::matrix< long >, nda::array< double, 1 > > read_bands_and_weights(std::string filename, ReadMode mode)
Read band dispersion and k-weights according to ReadMode. (internal)
Definition loaders.cpp:155
nda::array< nda::matrix< dcomplex >, 1 > read_spherical_to_dft_basis(std::string dft, std::vector< atomic_orbs > const &atomic_shells)
Prepare the spherical Ylm to DFT orbital basis rotations. (internal)
Definition loaders.cpp:191
ibz_symmetry_ops read_ibz_symmetry_ops(auto const &filename, ReadMode mode)
Construct the ibz_symmetry_ops according to ReadMode.
Definition loaders.cpp:201
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.
spin_kind_e
Kind of σ index.
nda::matrix< dcomplex > svd(const nda::matrix< dcomplex > &A)
utility to flatten a nested vector (move to utils/ ?)
Definition loaders.cpp:17
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 R = 0 component of a Hamiltonian to determine a GF block structure.
Definition loaders.cpp:54
std::vector< cmat_t > read_rotation_matrices(std::string const &filename, ReadMode mode)
Read rotation matrices from hdf5. (internal)
Definition loaders.cpp:91
spin_kind_e read_spin_kind(auto const &filename)
Setup spin_kind enum. (internal)
Definition loaders.cpp:171
std::vector< atomic_orbs > read_atomic_shells(auto const &filename, ReadMode mode)
Read atomic shells according to ReadMode. (internal)
Definition loaders.cpp:179
ReadMode
Enumerate the different reading modes for the obe factory functions.
Definition loaders.cpp:83
static constexpr auto r_all
Definition defs.hpp:40
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
nda::matrix< dcomplex > cmat_t
Definition defs.hpp:38
Info on an atomic shell.
The one-body dispersion as a function of momentum.
nda::array< long, 2 > n_bands_per_k
n_bands_per_k [k_idx, σ'] = # of nu
spin_kind_e spin_kind
Spin kind of the one-body data.
The projector that downfolds the one-body dispersion (ν) onto local orbitals (m).
A one-body elements struct where all of the underlying data exists on a fixed momentum grid.
C2PY_IGNORE std::optional< ibz_symmetry_ops > ibz_symm_ops
IBZ symmetrizer after a k-sum.