TRIQS/triqs_modest 3.3.0
Modular Electronic Structure Toolkit
Loading...
Searching...
No Matches
embedding.hpp
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#pragma once
7#include "./downfolding.hpp"
8#include "utils/defs.hpp"
9#include "utils/gf_supp.hpp"
10#include "utils/nda_supp.hpp"
11#include "utils/range_supp.hpp"
12#include <fmt/ranges.h>
13
14namespace triqs {
15 using block_matrix_t = std::vector<nda::matrix<dcomplex>>;
16 using block2_matrix_t = nda::array<nda::matrix<dcomplex>, 2>;
17} // namespace triqs
18
19namespace triqs::modest {
20
30 class embedding {
31
32 // decomposition of C used by Sigma
33 std::vector<long> sigma_embed_decomp;
34
35 // decomposition of each impurity
36 std::vector<std::vector<long>> imp_decomps;
37
38 // names of the sigma (and tau) indices
39 std::vector<std::string> _sigma_names;
40
41 // names of the alpha indices
42 std::vector<std::string> alpha_names;
43
44 // stream
45 friend std::ostream &operator<<(std::ostream &out, embedding const &E);
46
48 friend void h5_write(h5::group g, std::string const &name, embedding const &x);
49 friend void h5_read(h5::group g, std::string const &name, embedding &x);
50
51 public:
55 struct imp_block_t {
56
57 long imp_idx = 0;
58 long gamma = 0;
59 long tau = 0;
60
61 imp_block_t() = default;
62 imp_block_t(long n_imp, long gamma, long tau) : imp_idx(n_imp), gamma(gamma), tau(tau) {}
63 friend bool operator==(imp_block_t const &, imp_block_t const &) = default;
64
65 // FIXME : merge with format_as
66 friend std::ostream &operator<<(std::ostream &out, imp_block_t const &x) {
67 return out << fmt::format("(imp_idx = {}, γ = {}, τ = {})", x.imp_idx, x.gamma, x.tau);
68 }
69 };
70
73 private:
74 // For each imp, for all (γ, τ), a list of all (α, σ) such that ψ[α, σ] ==(n_imp, γ, τ)
75 nda::array<imp_block_t, 2> psi; // ψ [α, σ] --> (n_imp, γ, τ)
76
77 // reverse ψ [n_imp] -> (γ, τ) -> [(α, σ)]
78 std::vector<nda::array<std::vector<std::array<long, 2>>, 2>> reverse_psi;
79
80 public:
91 embedding(std::vector<long> sigma_embed_decomposition, std::vector<std::vector<long>> imp_decompositions, nda::array<imp_block_t, 2> psi,
92 std::vector<std::string> sigma_names);
93
97 embedding() = default; // for h5_read
98
103
108 imp_block_t operator[](long alpha, long sigma) const { return psi(alpha, sigma); }
109
110 // HL: get_psi -> psi to match other classes?
112 [[nodiscard]] nda::array<imp_block_t, 2> get_psi() const { return psi; }
113
115 [[nodiscard]] long n_alpha() const { return psi.extent(0); }
116
118 [[nodiscard]] long n_sigma() const { return psi.extent(1); }
119
121 [[nodiscard]] long n_gamma(long imp_idx) const { return long(imp_decomps[imp_idx].size()); }
122
124 [[nodiscard]] long n_impurities() const { return long(imp_decomps.size()); }
125
127 [[nodiscard]] std::vector<std::string> sigma_names() const { return _sigma_names; };
128
130 [[nodiscard]] std::vector<long> imp_decomposition(long imp_idx) const { return imp_decomps[imp_idx]; };
131
134
136 std::vector<gf_struct_t> imp_block_shape() const;
137
139 std::string description(bool verbosity = false) const;
141
142 // ****************** Operation methods to change the embedding **********************
143
150 // --------------------------------------------------------
151 bool operator==(embedding const &other) const = default;
152 // --------------------------------------------------------
153
163 embedding drop(long imp_idx) const;
164
175 embedding replace(long imp_idx_to_remove, long imp_idx_to_replace_with) const;
176
186 embedding flip_spin(long alpha) const;
187
197 embedding flip_spin(std::vector<long> alphas) const;
198
203 embedding split(long imp_idx, std::function<bool(long)> p) const;
204
215 embedding split(long imp_idx, std::vector<long> const &block_list) const;
216
217 embedding split(long imp_idx, std::initializer_list<const char *> x) = delete;
218
220
221 //------------------------------------------------------------------------------------
222
224 template <typename Mesh> std::vector<std::pair<block_gf<Mesh, matrix_valued>, block_matrix_t>> make_zero_imp_self_energies(Mesh const &mesh) {
225
226 auto make_block_matrix = [](auto const &gf_struct) {
227 return gf_struct | stdv::transform([](auto &x) {
228 auto bl_size = x.second;
229 return nda::zeros<dcomplex>(bl_size, bl_size);
230 })
231 | tl::to<std::vector<nda::matrix<dcomplex>>>();
232 };
233
234 auto make_self_energy = [&](auto const &gf_struct) {
235 auto Sigma_static = make_block_matrix(gf_struct);
236 auto Sigma_dynamic = block_gf<Mesh, matrix_valued>{mesh, gf_struct};
237 return std::make_pair(Sigma_dynamic, Sigma_static);
238 };
239
240 return imp_block_shape() | stdv::transform(make_self_energy) | tl::to<std::vector>();
241 }
242 //------------------------------------------------------------------------------------
243
244 // ****************************************************
245 // Embedding Extract/Embed methods
246 // ****************************************************
253 //--------------------- Embed -----------------------------------------
254
266 template <typename Mesh> block2_gf<Mesh, matrix_valued> embed(std::vector<block_gf<Mesh, matrix_valued>> const &Sigma_imp_vec) const {
267 // Check that all meshes are the same for Sigma_imp_vec
268 if (not all_equal(Sigma_imp_vec | stdv::transform([](auto &&x) -> decltype(auto) { return x[0].mesh(); })))
269 throw std::runtime_error{"[embedding_desc::embed]: meshes of solvers are not all equal"};
270
271 auto const &mesh = Sigma_imp_vec[0][0].mesh();
272
273 // build the result
274 auto Sigma_embed = make_block2_gf(mesh, this->sigma_embed_block_shape());
275 for (auto &&[S, m] : zip(Sigma_embed, psi)) {
276 if (m.imp_idx == -1) continue;
277 S() = Sigma_imp_vec[m.imp_idx][m.gamma + n_gamma(m.imp_idx) * m.tau];
278 }
279 return Sigma_embed;
280 }
281
292 template <typename Mesh>
293 std::pair<block2_gf<Mesh, matrix_valued>, block2_matrix_t> embed(std::vector<block_gf<Mesh, matrix_valued>> const &Sigma_imp_vec,
294 std::vector<block_matrix_t> const &Sigma_imp_static_vec) const {
295 if (Sigma_imp_vec.size() != Sigma_imp_static_vec.size()) {
296 throw std::runtime_error(fmt::format("The lists of self-energies are not equal {} != {}", Sigma_imp_vec.size(), Sigma_imp_static_vec.size()));
297 }
298 return {this->embed(Sigma_imp_vec), this->embed(Sigma_imp_static_vec)};
299 }
300
302 block2_matrix_t embed(std::vector<block_matrix_t> const &Sigma_imp_static_vec) const;
303
304 block_matrix_t embed_ij(std::vector<block_matrix_t> const &Sigma_imp_static_vec) const;
305
306 //--------------------- Extract ---------------------------------------
307
315 template <typename Mesh> std::vector<block_gf<Mesh, matrix_valued>> extract(block2_gf<Mesh, matrix_valued> const &g_loc) const {
316
317 if (auto decomp = get_struct(g_loc).dims(r_all, 0) | tl::to<std::vector>(); decomp != this->sigma_embed_decomp) {
318 if (decomp.size() != 1) throw std::runtime_error{"extract: g should have decomp = sigma_embedding_decomp or [1]"};
319 return extract(decomposition_view(g_loc, this->sigma_embed_block_shape()));
320 }
321
322 // FIXME : check all meshes are the same
323 auto imp_gf_stru_list = imp_block_shape();
324 auto extract_one_imp = [&](long n_imp) {
325 auto gimp = block_gf{g_loc(0, 0).mesh(), imp_gf_stru_list[n_imp]};
326 auto const &rpsi = reverse_psi[n_imp];
327 for (auto [gamma, tau] : rpsi.indices()) {
328 auto [alpha, sigma] = rpsi(gamma, tau)[0];
329 gimp[gamma + n_gamma(n_imp) * tau].data() = g_loc(alpha, sigma).data();
330 }
331 return gimp;
332 };
333 return range(n_impurities()) | stdv::transform(extract_one_imp) | tl::to<std::vector>();
334 }
335
337 std::vector<block_matrix_t> extract(block2_matrix_t const &matrix_C) const;
338
340
348 //--------------------- Embed -----------------------------------------
349
351 std::vector<nda::array<dcomplex, 3>> embed_wij(std::vector<std::vector<nda::array<dcomplex, 3>>> const &Sigma_imp_vec) const;
352
354 nda::array<dcomplex, 5> embed_wijkl(std::vector<nda::array<dcomplex, 5>> const &pi_imp_vec) const;
355
357 nda::array<dcomplex, 4> embed_ijkl(std::vector<nda::array<dcomplex, 4>> const &U_tensor_vec) const;
358
359 //--------------------- Extract ---------------------------------------
360
362 std::vector<std::vector<nda::array<dcomplex, 3>>> extract_wij(nda::array<dcomplex, 4> const &g_loc) const;
363
365 std::vector<nda::array<dcomplex, 5>> extract_wijkl(nda::array<dcomplex, 5> const &Pi_loc) const;
366
368 std::vector<nda::array<dcomplex, 4>> extract_ijkl(nda::array<dcomplex, 4> const &U_tensor) const;
369
371 };
372
373 // ***************************** Free functions/factories *******************************************
374
392 embedding embedding_builder(std::vector<std::string> const &spin_names, nda::array<std::vector<long>, 2> const &block_decomposition,
393 std::vector<long> const &atom_to_imp);
405 embedding embedding_builder(std::vector<std::string> const &spin_names, std::vector<std::vector<long>> const &block_decomposition,
406 std::vector<long> const &atom_to_imp);
407
422 embedding make_embedding(local_space const &C_space, bool use_atom_equivalences = true, bool use_atom_decomp = false);
423
424 // -----------------------------------------------------------------------
439 inline std::pair<one_body_elements_on_grid, embedding> make_embedding_with_clusters(one_body_elements_on_grid obe,
440 std::vector<std::vector<long>> const &atom_partition) {
441 auto new_obe = permute_local_space(atom_partition, obe);
442 auto E = make_embedding(new_obe.C_space, false);
443 return {new_obe, E};
444 }
447 //-------------------------------------------------------------------------
458 template <typename Mesh>
459 std::vector<gf<Mesh, matrix_valued>> rotate_embedded_self_energy(block2_gf<Mesh, matrix_valued> const &Sigma_embed_dynamic_loc,
460 nda::matrix<dcomplex> const &U) {
461 auto const &mesh = Sigma_embed_dynamic_loc(0, 0).mesh();
462 auto const &embedding_decomp = get_struct(Sigma_embed_dynamic_loc).dims(r_all, 0) | tl::to<std::vector>();
463 auto n_sigma = Sigma_embed_dynamic_loc.size2();
464 auto Sigma_embed_dynamic_rot =
465 range(n_sigma) | stdv::transform([&](auto s) { return gf<Mesh, matrix_valued>{mesh, {U.extent(0), U.extent(0)}}; }) | tl::to<std::vector>();
466
467 for (auto s : range(n_sigma))
468 for (auto &&[n, w] : enumerate(mesh)) {
469 for (auto &&[alpha, R] : enumerated_sub_slices(embedding_decomp)) {
470 auto P = U(r_all, R);
471 Sigma_embed_dynamic_rot[s].data()(n, r_all, r_all) +=
472 P * nda::matrix<dcomplex>{Sigma_embed_dynamic_loc(alpha, s).data()(n, r_all, r_all)} * dagger(P);
473 }
474 }
475 return Sigma_embed_dynamic_rot;
476 }
477
478 //-------------------------------------------------------------------------
489 template <typename Mesh>
490 std::vector<gf<Mesh, matrix_valued>> rotate_embedded_self_energy(block2_gf<Mesh, matrix_valued> const &Sigma_embed_dynamic_loc,
491 one_body_elements_on_grid const &obe) {
492 auto const &U = obe.C_space.rotation_from_dft_to_local_basis()(r_all, 0) | tl::to<std::vector<nda::matrix<dcomplex>>>();
493 return rotate_embedded_self_energy(Sigma_embed_dynamic_loc, nda::block_diag(U));
494 }
495
496 //-------------------------------------------------------------------------
506 std::vector<nda::array<dcomplex, 3>> rotate_embedded_self_energy(std::vector<nda::array<dcomplex, 3>> const &Sigma_embed_dynamic_loc,
507 nda::matrix<dcomplex> const &U);
508
509 //-------------------------------------------------------------------------
519 std::vector<nda::array<dcomplex, 3>> rotate_embedded_self_energy(std::vector<nda::array<dcomplex, 3>> const &Sigma_embed_dynamic_loc,
520 one_body_elements_on_grid const &obe);
521
522 //-------------------------------------------------------------------------
532 std::vector<nda::matrix<dcomplex>> rotate_embedded_self_energy(std::vector<nda::matrix<dcomplex>> const &Sigma_embed_static_loc,
533 nda::matrix<dcomplex> const &U);
534
535 //-------------------------------------------------------------------------
545 std::vector<nda::matrix<dcomplex>> rotate_embedded_self_energy(std::vector<nda::matrix<dcomplex>> const &Sigma_embed_static_loc,
546 one_body_elements_on_grid const &obe);
547
548 // ------------------------------------------------------------------------------
549
550#define INSTANTIATE(Mesh) \
551 template block2_gf<Mesh, matrix_valued> embedding::embed(std::vector<block_gf<Mesh, matrix_valued>> const &) const; \
552 template std::pair<block2_gf<Mesh, matrix_valued>, block2_matrix_t> embedding::embed(std::vector<block_gf<Mesh, matrix_valued>> const &, \
553 std::vector<block_matrix_t> const &) const; \
554 template std::vector<block_gf<Mesh, matrix_valued>> embedding::extract(block2_gf<Mesh, matrix_valued> const &) const; \
555 template std::vector<std::pair<block_gf<Mesh, matrix_valued>, block_matrix_t>> embedding::make_zero_imp_self_energies(Mesh const &); \
556 template std::vector<gf<Mesh, matrix_valued>> rotate_embedded_self_energy(block2_gf<Mesh, matrix_valued> const &, nda::matrix<dcomplex> const &); \
557 template std::vector<gf<Mesh, matrix_valued>> rotate_embedded_self_energy(block2_gf<Mesh, matrix_valued> const &, \
558 one_body_elements_on_grid const &);
559 INSTANTIATE(imfreq);
560 INSTANTIATE(refreq);
561 INSTANTIATE(dlr_imfreq);
562#undef INSTANTIATE
563
564} // namespace triqs::modest
The embedding class.
Definition embedding.hpp:30
friend void h5_write(h5::group g, std::string const &name, embedding const &x)
h5 read/write
Definition h5.cpp:104
C2PY_IGNORE gf_struct2_t sigma_embed_block_shape() const
Gf block structure for .
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 .
block_matrix_t embed_ij(std::vector< block_matrix_t > const &Sigma_imp_static_vec) const
bool operator==(embedding const &other) const =default
embedding split(long imp_idx, std::initializer_list< const char * > x)=delete
nda::array< imp_block_t, 2 > get_psi() const
The mapping table .
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).
std::vector< nda::array< dcomplex, 4 > > extract_ijkl(nda::array< dcomplex, 4 > const &U_tensor) const
Extract tensors (CoQui).
long n_alpha() const
Number of blocks in for the .
std::vector< long > imp_decomposition(long imp_idx) const
The impurity decomposition.
nda::array< dcomplex, 4 > embed_ijkl(std::vector< nda::array< dcomplex, 4 > > const &U_tensor_vec) const
Embed tensors (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 .
friend std::ostream & operator<<(std::ostream &out, embedding const &E)
std::vector< nda::array< dcomplex, 5 > > extract_wijkl(nda::array< dcomplex, 5 > const &Pi_loc) const
Extract two-particle quantities (CoQui).
friend void h5_read(h5::group g, std::string const &name, embedding &x)
Definition h5.cpp:96
std::vector< std::pair< block_gf< Mesh, matrix_valued >, block_matrix_t > > make_zero_imp_self_energies(Mesh const &mesh)
Zero initialize impurity self-energies.
embedding split(long imp_idx, std::function< bool(long)> p) const
Split impurity imp_idx.
std::vector< std::vector< nda::array< dcomplex, 3 > > > extract_wij(nda::array< dcomplex, 4 > const &g_loc) const
Extract single-particle quantities (CoQui).
embedding replace(long imp_idx_to_remove, long imp_idx_to_replace_with) const
Replaces one impurity in the embedding table .
imp_block_t operator[](long alpha, long sigma) const
Bracket accessor: .
nda::array< dcomplex, 5 > embed_wijkl(std::vector< nda::array< dcomplex, 5 > > const &pi_imp_vec) const
Embed two-particle quantities (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).
std::pair< block2_gf< Mesh, matrix_valued >, block2_matrix_t > embed(std::vector< block_gf< Mesh, matrix_valued > > const &Sigma_imp_vec, std::vector< block_matrix_t > const &Sigma_imp_static_vec) const
Embed single-particle quantities (TRIQS/ModEST).
std::vector< nda::array< dcomplex, 3 > > embed_wij(std::vector< std::vector< nda::array< dcomplex, 3 > > > const &Sigma_imp_vec) const
Embed single-particle quantities (CoQui).
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.
#define C2PY_IGNORE
Definition defs.hpp:17
#define INSTANTIATE(Mesh)
std::pair< one_body_elements_on_grid, embedding > make_embedding_with_clusters(one_body_elements_on_grid obe, std::vector< std::vector< long > > const &atom_partition)
Make an embedding for clusters of atoms.
embedding make_embedding(local_space const &C_space, bool use_atom_equivalences, bool use_atom_decomp)
Make an embedding from the local space.
nda::array< T, 2 > block_diag(std::vector< nda::matrix< T > > const &matrices)
Definition nda_supp.hpp:40
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
Definition gf_supp.hpp:41
block2_gf< Mesh > decomposition_view(block2_gf< Mesh > const &g, gf_struct2_t const &stru)
Definition gf_supp.hpp:64
gf_struct_t get_struct(block_gf< Mesh > const &g)
Definition gf_supp.hpp:51
std::ostream & operator<<(std::ostream &out, one_body_elements_on_grid const &)
Definition printing.cpp:73
std::vector< nda::array< dcomplex, 3 > > rotate_embedded_self_energy(std::vector< nda::array< dcomplex, 3 > > const &Sigma_embed_dynamic_loc, nda::matrix< dcomplex > const &U)
Rotate the dynamic part of the embedded self-energy from the local (solver) basis to the orbital basi...
one_body_elements_on_grid permute_local_space(std::vector< std::vector< long > > const &atom_partition, one_body_elements_on_grid const &obe)
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:16
static constexpr auto r_all
Definition defs.hpp:40
bool all_equal(R const &r)
Determines if all elements in the given range are equal.
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
std::vector< nda::matrix< dcomplex > > block_matrix_t
Definition embedding.hpp:15
A one-body elements struct where all of the underlying data exists on a fixed momentum grid.