TRIQS/triqs_modest 3.3.0
Brillouin zone summation
Loading...
Searching...
No Matches
gloc_fixed_grid.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 "./density.hpp"
9#include <triqs/mesh.hpp>
10#include "utils/gf_supp.hpp"
11
12namespace triqs::modest {
13
14// omp reduction operation for block2_gf
15#pragma omp declare reduction(block2_gf_sum : block2_gf<imfreq, matrix_valued> : omp_out += omp_in) \
16 initializer(omp_priv = make_block2_gf(omp_orig(0, 0).mesh(), get_struct(omp_orig)))
17#pragma omp declare reduction(block2_gf_sum : block2_gf<dlr_imfreq, matrix_valued> : omp_out += omp_in) \
18 initializer(omp_priv = make_block2_gf(omp_orig(0, 0).mesh(), get_struct(omp_orig)))
19
31 template <typename Mesh>
32 block2_gf<Mesh, matrix_valued> gloc_for_matrix_valued_dispersion_impl(one_body_elements_on_grid const &obe, double mu,
33 block2_gf<Mesh, matrix_valued> const &Sigma_dynamic,
34 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static) {
35
36 auto n_sigma = obe.C_space.n_sigma();
37 auto n_M = obe.C_space.dim();
38 auto n_kpts = long(obe.H.n_k());
39 auto const &mesh = Sigma_dynamic(0, 0).mesh();
40
41 auto embedding_decomp = get_struct(Sigma_dynamic).dims(r_all, 0) | tl::to<std::vector>();
42
43 auto PSP = [&](auto &w, auto &k_idx, auto &sigma) {
44 auto N_nu = obe.H.N_nu(sigma, k_idx);
45 auto out = nda::zeros<dcomplex>(N_nu, N_nu);
46 for (auto &&[alpha, R] : enumerated_sub_slices(embedding_decomp)) {
47 auto P = obe.P.P(sigma, k_idx)(R, r_all);
48 out(r_all, r_all) += dagger(P) * nda::matrix<dcomplex>{Sigma_dynamic(alpha, sigma).data()(w, r_all, r_all) + Sigma_static(alpha, sigma)} * P;
49 }
50 return out;
51 };
52
53 auto gloc_k = [&](auto &k_idx, auto &sigma) {
54 auto out = gf{mesh, {n_M, n_M}};
55 auto P = obe.P.P(sigma, k_idx);
56 for (auto &&[n, w] : enumerate(mesh)) {
57 out.data()(n, r_all, r_all) = P * inverse(w + mu - obe.H.H(sigma, k_idx) - PSP(n, k_idx, sigma)) * dagger(P);
58 }
59 return out;
60 };
61
62 auto gloc_result = make_block2_gf(mesh, obe.C_space.Gc_block_shape());
63 mpi::communicator comm = {};
64#pragma omp parallel for collapse(2) reduction(block2_gf_sum : gloc_result) default(none) shared(comm, gloc_k, n_kpts, n_sigma, obe, r_all)
65 for (auto k_idx : mpi::chunk(range(n_kpts), comm)) {
66 for (auto sigma : range(n_sigma)) { gloc_result(0, sigma).data()(r_all, r_all, r_all) += obe.H.k_weights(k_idx) * gloc_k(k_idx, sigma).data(); }
67 }
68 gloc_result = mpi::all_reduce(gloc_result);
69
70 if (auto const &S = obe.ibz_symm_ops; S) { gloc_result = S->symmetrize(gloc_result, obe.C_space.atomic_decomposition()); }
71 return gloc_result;
72 }
75 // ------------------------------------------------------------------
76
80
91 template <typename Mesh>
92 block2_gf<Mesh, matrix_valued> gloc(one_body_elements_on_grid const &obe, double mu, block2_gf<Mesh, matrix_valued> const &Sigma_dynamic,
93 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static) {
94
95 // intercept if the dispersion in obe is matrix valued. The Woodbury offers no performance gain for this case.
96 if (obe.H.matrix_valued) return gloc_for_matrix_valued_dispersion_impl(obe, mu, Sigma_dynamic, Sigma_static);
97
98 auto n_sigma = Sigma_dynamic.size2();
99 auto M = obe.C_space.dim();
100 auto n_kpts = long(obe.H.n_k());
101 auto const &mesh = Sigma_dynamic(0, 0).mesh();
102 auto gloc_result = make_block2_gf(mesh, obe.C_space.Gc_block_shape());
103 auto omegas = mesh | tl::to<std::vector<dcomplex>>();
104
105 // Embedding decomposition from structure of Sigma
106 auto embedding_decomp = get_struct(Sigma_dynamic).dims(r_all, 0) | tl::to<std::vector>();
107
108 auto timer = scoped_timer{};
109 // ---------
110 // NOTE: Is there any reason why sigma loop should be the external one?
111 // Internal is favorable for maximum parallelization.
112 mpi::communicator comm = {};
113#pragma omp parallel for collapse(2) reduction(block2_gf_sum : gloc_result) default(none) \
114 shared(comm, r_all, n_kpts, n_sigma, obe, mu, omegas, mesh, M, embedding_decomp, Sigma_dynamic, Sigma_static)
115 for (auto k_idx : mpi::chunk(range(n_kpts), comm)) {
116 for (auto sigma : range(n_sigma)) {
117 auto Y = detail::G0_C_k_sigma(obe, mu, k_idx, sigma, omegas, false);
118 for (auto &&[n, om] : itertools::enumerate(mesh)) {
119 auto Y1 = Y(n, r_all, r_all);
120 auto B = detail::calc_inv_G_G0(M, embedding_decomp, Sigma_dynamic, Sigma_static, om, sigma, Y1, Y1);
121 gloc_result(0, sigma).data()(n, r_all, r_all) += obe.H.k_weights(k_idx) * B;
122 }
123 }
124 // No normalization: the Pk are in obe ALREADY normalized.
125 }
126 gloc_result = mpi::all_reduce(gloc_result);
127
128 // FIXME :: the IBZ should work on a proper gf_view with atomic decomposition
129 // CHANGE IBZ accordingly ...
130 if (auto const &S = obe.ibz_symm_ops; S) gloc_result = S->symmetrize(gloc_result, obe.C_space.atomic_decomposition());
131 return gloc_result;
132 }
133
146 template <typename Mesh> block2_gf<Mesh, matrix_valued> gloc(Mesh const &mesh, one_body_elements_on_grid const &obe, double mu) {
147 auto Sigma_dynamic = make_block2_gf(mesh, obe.C_space.Gc_block_shape());
148 auto Sigma_static = nda::array<nda::matrix<dcomplex>, 2>(1, obe.C_space.n_sigma());
149 for (auto [i, j] : Sigma_static.indices()) { Sigma_static(i, j) = nda::zeros<dcomplex>(obe.C_space.dim(), obe.C_space.dim()); }
150 return gloc(obe, mu, Sigma_dynamic, Sigma_static);
151 }
153
165 template <typename Mesh>
166 block_gf<Mesh, matrix_valued> hybridization(std::vector<nda::matrix<dcomplex>> const &epsilon_levels, block_gf<Mesh, matrix_valued> const &Gloc,
167 block_gf<Mesh, matrix_valued> const &Sigma_dynamic,
168 std::vector<nda::matrix<dcomplex>> const &Sigma_static) {
169 auto gf_struct = get_struct(Gloc);
170 auto mesh = Gloc[0].mesh();
171 auto Delta = block_gf{mesh, gf_struct};
172 auto n_blocks = gf_struct.size();
173 for (auto bl : range(n_blocks)) {
174 for (auto &&[n, w] : enumerate(mesh))
175 Delta[bl].data()(n, r_all, r_all) =
176 (w - epsilon_levels[bl] - inverse(Gloc[bl]).data()(n, r_all, r_all) - (Sigma_dynamic[bl].data()(n, r_all, r_all) + Sigma_static[bl]));
177 }
178 return Delta;
179 }
180
190 template <typename Mesh>
191 block_gf<Mesh, matrix_valued> hybridization(std::vector<nda::matrix<dcomplex>> const &epsilon_levels, block_gf<Mesh, matrix_valued> const &Gloc) {
192 auto Sigma_static = get_struct(Gloc) | stdv::transform([](auto &x) { return nda::zeros<dcomplex>(x.second, x.second); })
193 | tl::to<std::vector<nda::matrix<dcomplex>>>();
194 auto Sigma_dynamic = block_gf{Gloc[0].mesh(), get_struct(Gloc)};
195 return hybridization(epsilon_levels, Gloc, Sigma_dynamic, Sigma_static);
196 }
197
198 // ------------------------------------------------------
199
200 template block2_gf<imfreq, matrix_valued> gloc(one_body_elements_on_grid const &one_body, double mu,
201 block2_gf<imfreq, matrix_valued> const &Sigma_dynamic,
202 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static);
203 template block2_gf<imfreq, matrix_valued> gloc(imfreq const &mesh, one_body_elements_on_grid const &obe, double mu);
204 template block2_gf<dlr_imfreq, matrix_valued> gloc(one_body_elements_on_grid const &one_body, double mu,
205 block2_gf<dlr_imfreq, matrix_valued> const &Sigma_dynamic,
206 nda::array<nda::matrix<dcomplex>, 2> const &Sigma_static);
207 template block2_gf<dlr_imfreq, matrix_valued> gloc(dlr_imfreq const &mesh, one_body_elements_on_grid const &obe, double mu);
208 template block_gf<imfreq, matrix_valued> hybridization(std::vector<nda::matrix<dcomplex>> const &epsilon_levels,
209 block_gf<imfreq, matrix_valued> const &Gloc);
210 template block_gf<imfreq, matrix_valued> hybridization(std::vector<nda::matrix<dcomplex>> const &epsilon_levels,
211 block_gf<imfreq, matrix_valued> const &Gloc,
212 block_gf<imfreq, matrix_valued> const &Sigma_dynamic,
213 std::vector<nda::matrix<dcomplex>> const &Sigma_static);
214 template block_gf<dlr_imfreq, matrix_valued> hybridization(std::vector<nda::matrix<dcomplex>> const &epsilon_levels,
215 block_gf<dlr_imfreq, matrix_valued> const &Gloc);
216 template block_gf<dlr_imfreq, matrix_valued> hybridization(std::vector<nda::matrix<dcomplex>> const &epsilon_levels,
217 block_gf<dlr_imfreq, matrix_valued> const &Gloc,
218 block_gf<dlr_imfreq, matrix_valued> const &Sigma_dynamic,
219 std::vector<nda::matrix<dcomplex>> const &Sigma_static);
220
221} // namespace triqs::modest
long n_sigma() const
Dimension of the σ index.
auto atomic_decomposition() const
Generates [dimension of the atomic shell].
long dim() const
Dimension of the correlated space.
C2PY_IGNORE gf_struct2_t Gc_block_shape() const
Shape of the Green function in the correlated space, without block decomposition.
A utility class for measuring the execution time of a scope.
block2_gf< Mesh, matrix_valued > gloc(one_body_elements_on_grid const &obe, double mu, block2_gf< Mesh, matrix_valued > const &Sigma_dynamic, nda::array< nda::matrix< dcomplex >, 2 > const &Sigma_static)
compute Gš“’ local Green's function on Mesh(MxM)
block_gf< Mesh, matrix_valued > hybridization(std::vector< nda::matrix< dcomplex > > const &epsilon_levels, block_gf< Mesh, matrix_valued > const &Gloc, block_gf< Mesh, matrix_valued > const &Sigma_dynamic, std::vector< nda::matrix< dcomplex > > const &Sigma_static)
Compute the hybridization function from the effective impurity levels, the local Green's function,...
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
Definition gf_supp.hpp:41
gf_struct_t get_struct(block_gf< Mesh > const &g)
Definition gf_supp.hpp:51
static constexpr auto r_all
Definition defs.hpp:40
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
bool matrix_valued
Is the dispersion matrix-valued?
nda::array< double, 1 > k_weights
k_weights[k_idx]
long n_k() const
Number of k points in the grid.
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.