TRIQS/triqs_modest 3.3.0
Modular Electronic Structure Toolkit
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"
7#include "dft_tools/utils.hpp"
9#include "utils/nda_supp.hpp"
10#include "utils/h5_proxy.hpp"
11#include "utils/to_vector.hpp"
12#include "utils/graph_algo.hpp"
13
14namespace triqs::modest {
15 // utility to flatten a nested vector (move to utils/ ?)
16
17 namespace detail {
18 // inject an object T from the C space to W space (used in the context of post-processing).
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);
24
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>();
27
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);
31 Tembed(n, r_all) = T(uidx, r_all);
32 } else {
33 Tembed(n, r_all) = std::vector<long>{long(new_space[n].dim)};
34 }
35 }
36 return Tembed;
37 }
38 } // namespace detail
39
40 //-------------------------------------------------------
41 // Disovers (approximate) irreducible symmetries for Green's function from the non-interacting part of the local
42 // Hamiltonian (H0 = ∑k P(k) Hνν' P†(k) ), which represents the block structure of the TRIQS Gf.
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) {
46
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);
50
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);
55 decomposition(atom, sigma) = D | stdv::transform([](auto &x) { return long(x.size()); }) | tl::to<std::vector>();
56
57 // diagonalize the hloc0 to find a new basis of orbitals
58 if (diagonalize_hloc) {
59 auto U_diag = nda::matrix<dcomplex>(shell.dim, shell.dim);
60 for (auto &&[idx, r_idx] : enumerated_sub_slices(decomposition(atom, sigma))) {
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)));
63 }
64 U_rotation(atom, sigma) *= U_diag;
65 }
66 }
67 }
68 return {decomposition, U_rotation};
69 }
70
71 //-------------------------------------------------------
72 // Enumerate the different reading modes for the obe factory functions.
73 enum class ReadMode {
74 Correlated, // reads bands, projectors, and correlated shells from "dft_input"
75 ThetaProjectors, // read bands ands shells from "dft_input" and projectors from "dft_parproj_input" ("proj_mat_all")
76 Bands // read bands and projectors from "dft_bands_input"
77 };
78
79 //-------------------------------------------------------
80 // Read rotation matrices from hdf5. (internal)
81 std::vector<cmat_t> read_rotation_matrices(std::string const &filename, ReadMode mode) {
82
83 auto root = h5::proxy{filename, 'r'};
84 auto SO = long(root["dft_input"]["SO"]);
85
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>>();
90
91 // NB: mat = D(R_{\alpaha})
92 // if mat has time inversion symmetry (T), then T*D(R_{\alpha}) = -D(R_{\alpha})
93
94 auto uv_from_svd = [](auto const &M) {
95 auto [U, S, V] = nda::linalg::svd(M);
96 return U * V;
97 };
98
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);
101 })
102 | tl::to<std::vector<cmat_t>>();
103 };
104 return (mode == ReadMode::Correlated) ? read_mats(root["dft_input"], "rot_mat", "rot_mat_time_inv") :
105 (mode == ReadMode::ThetaProjectors) ? read_mats(root["dft_parproj_input"], "rot_mat_all", "rot_mat_all_time_inv") :
106 throw std::runtime_error("This should not happen!");
107 }
108
109 //-------------------------------------------------------
110 // Read projectors using ReadMode, rotate to local frame, and embed them in the M space. (internal)
111 nda::array<dcomplex, 4> load_rotate_and_format_projectors(std::string const &filename, ReadMode mode, std::vector<cmat_t> const &rot_mats,
112 std::vector<long> const &atom_decomp) {
113 auto load_Pks = [](auto f, auto m) {
114 auto root = h5::proxy{f, 'r'};
115 if (m == ReadMode::Correlated || m == ReadMode::Bands) {
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"]);
118 } else if (m == ReadMode::ThetaProjectors) {
119 auto tmp = as<nda::array<dcomplex, 6>>(root["dft_parproj_input"]["proj_mat_all"]);
120 // FIXME: The θ projectors have an extra dimesion called ir. Not sure why it is there...
121 return nda::array<dcomplex, 5>{tmp(r_all, r_all, r_all, 0, r_all, r_all)};
122 } else {
123 throw std::runtime_error{"This should not happen!"};
124 }
125 };
126
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>();
130
131 // Merge the rotation matrices R into the Ps: P <- dagger(R) * P
132 auto [n_k, n_sigma, n_m, n_nu] = P_k_list[0].shape(); // NOLINT
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)};
137 }
138 }
139 }
140
141 // Place the P_k_list into the P_k living in the M x M space.
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);
144 for (auto const &[atom, sli] : enumerated_sub_slices(atom_decomp)) {
145 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);
146 }
147 return P_k;
148 }
149
150 //-------------------------------------------------------
151 // Read band dispersion and k-weights according to ReadMode. (internal)
152 std::tuple<nda::array<dcomplex, 4>, nda::matrix<long>, nda::array<double, 1>> read_bands_and_weights(std::string filename, ReadMode mode) {
153 auto root = h5::proxy{filename, 'r'};
154 if (mode == ReadMode::Correlated || mode == ReadMode::ThetaProjectors) {
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"])};
158 } else if (mode == ReadMode::Bands) {
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"]), {}};
161 } else {
162 throw std::runtime_error{"This should not happen!"};
163 }
164 }
165
166 nda::array<long, 3> read_band_window(std::string const &filename) {
167 auto root = h5::proxy{filename, 'r'};
168 // if (!root.has_group("dft_misc_input")) {
169 // throw std::runtime_error{fmt::format("The group dft_misc_input is missing in the hdf5 file ({})", filename)};
170 // }
171 return as<nda::array<long, 3>>(root["dft_misc_input"]["band_window"]);
172 }
173
174 nda::array<double, 2> read_kpts(std::string const &filename) {
175 // TODO: add error handling
176 auto g_dft = h5::proxy{filename, 'r'}["dft_input"];
177 return as<nda::array<double, 2>>(g_dft["kpts"]);
178 }
179
180 //-------------------------------------------------------
181 // Setup spin_kind enum. (internal)
182 spin_kind_e read_spin_kind(auto const &filename) {
183 // set up spin_type
184 auto g_dft = h5::proxy{filename, 'r'}["dft_input"];
185 return (long(g_dft["SO"]) == 1) ? spin_kind_e::NonColinear : ((long(g_dft["SP"]) == 1) ? spin_kind_e::Polarized : spin_kind_e::NonPolarized);
186 }
187
188 //-------------------------------------------------------
189 // Read atomic shells according to ReadMode. (internal)
190 std::vector<atomic_orbs> read_atomic_shells(auto const &filename, ReadMode mode) {
191 auto g_dft = h5::proxy{filename, 'r'}["dft_input"];
192 return ((mode == ReadMode::Correlated) ? sort_keys_as_int(g_dft["corr_shells"]) : sort_keys_as_int(g_dft["shells"]))
193 | stdv::transform([](auto const &g) {
194 //NB: as<long>(g["atom"]), as<long>(g["dim"]), as<long>(g["equiv_cls_idx"]) );
195 return atomic_orbs{.dim = long(g["dim"]), .l = long(g["l"]), .cls_idx = long(g["sort"]), .dft_idx = long(g["atom"])};
196 })
197 | tl::to<std::vector>();
198 }
199
200 //-------------------------------------------------------
201 // Prepare the spherical Ylm to DFT orbital basis rotations. (internal)
202 nda::array<nda::matrix<dcomplex>, 1> read_spherical_to_dft_basis(std::string dft, std::vector<atomic_orbs> const &atomic_shells) {
203 //TODO: finish this!
204 auto code = dft_tools::dft_code_to_enum(dft);
205 auto Ylms = nda::array<nda::matrix<dcomplex>, 1>(atomic_shells.size());
206 for (auto const &[iatom, atom] : enumerate(atomic_shells)) { Ylms(iatom) = dft_tools::get_spherical_to_dft_rotation(code, atom.l); }
207 return Ylms;
208 }
209
210 //-------------------------------------------------------
211 // Construct the ibz_symmetry_ops according to ReadMode.
212 ibz_symmetry_ops read_ibz_symmetry_ops(auto const &filename, ReadMode mode) {
213
214 auto root = h5::proxy{filename, 'r'};
215
216 auto rot_mats = read_rotation_matrices(filename, mode);
217 auto atomic_shells = read_atomic_shells(filename, mode);
218
219 auto g_symm = (mode == ReadMode::Correlated) ? root["dft_symmcorr_input"] : root["dft_symmpar_input"];
220 auto symm_ops = ibz_symmetry_ops{};
221
222 // read the symmetrization matrices (Q) for each symmetry operation S in the space group G.
223 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)); })
224 | tl::to<std::vector>();
225
226 // read the permutation table which contains: for each symmetry op S in space group G,
227 // the permutations of all atoms in the crystal structure under S.
228 // dim(perm_table_all) = [number of sym ops][number of atoms in crystal]
229 auto perm_table_all =
230 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>();
231
232 // The permutation table is written for all atoms in the crystal. We must filter to obtain only the correlated atoms.
233 auto corr_atom_to_alpha = std::unordered_map<long, long>{};
234 for (auto iatom : range(atomic_shells.size())) corr_atom_to_alpha[atomic_shells[iatom].dft_idx] = iatom;
235
236 // The filtered permutation table (perm_table_corr): for each sym S, filter only the correlated atoms
237 // and map their indices from dft_idx correlated idx.
238 // dim(perm_table_correlated) = [number of sym ops][number of correlated atoms in crystal]
239 auto perm_table_correlated = perm_table_all | stdv::transform([&](auto const &sym) {
240 return atomic_shells
241 | stdv::transform([&](auto corr_atom) { return corr_atom_to_alpha[sym[corr_atom.dft_idx - 1]]; })
242 | tl::to<std::vector>();
243 })
244 | tl::to<std::vector>();
245
246 // Merge the rotation matrices R into the symmetrization matrices (Qs).
247 for (auto const &[iq, perm] : enumerate(perm_table_correlated)) {
248 for (auto const &[a, b] : enumerate(perm)) { symm_ops_mats[iq][a] = dagger(rot_mats[b]) * symm_ops_mats[iq][a] * rot_mats[a]; }
249 }
250
251 // Does this op have time inversion symmetry
252 auto time_inv_op = to_vector<long>(sort_keys_as_int(g_symm["time_inv"]));
253 // save the symmetry ops in to the ibz_symmetrizer
254 symm_ops.ops = range(perm_table_correlated.size()) | stdv::transform([symm_ops_mats, perm_table_correlated, time_inv_op](auto const &isym) {
255 return ibz_symmetry_ops::op{symm_ops_mats[isym], perm_table_correlated[isym], time_inv_op[isym]};
256 })
257 | tl::to<std::vector>();
258
259 return symm_ops;
260 };
261
262 std::pair<double, one_body_elements_on_grid> read_obe_from_dft_converter_hdf5(std::string const &filename, double threshold,
263 bool diagonalize_hloc) {
264 auto g_dft = h5::proxy{filename, 'r'}["dft_input"];
265
266 auto target_density = as<double>(g_dft["density_required"]);
267
268 //TODO: FIXME! hdf5 read to strict on long
269 //auto charge_below = (as<std::string>(g_dft["dft_code"]) != "w90" && as<std::string>(g_dft["dft_code"]) != "hk") ?
270 auto charge_below = (as<std::string>(g_dft["dft_code"]) != "w90") ? as<double>(g_dft["charge_below"]) : as<long>(g_dft["charge_below"]);
271 target_density -= charge_below;
272
273 // set up spin_type
274 auto spin_kind = read_spin_kind(filename);
275
276 // set up atomic shells
277 auto atomic_shells = read_atomic_shells(filename, ReadMode::Correlated);
278
279 // disperion and k weights
280 auto [H_k, n_bands_per_k, k_weights] = read_bands_and_weights(filename, ReadMode::Correlated);
281
282 // rotation matrices in csc mode
283 auto rot_mats = read_rotation_matrices(filename, ReadMode::Correlated);
284
285 // read and rotate projectors
286 auto atom_decomp = atomic_shells | stdv::transform([](auto &x) { return x.dim; }) | tl::to<std::vector<long>>();
287 auto P_k = load_rotate_and_format_projectors(filename, ReadMode::Correlated, rot_mats, atom_decomp);
288
289 // read symmetry ops
290 //FIXME: auto symm_ops = (long(g_dft["symm_op"]) == 0) ? ibz_symmetry_ops{} : read_ibz(root, atomic_shells, Rmats);
291 auto symm_ops = (long(g_dft["symm_op"]) == 0) ? std::optional<ibz_symmetry_ops>{} :
292 std::optional<ibz_symmetry_ops>(read_ibz_symmetry_ops(filename, ReadMode::Correlated));
293
294 auto n_k = H_k.extent(0);
295 auto H_k_is_diagonal = true;
296 for (auto ik : range(n_k)) {
297 if (!nda::is_diagonal(nda::matrix<dcomplex>{H_k(ik, 0, r_all, r_all)})) {
298 H_k_is_diagonal = false;
299 break;
300 }
301 }
302 auto eps_k = band_dispersion{
303 .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};
304 auto proj = downfolding_projector{.spin_kind = spin_kind, .P_k = std::move(P_k), .n_bands_per_k = n_bands_per_k};
305
306 // build a first version without symmetries
307 auto C_space_no_symm = local_space{spin_kind, atomic_shells, {}, {}, {}};
308 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)};
309
310 // TODO: verbosity should report the symmetries found (or at least the result of the symmetries found).
311 // auto out = ostream_with_verbosity(std::cout, verbosity);
312 // FIXME: verbosity reporting of local H0 which is used to analyze the symmetries
313 auto Hloc0 = obe.C_space.atomic_view(impurity_levels(obe));
314 auto [decomposition, U_rotations] = discover_symmetries(Hloc0, atomic_shells, threshold, diagonalize_hloc);
315 // FIXME: printing of the local symmetries discovered: eigenvalues (and eigenvectors of Hloc0)
316 // Should we print the rotation matrices as well?
317 // This is a lot of matrices that will be printed...is there a more compact representation?
318 // FIXME : NORMALLY the rotate_local_basis shuold also rotate the local_basis !!!
319 // FIXME !! ---> @ HL : the question is multiply rotation_from_dft_basis LEFT OR RIGHT ?
320 // update the orbital set with the decomposition
321
322 // FIXME: h5_proxy bug?
323 // if (!g_dft.has_key("dft_code")) {
324 // throw std::runtime_error{fmt::format(
325 // "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.",
326 // filename)};
327 // }
328
329 obe.C_space = local_space{spin_kind, atomic_shells, decomposition, U_rotations,
330 read_spherical_to_dft_basis(as<std::string>(g_dft["dft_code"]), atomic_shells)};
331 // rotate to the local basis.
332 // FIXME: The dft_tools converters do not write the spherical_to_dft rotation for all cases.
333 // Solution: hard-code the rotations for each dft_code (read from hdf5) and save in the local space.
334 // The only issue is dft_code breaks backward compatibility with older hdf5 files.
335 // Therefore the user can either pass at this stage this rotation or in the function that constructs the
336 // slate hamiltonian.
337 auto obe_final = rotate_local_basis(U_rotations, std::move(obe));
338 return {target_density, std::move(obe_final)};
339 }
340
341 //-------------------------------------------------------
342 // Prepare one-body elements for a DMFT calculation.
343 std::pair<double, one_body_elements_on_grid> one_body_elements_from_dft_converter(std::string const &filename, double threshold,
344 bool diagonalize_hloc) {
345 mpi::communicator comm = {};
346 int root = 0;
347 double target_density = 0;
349
350 if (comm.rank() == root) { std::tie(target_density, obe_final) = read_obe_from_dft_converter_hdf5(filename, threshold, diagonalize_hloc); }
351
352 mpi::broadcast(target_density, comm, root);
353 mpi::broadcast(obe_final, comm, root);
354
355 return {target_density, std::move(obe_final)};
356 }
357
359 //check for group and throw error
360 auto h5root = h5::proxy{filename, 'r'};
361 if (!h5root.has_group("dft_parproj_input")) {
362 throw std::runtime_error{fmt::format("The hdf5 file {} does not contain the group dft_parproj_input", filename)};
363 }
364
365 // all the atomic shells
366 auto atomic_shells = read_atomic_shells(filename, ReadMode::ThetaProjectors);
367
368 // The decomposition and rotations must be embedded from the C spcae to the W space
369 auto new_block_decomposition = detail::inject_to_new_space(obe.C_space.atoms_block_decomposition(), obe.C_space.atomic_shells(), atomic_shells);
370
371 // The local space expanded from C to W
372 auto W_space = local_space{obe.C_space.spin_kind(), atomic_shells, new_block_decomposition, {}, {}};
373
374 // rotation matrices using ThetaProjector mode
375 auto rot_mats = read_rotation_matrices(filename, ReadMode::ThetaProjectors);
376
377 // read and rotate projectors
378 auto atom_decomp = W_space.atomic_decomposition() | tl::to<std::vector<long>>();
379 auto P_k = load_rotate_and_format_projectors(filename, ReadMode::ThetaProjectors, rot_mats, atom_decomp);
380 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};
381
382 // create a new IBZ symmetrizer that spans all atoms instead of just the correlated atoms
383 auto symm_ops = (obe.ibz_symm_ops) ? std::optional<ibz_symmetry_ops>(read_ibz_symmetry_ops(filename, ReadMode::ThetaProjectors)) :
384 std::optional<ibz_symmetry_ops>{};
385 return one_body_elements_on_grid{.H = obe.H, .C_space = W_space, .P = theta_proj, .ibz_symm_ops = symm_ops};
386 }
387
388 //-------------------------------------------------------
389 // Prepare one-body elements with the Θ projectors.
391
392 mpi::communicator comm = {};
393 int root = 0;
395
396 if (comm.rank() == root) { obe_final = read_theta_projectors_for_obe(filename, obe); }
397
398 mpi::broadcast(obe_final, comm, root);
399 return obe_final;
400 }
401
403 // check for group and throw error
404 auto h5root = h5::proxy{filename, 'r'};
405 if (!h5root.has_group("dft_bands_input")) {
406 throw std::runtime_error{fmt::format("The hdf5 file {} does not contain the group dft_bands_input", filename)};
407 }
408
409 // disperion and k weights
410 auto [H_k, n_bands_per_k, k_weights] = read_bands_and_weights(filename, ReadMode::Bands);
411
412 // rotation matrices in csc mode
413 auto rot_mats = read_rotation_matrices(filename, ReadMode::Correlated);
414
415 // read and rotate projectors
416 auto atom_decomp = obe.C_space.atomic_decomposition() | tl::to<std::vector<long>>();
417 auto P_k = load_rotate_and_format_projectors(filename, ReadMode::Bands, rot_mats, atom_decomp);
418
419 // construct one-body elements (ibz_symm_ops are needed so we drop)
420 auto eps_k = band_dispersion{
421 .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};
422 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};
423 auto obe1 = one_body_elements_on_grid{.H = eps_k, .C_space = obe.C_space, .P = proj, .ibz_symm_ops = {}};
424 // rotate to the local basis that the self-energies will be defined in.
425 return rotate_local_basis(obe.C_space.rotation_from_dft_to_local_basis(), std::move(obe1));
426 }
427
428 //-------------------------------------------------------
429 // Prepare one-body elements along high-symmetry k-path.
431
432 mpi::communicator comm;
433 int root = 0;
435
436 if (comm.rank() == root) { obe_final = read_data_on_high_symm_path_for_obe(filename, obe); }
437
438 mpi::broadcast(obe_final, comm, root);
439 return obe_final;
440 }
441
442 //-------------------------------------------------------
443 one_body_elements_gw make_one_body_elements_gw(std::string const &filename, double threshold, bool diagonalize_hloc) {
444
445 mpi::communicator comm;
446 int root = 0;
448
449 if (comm.rank() == root) {
450
451 auto [target_density, obe] = read_obe_from_dft_converter_hdf5(filename, threshold, diagonalize_hloc);
452
453 // read the band window
454 auto band_window = read_band_window(filename);
455 auto kpts = read_kpts(filename);
456
457 // build the extended projector
458 auto proj = downfolding_projector_ext{{obe.P}, std::move(band_window), std::move(kpts)};
459
460 obe_gw = one_body_elements_gw{.C_space = obe.C_space, .P = proj};
461 }
462
463 mpi::broadcast(obe_gw, comm, root);
464 return obe_gw;
465 }
466} // namespace triqs::modest
Describe the atomic orbitals within downfolded space.
spin_kind_e spin_kind() const
Spin kind of index.
block2_gf< Mesh > atomic_view(block2_gf< Mesh > const &G_C)
Views a 2-dim block GF according to the atomic decomposition.
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.
std::vector< atomic_orbs > const & atomic_shells() const
List of all atomic shells spanning the space.
std::vector< long > atomic_decomposition() const
Dimensions of each atomic shell, in order.
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_gw make_one_body_elements_gw(std::string const &filename, double threshold, bool diagonalize_hloc)
Create a one-body elements for GW calculations with CoQui.
Definition loaders.cpp:443
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.
Definition loaders.cpp:430
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.
Definition loaders.cpp:343
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.
Definition loaders.cpp:390
nda::matrix< T > make_matrix_from_permutation(std::vector< int > const &p)
Definition nda_supp.hpp:19
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
DFTCode dft_code_to_enum(std::string const &code)
Definition utils.hpp:22
nda::matrix< dcomplex > get_spherical_to_dft_rotation(DFTCode code, long l)
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)
Definition loaders.cpp:111
one_body_elements_on_grid read_theta_projectors_for_obe(const std::string &filename, const one_body_elements_on_grid &obe)
Definition loaders.cpp:358
std::tuple< nda::array< dcomplex, 4 >, nda::matrix< long >, nda::array< double, 1 > > read_bands_and_weights(std::string filename, ReadMode mode)
Definition loaders.cpp:152
nda::array< nda::matrix< dcomplex >, 1 > read_spherical_to_dft_basis(std::string dft, std::vector< atomic_orbs > const &atomic_shells)
Definition loaders.cpp:202
ibz_symmetry_ops read_ibz_symmetry_ops(auto const &filename, ReadMode mode)
Definition loaders.cpp:212
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)
Definition loaders.cpp:262
nda::array< long, 3 > read_band_window(std::string const &filename)
Definition loaders.cpp:166
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)
Definition loaders.cpp:402
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.
Definition loaders.cpp:44
std::vector< cmat_t > read_rotation_matrices(std::string const &filename, ReadMode mode)
Definition loaders.cpp:81
spin_kind_e read_spin_kind(auto const &filename)
Definition loaders.cpp:182
nda::array< double, 2 > read_kpts(std::string const &filename)
Definition loaders.cpp:174
std::vector< atomic_orbs > read_atomic_shells(auto const &filename, ReadMode mode)
Definition loaders.cpp:190
nda::matrix< dcomplex > cmat_t
Definition defs.hpp:31
static constexpr auto r_all
Definition defs.hpp:33
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
auto to_vector(auto &&gen)
Definition to_vector.hpp:11
Info on an atomic shell.
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 .
The projector that downfolds the energy bands onto a set of localized atomic-like orbitals.
Irreducible Brillouin Zone (IBZ) symmetry operations to symmetrize observables over the entire Brillo...
A one-body elements struct for GW (CoQui) calculations.
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.
band_dispersion H
Band dispersion.