TRIQS/triqs_modest 3.3.0
Modular Electronic Structure Toolkit
Loading...
Searching...
No Matches
embedding.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 "embedding.hpp"
7#include "utils/gf_supp.hpp"
8#include "utils/defs.hpp"
11#include <ranges>
12#include <set>
13//#include <fmt/ranges.h>
14//#include <sstream>
15
16namespace triqs::modest {
17
18 embedding::embedding(std::vector<long> sigma_embed_decomposition, std::vector<std::vector<long>> imp_decompositions, nda::array<imp_block_t, 2> psi,
19 std::vector<std::string> sigma_names)
20 : sigma_embed_decomp{std::move(sigma_embed_decomposition)},
21 imp_decomps{std::move(imp_decompositions)},
22 _sigma_names{std::move(sigma_names)},
23 psi{std::move(psi)} {
24
25 alpha_names = range(n_alpha()) | //
26 stdv::transform([](auto i) { return std::to_string(i); }) | tl::to<std::vector>();
27
28 // Compute reverse_psi
29 reverse_psi = imp_decomps | stdv::transform([&](auto &v) { return nda::array<std::vector<std::array<long, 2>>, 2>(v.size(), n_sigma()); })
30 | tl::to<std::vector>();
31
32 for (auto [alpha, sigma] : this->psi.indices()) { // beware the psi (argument) has been moved. use 2 names ?
33 auto const &y = this->psi(alpha, sigma);
34 if (y.imp_idx == -1) continue;
35 reverse_psi[y.imp_idx](y.gamma, y.tau).push_back(std::array{alpha, sigma});
36 }
37
38 // FIXME : MAKE ALL NECESSARY CHECKS.... since
39 }
40
41 embedding embedding_builder(std::vector<std::string> const &spin_names, nda::array<std::vector<long>, 2> const &block_decomposition,
42 std::vector<long> const &atom_to_imp) {
43
44 long n_alpha = stdr::fold_left(block_decomposition(r_all, 0) | stdv::transform([](auto const &x) { return long(x.size()); }), 0, std::plus<>());
45 long n_sigma = spin_names.size();
46
47 auto embed_bl_sizes = std::vector<long>{};
48 auto imp_decompositions = std::vector<std::vector<long>>{};
49 auto psi = nda::array<embedding::imp_block_t, 2>(n_alpha, n_sigma);
50
51 std::set<long> seen_impurities;
52
53 auto n_atoms = block_decomposition.extent(0);
54 for (auto atom : range(n_atoms)) {
55 for (auto &&[idx, bl_size] : enumerate(block_decomposition(atom, 0))) {
56 for (auto sigma : range(n_sigma)) { psi(embed_bl_sizes.size(), sigma) = {atom_to_imp[atom], idx, sigma}; }
57 embed_bl_sizes.emplace_back(bl_size);
58 }
59 auto build_impurity = !seen_impurities.contains(atom_to_imp[atom]);
60 if (build_impurity) {
61 imp_decompositions.push_back(std::move(block_decomposition(atom, 0)));
62 seen_impurities.insert(atom_to_imp[atom]);
63 }
64 }
65 return embedding{std::move(embed_bl_sizes), std::move(imp_decompositions), std::move(psi), std::move(spin_names)};
66 }
67
68 embedding embedding_builder(std::vector<std::string> const &spin_names, std::vector<std::vector<long>> const &block_decomposition,
69 std::vector<long> const &atom_to_imp) {
70 auto n_decomps = block_decomposition.size();
71 auto n_sigma = spin_names.size();
72 auto block_decomp_mat = nda::array<std::vector<long>, 2>(n_decomps, n_sigma);
73 for (auto d : range(n_decomps))
74 for (auto s : range(n_sigma)) block_decomp_mat(d, s) = block_decomposition[d];
75 return embedding_builder(spin_names, block_decomp_mat, atom_to_imp);
76 }
77
78 // -------------------------------------------------------------------------------------------
79 embedding make_embedding_with_equivalences(local_space const &C_space, bool use_atom_decomp) {
80 std::unordered_map<long, long> atom_to_cls, cls_to_imp;
81 long imp_idx = 0;
82 for (auto const &[ish, sh] : enumerate(C_space.atomic_shells())) {
83 atom_to_cls[ish] = sh.cls_idx;
84 if (not cls_to_imp.contains(sh.cls_idx)) cls_to_imp[sh.cls_idx] = imp_idx++;
85 }
86 auto atom_to_imp_idx = range(C_space.atomic_shells().size()) | stdv::transform([&](auto const &atom) { return cls_to_imp[atom_to_cls[atom]]; })
87 | tl::to<std::vector>();
88
89 nda::array<std::vector<long>, 2> decomp(C_space.n_atoms(), C_space.n_sigma());
90 if (use_atom_decomp) {
91 auto atom_decomp = C_space.atomic_decomposition();
92 for (auto &&[iatom, atom] : enumerate(atom_decomp)) {
93 for (auto sigma : range(C_space.n_sigma())) { decomp(atom, sigma).emplace_back(atom); }
94 }
95 } else {
96 decomp = C_space.atoms_block_decomposition();
97 }
98 return embedding_builder(C_space.sigma_names(), decomp, atom_to_imp_idx);
99 };
100
101 // -------------------------------------------------------------------------------------------
102 embedding make_embedding_with_no_equivalences(local_space const &C_space, bool use_atom_decomp) {
103 nda::array<std::vector<long>, 2> decomp(C_space.n_atoms(), C_space.n_sigma());
104 if (use_atom_decomp) {
105 auto atom_decomp = C_space.atomic_decomposition();
106 for (auto &&[iatom, atom] : enumerate(atom_decomp)) {
107 for (auto sigma : range(C_space.n_sigma())) { decomp(atom, sigma).emplace_back(atom); }
108 }
109 } else {
110 decomp = C_space.atoms_block_decomposition();
111 }
112
113 auto atom_to_imp_idx = range(C_space.atomic_shells().size()) | tl::to<std::vector>();
114 return embedding_builder(C_space.sigma_names(), decomp, atom_to_imp_idx);
115 }
116
117 // -------------------------------------------------------------------------------------------
118 embedding make_embedding(local_space const &C_space, bool use_atom_equivalences, bool use_atom_decomp) {
119 return (use_atom_equivalences) ? make_embedding_with_equivalences(C_space, use_atom_decomp) :
120 make_embedding_with_no_equivalences(C_space, use_atom_decomp);
121 }
122
123 // ------------------------------ PRINTING -------------------------------------------------------------
124
125 auto format_as(embedding::imp_block_t const &p) {
126 //return fmt::format("({},{},{})", p.n_imp, p.gamma, p.tau);
127 return fmt::format("(imp_idx = {}, γ = {}, τ = {})", p.imp_idx, p.gamma, p.tau);
128 }
129
130 // -------------------------------------------------------------------------------------------------------
131
132 std::string embedding::description(bool verbosity) const {
133 auto sigma_embed_shape = this->sigma_embed_block_shape();
134 auto impurities_shape_list = this->imp_block_shape();
135
136 std::ostringstream out;
137 auto out1 = indented_ostream(out, 2); // same stream, but shifted by 2 spaces
138 auto out2 = indented_ostream(out, 4);
139 auto out3 = indented_ostream(out, 6);
140
141 if (!verbosity) {
142 out << "Embedding: ";
143 out << fmt::format("{} impurities\n", this->n_impurities());
144 out1 << "Σ_embed block decomposition:\n";
145 auto pr_vec = [](auto const &V) {
146 return fmt::format("{}\n", fmt::join(V | stdv::transform([](auto x) { return fmt::format("{:>3}", x); }), " "));
147 };
148 out2 << "dim_α: " << pr_vec(this->sigma_embed_decomp);
149 out2 << " α: " << pr_vec(range(this->sigma_embed_decomp.size()));
150 out1 << "\nImpurities\n";
151 out2 << "Block dimensions, dim_γ for all γ:\n";
152 for (auto &&[n, dec] : enumerate(this->imp_decomps)) {
153 auto head = fmt::format("[n_imp = {}]", n);
154 out3 << fmt::format("{} dim_γ = {}", head, pr_vec(dec));
155 out3 << fmt::format("{:>{}} γ = {}", " ", head.size(), pr_vec(range(dec.size())));
156 }
157 return out.str();
158 }
159
160 out << "Embedding:\n";
161 out1 << fmt::format("Spin index (σ/τ) names: {}\n\n", this->sigma_names());
162 out1 << "Σ_embed block decomposition:\n";
163 auto pr_vec = [](auto const &V) {
164 return fmt::format("{}\n", fmt::join(V | stdv::transform([](auto x) { return fmt::format("{:>3}", x); }), " "));
165 };
166 out2 << "dim_α: " << pr_vec(this->sigma_embed_decomp);
167 out2 << " α: " << pr_vec(range(this->sigma_embed_decomp.size()));
168 //out << fmt::format(" {}\n", enumerate(E.sigma_embed_decomp));
169 out1 << "\nImpurities\n";
170 out2 << "Block dimensions, dim_γ for all γ:\n";
171 for (auto &&[n, dec] : enumerate(this->imp_decomps)) {
172 auto head = fmt::format("[n_imp = {}]", n);
173 out3 << fmt::format("{} dim_γ = {}", head, pr_vec(dec));
174 out3 << fmt::format("{:>{}} γ = {}", " ", head.size(), pr_vec(range(dec.size())));
175 }
176 out2 << "Gf Block structures for solvers as names, [dim]:\n";
177 for (auto &&[n, ish] : enumerate(impurities_shape_list)) {
178 auto formatted_vec = ish | stdv::transform([](auto &&p) { return fmt::format("{} [{}]", p.first, p.second); }) | tl::to<std::vector>();
179 out3 << fmt::format("[imp_idx = {}] {}\n", n, fmt::join(formatted_vec, ", "));
180 }
181 out1 << "\nMapping ψ(α,σ) = (imp_idx, γ, τ) \n";
182 //out2 << fmt::format("{}", E.psi);
183 auto row_labels = range(this->n_alpha()) | stdv::transform([](auto x) { return fmt::format("α = {}", x); }) | tl::to<std::vector>();
184 auto col_labels = range(this->n_sigma()) | stdv::transform([&](auto i) { return fmt::format("σ = {} / {}", i, this->sigma_names()[i]); })
185 | tl::to<std::vector>();
186 nda::format_as_table(out3, this->psi, row_labels, col_labels);
187
188 return out.str();
189 }
190
191 std::ostream &operator<<(std::ostream &out, embedding const &E) {
192 out << E.description(false);
193 return out;
194 }
195
196 //-----------------------------------------------------------------
197
199 auto res = nda::zeros<long>(n_alpha(), n_sigma());
200 for (long alpha : range(n_alpha())) res(alpha, r_all) = sigma_embed_decomp[alpha];
201 return {.names = {alpha_names, _sigma_names}, .dims = std::move(res)};
202 }
203
204 //-----------------------------------------------------------------
205
206 std::vector<gf_struct_t> embedding::imp_block_shape() const {
207 auto l = [this](std::vector<long> const &decomp) -> gf_struct_t {
208 gf_struct_t res;
209 for (auto sigma : range(n_sigma())) {
210 for (auto const &[idx, bl_size] : enumerate(decomp)) res.emplace_back(fmt::format("{}_{}", _sigma_names[sigma], idx), bl_size);
211 }
212 return res;
213 };
214 return imp_decomps | stdv::transform(l) | tl::to<std::vector>();
215 }
216
217 //-----------------------------------------------------------------
218 embedding embedding::flip_spin(long alpha) const {
219 if (n_sigma() != 2) throw std::runtime_error(fmt::format("Can not flip spin when {} != 2", n_sigma()));
220 if (alpha >= n_alpha()) throw std::runtime_error(fmt::format("Out of bounds {} >= {}", alpha, n_alpha()));
221 auto new_psi = this->psi;
222 for (auto sigma : range(n_sigma())) new_psi(alpha, sigma).tau = 1 - new_psi(alpha, sigma).tau;
223 return {this->sigma_embed_decomp, this->imp_decomps, new_psi, this->_sigma_names};
224 }
225
226 //-----------------------------------------------------------------
227 embedding embedding::flip_spin(std::vector<long> alphas) const {
228 auto res = *this;
229 for (auto alpha : alphas) { res = res.flip_spin(alpha); }
230 return res;
231 }
232
233 //-----------------------------------------------------------------
234
235 embedding embedding::drop(long imp_idx) const {
236 auto new_imp_decomps = this->imp_decomps;
237 auto new_psi = this->psi;
238 new_imp_decomps.erase(begin(new_imp_decomps) + imp_idx);
239 new_psi = nda::map([&](imp_block_t const &b) -> imp_block_t {
240 if (b.imp_idx < imp_idx) return {b.imp_idx, b.gamma, b.tau};
241 if (b.imp_idx > imp_idx) return {b.imp_idx - 1, b.gamma, b.tau};
242 return {-1, 0, 0}; // imp_idx == b.n_imp : we connect to nothing now
243 })(new_psi);
244 return {this->sigma_embed_decomp, new_imp_decomps, new_psi, this->_sigma_names};
245 }
246
247 //-----------------------------------------------------------------
248 // HL: re-implementation of replace. Please review.
249 embedding embedding::replace(long imp_idx_to_remove, long imp_idx_to_replace_with) const {
250 auto new_psi = this->psi;
251 if (imp_block_shape()[imp_idx_to_remove] != imp_block_shape()[imp_idx_to_replace_with])
252 throw std::runtime_error(fmt::format("The number of blocks that imp_to_remove= {} and imp_to_replace_with={} connect to do not match!",
253 imp_idx_to_remove, imp_idx_to_replace_with));
254 new_psi = nda::map([&](imp_block_t const &b) -> imp_block_t {
255 if (b.imp_idx == imp_idx_to_remove) return {imp_idx_to_replace_with, b.gamma, b.tau};
256 return b;
257 })(new_psi);
258 return embedding(this->sigma_embed_decomp, this->imp_decomps, new_psi, this->_sigma_names).drop(imp_idx_to_remove);
259 }
260
261 //-----------------------------------------------------------------
262
263 embedding embedding::split(long imp_idx, std::function<bool(long)> p) const {
264 // auto res = *this; // copy. We will modify the impurities_gf_struct and the table
265 auto new_psi = this->psi;
266 auto new_imp_decomps = this->imp_decomps;
267 auto const &igs = new_imp_decomps[imp_idx];
268 auto indices = nda::range(long(igs.size())) | tl::to<std::vector>(); // {0,1,2, ... n_gamma}
269
270 // separate the block indices according to p. We put the indices in regard to the blocks and partition them
271 auto mid = std::stable_partition(begin(indices), end(indices), p);
272
273 // make 2 new gf_struct from the indices partition
274 auto get_igs = [&](int i) { return igs[i]; };
275 auto stru1 = stdr::subrange{begin(indices), mid} | stdv::transform(get_igs) | tl::to<std::vector>();
276 auto stru2 = stdr::subrange{mid, end(indices)} | stdv::transform(get_igs) | tl::to<std::vector>();
277 long L1 = long(stru1.size());
278
279 // Store the new gf_struct in result at the position of the old impurity model
280 new_imp_decomps[imp_idx] = std::move(stru1);
281 new_imp_decomps.insert(begin(new_imp_decomps) + imp_idx + 1, std::move(stru2));
282
283 // compute the inverse table of indices
284 auto indices_inv = indices;
285 for (auto i : range(indices.size())) indices_inv[indices[i]] = i;
286
287 new_psi = nda::map([&](imp_block_t const &b) -> imp_block_t {
288 if (b.imp_idx < imp_idx) return b;
289 if (b.imp_idx > imp_idx) return {b.imp_idx + 1, b.gamma, b.tau};
290 long new_gamma = indices_inv[b.gamma];
291 return (new_gamma < L1 ? imp_block_t{b.imp_idx, new_gamma, b.tau} : imp_block_t{b.imp_idx + 1, new_gamma - L1, b.tau});
292 })(new_psi);
293 return {this->sigma_embed_decomp, new_imp_decomps, new_psi, this->_sigma_names};
294 }
295
296 // ----------------------------------------------------------------------
297
298 embedding embedding::split(long imp_idx, std::vector<long> const &block_list) const {
299 if (not stdr::all_of(block_list, [&](auto i) { return (i >= 0) and (i < n_gamma(imp_idx)); }))
300 throw std::runtime_error(fmt::format("[embedding::split] The list of block indices {} is incorrect. Indices i should all be 0<= i < N_γ = {}",
301 block_list, n_gamma(imp_idx)));
302 return split(imp_idx, [&](long idx) { return stdr::find(block_list, idx) != block_list.end(); });
303 }
304
305 // ----------------------------------------------------------------------
306
307 block2_matrix_t embedding::embed(std::vector<block_matrix_t> const &Sigma_imp_static_vec) const {
308 auto Sigma_static_embed = nda::array<nda::matrix<dcomplex>, 2>(n_alpha(), n_sigma());
309 for (auto &&[alpha, sigma] : psi.indices()) {
310 auto bl_size = sigma_embed_decomp[alpha];
311 Sigma_static_embed(alpha, sigma) = nda::zeros<dcomplex>(bl_size, bl_size);
312 }
313 for (auto &&[S, m] : zip(Sigma_static_embed, psi)) {
314 if (m.imp_idx == -1) continue;
315 S = Sigma_imp_static_vec[m.imp_idx][m.gamma + n_gamma(m.imp_idx) * m.tau];
316 }
317 return Sigma_static_embed;
318 }
319
320 // ----------------------------------------------------------------------
321
322 std::vector<block_matrix_t> embedding::extract(block2_matrix_t const &matrix_C) const {
323
324 auto imp_gf_stru_list = imp_block_shape();
325
326 auto matrix_E = nda::matrix<nda::matrix<dcomplex>>(n_alpha(), n_sigma());
327 for (auto [alpha, r_alpha] : enumerated_sub_slices(sigma_embed_decomp)) {
328 for (auto sigma : range(n_sigma())) { matrix_E(alpha, sigma) = matrix_C(0, sigma)(r_alpha, r_alpha); }
329 }
330
331 auto extract_one_imp = [&](long n_imp) {
332 auto matrix_imp = std::vector<nda::matrix<dcomplex>>{};
333 for (auto [bl, bl_size] : imp_gf_stru_list[n_imp]) { matrix_imp.emplace_back(bl_size, bl_size); }
334 auto const &rpsi = reverse_psi[n_imp];
335 for (auto [gamma, tau] : rpsi.indices()) {
336 auto [alpha, sigma] = rpsi(gamma, tau)[0];
337 matrix_imp[gamma + n_gamma(n_imp) * tau] = matrix_E(alpha, sigma);
338 }
339 return matrix_imp;
340 };
341
342 return range(n_impurities()) | stdv::transform(extract_one_imp) | tl::to<std::vector>();
343 }
344
345 // ----------------------------------------------------------------------
346 std::vector<nda::array<dcomplex, 4>> embedding::extract_tensor(nda::array<dcomplex, 4> const &U_tensor) const {
347
348 auto imp_gf_stru_list = imp_block_shape();
349
350 auto tensor_E = std::vector<nda::array<dcomplex, 4>>(n_alpha());
351 for (auto [alpha, r_alpha] : enumerated_sub_slices(sigma_embed_decomp)) { tensor_E[alpha] = U_tensor(r_alpha, r_alpha, r_alpha, r_alpha); }
352
353 auto extract_one_imp = [&](long n_imp) {
354 auto bl_size = imp_decomposition(n_imp)[0];
355 auto tensor_imp = nda::zeros<dcomplex>(bl_size, bl_size, bl_size, bl_size);
356 auto alpha = reverse_psi[n_imp](0, 0)[0][0];
357 return tensor_E[alpha];
358 };
359 return range(n_impurities()) | stdv::transform(extract_one_imp) | tl::to<std::vector>();
360 }
361
362 // --------------------------------------------------------------------------------------------
363 nda::array<dcomplex, 4> embedding::embed_tensor(std::vector<nda::array<dcomplex, 4>> const &U_tensor_vec) const {
364 auto Utensor_E = std::vector<nda::array<dcomplex, 4>>(n_alpha());
365
366 for (auto alpha : range(n_alpha())) {
367 auto bl_size = sigma_embed_decomp[alpha];
368 Utensor_E[alpha] = nda::zeros<dcomplex>(bl_size, bl_size, bl_size, bl_size);
369 }
370
371 for (auto &&[U, a] : zip(Utensor_E, range(n_alpha()))) {
372 if (psi(a, 0).imp_idx == -1) continue;
373 U = U_tensor_vec[psi(a, 0).imp_idx];
374 }
375
376 auto dim_C = stdr::fold_left(sigma_embed_decomp, 0, std::plus<>());
377 auto U_tensor_C = nda::array<dcomplex, 4>(dim_C, dim_C, dim_C, dim_C);
378 for (auto &&[index, sli] : enumerated_sub_slices(sigma_embed_decomp)) { U_tensor_C(sli, sli, sli, sli) = Utensor_E[index]; }
379 return U_tensor_C;
380 }
381 // --------------------------------------------------------------------------------------------
382
383 std::vector<std::vector<nda::array<dcomplex, 3>>> embedding::extract_1p(nda::array<dcomplex, 4> const &g_loc) const {
384
385 auto imp_gf_stru_list = imp_block_shape();
386 auto n_w = g_loc.extent(0);
387
388 auto gloc_E = nda::array<nda::array<dcomplex, 3>, 2>(n_alpha(), n_sigma());
389 for (auto [alpha, r_alpha] : enumerated_sub_slices(sigma_embed_decomp)) {
390 for (auto sigma : range(n_sigma())) { gloc_E(alpha, sigma) = g_loc(r_all, sigma, r_alpha, r_alpha); }
391 }
392 auto extract_one_imp = [&](long n_imp) {
393 auto g_imp = std::vector<nda::array<dcomplex, 3>>{};
394 for (auto [bl, bl_size] : imp_gf_stru_list[n_imp]) { g_imp.emplace_back(n_w, bl_size, bl_size); }
395 auto const &rpsi = reverse_psi[n_imp];
396 for (auto [gamma, tau] : rpsi.indices()) {
397 auto [alpha, sigma] = rpsi(gamma, tau)[0];
398 g_imp[gamma + n_gamma(n_imp) * tau] = gloc_E(alpha, sigma);
399 }
400 return g_imp;
401 };
402
403 return range(n_impurities()) | stdv::transform(extract_one_imp) | tl::to<std::vector>();
404 }
405 // --------------------------------------------------------------------------------------------
406
407 std::vector<nda::array<dcomplex, 3>> embedding::embed_1p(std::vector<std::vector<nda::array<dcomplex, 3>>> const &Sigma_imp_vec) const {
408
409 auto Sigma_embed = nda::array<nda::array<dcomplex, 3>, 2>(n_alpha(), n_sigma());
410 auto n_w = Sigma_imp_vec[0][0].extent(0);
411
412 for (auto &&[alpha, sigma] : psi.indices()) {
413 auto bl_size = sigma_embed_decomp[alpha];
414 Sigma_embed(alpha, sigma) = nda::zeros<dcomplex>(n_w, bl_size, bl_size);
415 }
416
417 for (auto &&[S, m] : zip(Sigma_embed, psi)) {
418 if (m.imp_idx == -1) continue;
419 S = Sigma_imp_vec[m.imp_idx][m.gamma + n_gamma(m.imp_idx) * m.tau];
420 }
421
422 auto dim_C = stdr::fold_left(sigma_embed_decomp, 0, std::plus<>());
423 auto Sigma_C =
424 range(n_sigma()) | stdv::transform([&](auto const &sig) { return nda::array<dcomplex, 3>(n_w, dim_C, dim_C); }) | tl::to<std::vector>();
425 for (auto sigma : range(n_sigma())) {
426 for (auto &&[index, sli] : enumerated_sub_slices(sigma_embed_decomp)) { Sigma_C[sigma](r_all, sli, sli) = Sigma_embed(index, sigma); }
427 }
428 return Sigma_C;
429 }
430
431 // --------------------------------------------------------------------------------------------
432
433 //FIXME : protect this function as it will only work with a Pi_embed_decomp
434 std::vector<nda::array<dcomplex, 5>> embedding::extract_2p(nda::array<dcomplex, 5> const &pi_loc) const {
435
436 auto Pi_E = std::vector<nda::array<dcomplex, 5>>{};
437 for (auto [alpha, r_alpha] : enumerated_sub_slices(sigma_embed_decomp)) { Pi_E.emplace_back(pi_loc(r_all, r_alpha, r_alpha, r_alpha, r_alpha)); }
438
439 auto extract_one_imp = [&](long n_imp) {
440 auto const &rpsi = reverse_psi[n_imp];
441 auto [alpha, sigma] = rpsi(0, 0)[0];
442 return Pi_E[alpha];
443 };
444
445 return range(n_impurities()) | stdv::transform(extract_one_imp) | tl::to<std::vector>();
446 }
447 // --------------------------------------------------------------------------------------------
448
449 //FIXME : protect this function as it will only work with a Pi_embed_decomp
450 nda::array<dcomplex, 5> embedding::embed_2p(std::vector<nda::array<dcomplex, 5>> const &pi_imp_vec) const {
451
452 auto n_w = pi_imp_vec[0].extent(0);
453
454 auto Pi_embed = std::vector<nda::array<dcomplex, 5>>(n_alpha());
455 for (auto alpha : range(n_alpha())) {
456 auto bl_size = sigma_embed_decomp[alpha];
457 Pi_embed[alpha] = nda::zeros<dcomplex>(n_w, bl_size, bl_size, bl_size, bl_size);
458 }
459
460 for (auto alpha : range(n_alpha())) {
461 auto const &m = psi(alpha, 0);
462 if (m.imp_idx == -1) continue; // check
463 Pi_embed[alpha] = pi_imp_vec[m.imp_idx];
464 }
465
466 auto dim_C = stdr::fold_left(sigma_embed_decomp, 0, std::plus<>());
467 auto Pi_C = nda::array<dcomplex, 5>(n_w, dim_C, dim_C, dim_C, dim_C);
468 for (auto &&[alpha, sli] : enumerated_sub_slices(sigma_embed_decomp)) { Pi_C(r_all, sli, sli, sli, sli) = Pi_embed[alpha]; }
469 return Pi_C;
470 }
471
472} // namespace triqs::modest
A custom output stream that automatically indents each new line by a specified number of spaces.
Definition streams.hpp:88
The embedding class.
Definition embedding.hpp:29
std::vector< nda::array< dcomplex, 3 > > embed_1p(std::vector< std::vector< nda::array< dcomplex, 3 > > > const &Sigma_imp_vec) const
Embed single-particle quantities (CoQui).
C2PY_IGNORE gf_struct2_t sigma_embed_block_shape() const
Gf block structure for .
nda::array< dcomplex, 4 > embed_tensor(std::vector< nda::array< dcomplex, 4 > > const &U_tensor_vec) const
Embed tensors (CoQui).
long n_impurities() const
Number of impurities.
long n_gamma(long imp_idx) const
Number of blocks in for the [imp_idx].
long n_sigma() const
Number of blocks in for the .
std::vector< gf_struct_t > imp_block_shape() const
Gf block structure for the impurity solvers.
embedding flip_spin(long alpha) const
Flip the spins ( ) for block .
embedding(std::vector< long > sigma_embed_decomposition, std::vector< std::vector< long > > imp_decompositions, nda::array< imp_block_t, 2 > psi, std::vector< std::string > sigma_names)
Construct an embedding object.
Definition embedding.cpp:18
nda::array< dcomplex, 5 > embed_2p(std::vector< nda::array< dcomplex, 5 > > const &pi_imp_vec) const
Embed two-particle quantities (CoQui).
std::vector< std::string > sigma_names() const
The names of the sigma indices.
std::vector< block_gf< Mesh, matrix_valued > > extract(block2_gf< Mesh, matrix_valued > const &g_loc) const
Extract single-particle quantities (TRIQS/ModEST).
long n_alpha() const
Number of blocks in for the .
std::vector< long > imp_decomposition(long imp_idx) const
The impurity decomposition.
std::vector< nda::array< dcomplex, 5 > > extract_2p(nda::array< dcomplex, 5 > const &Pi_loc) const
Extract two-particle quantities (CoQui).
std::vector< std::vector< nda::array< dcomplex, 3 > > > extract_1p(nda::array< dcomplex, 4 > const &g_loc) const
Extract single-particle quantities (CoQui).
std::string description(bool verbosity=false) const
Summarize the embedding object.
embedding drop(long imp_idx) const
Remove an impurity from the embedding table .
embedding split(long imp_idx, std::function< bool(long)> p) const
Split impurity imp_idx.
embedding replace(long imp_idx_to_remove, long imp_idx_to_replace_with) const
Replaces one impurity in the embedding table .
std::vector< nda::array< dcomplex, 4 > > extract_tensor(nda::array< dcomplex, 4 > const &U_tensor) const
Extract tensors (CoQui).
block2_gf< Mesh, matrix_valued > embed(std::vector< block_gf< Mesh, matrix_valued > > const &Sigma_imp_vec) const
Embed single-particle quantities (TRIQS/ModEST).
Describe the atomic orbitals within downfolded space.
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.
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.
long n_atoms() const
The number of atoms.
std::vector< std::string > sigma_names() const
Names of spin indices for naming blocks in block GFs.
embedding make_embedding(local_space const &C_space, bool use_atom_equivalences, bool use_atom_decomp)
Make an embedding from the local space.
void format_as_table(std::ostream &out, nda::Matrix auto const &mat, auto const &row_labels, auto const &col_labels)
Format the matrix mat as a table, with row/col_labels.
std::ostream & operator<<(std::ostream &out, one_body_elements_on_grid const &)
Definition printing.cpp:73
embedding make_embedding_with_no_equivalences(local_space const &C_space, bool use_atom_decomp)
auto format_as(embedding::imp_block_t const &p)
embedding make_embedding_with_equivalences(local_space const &C_space, bool use_atom_decomp)
Definition embedding.cpp:79
embedding embedding_builder(std::vector< std::string > const &spin_names, nda::array< std::vector< long >, 2 > const &block_decomposition, std::vector< long > const &atom_to_imp)
Definition embedding.cpp:41
nda::array< nda::matrix< dcomplex >, 2 > block2_matrix_t
Definition embedding.hpp:15
static constexpr auto r_all
Definition defs.hpp:40
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)