8#include <triqs/mesh.hpp>
14#pragma omp declare reduction(block2_gf_sum : block2_gf<imfreq, matrix_valued> : omp_out += omp_in) \
15 initializer(omp_priv = make_block2_gf(omp_orig(0, 0).mesh(), get_struct(omp_orig)))
16#pragma omp declare reduction(block2_gf_sum : block2_gf<dlr_imfreq, matrix_valued> : omp_out += omp_in) \
17 initializer(omp_priv = make_block2_gf(omp_orig(0, 0).mesh(), get_struct(omp_orig)))
21 template <
typename Mesh>
22 constexpr auto upfold_self_energy_at_freq(one_body_elements_on_grid
const &obe, downfolding_projector
const &Proj,
23 block2_gf<Mesh, matrix_valued>
const &Sigma_dynamic,
24 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static,
long w_idx,
long k_idx,
long sigma_idx) {
25 auto N_nu = obe.H.N_nu(sigma_idx, k_idx);
26 auto out = nda::zeros<dcomplex>(N_nu, N_nu);
28 auto P = Proj.P(sigma_idx, k_idx)(R, r_all);
30 dagger(P) * nda::matrix<dcomplex>{Sigma_dynamic(alpha, sigma_idx).data()(w_idx, r_all, r_all) + Sigma_static(alpha, sigma_idx)} * P;
36 template <
typename Mesh>
37 constexpr auto local_gf_at_k(one_body_elements_on_grid
const &obe,
double const &mu, downfolding_projector
const &Proj,
38 block2_gf<Mesh, matrix_valued>
const &Sigma_dynamic, nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static) {
39 return [&](
auto const &k_idx,
auto const &sigma_idx) {
40 using nda::linalg::inv;
41 auto const n_M = obe.C_space.dim();
42 auto const &mesh = Sigma_dynamic(0, 0).mesh();
43 auto out = gf{mesh, {n_M, n_M}};
44 auto P = obe.P.P(sigma_idx, k_idx);
45 for (
auto &&[n, w] : enumerate(mesh)) {
46 auto PSP = upfold_self_energy_at_freq(obe, Proj, Sigma_dynamic, Sigma_static, n, k_idx, sigma_idx);
47 out.data()(n, r_all, r_all) = P * inv(w + mu - obe.H.H(sigma_idx, k_idx) - PSP) * dagger(P);
53 template <
typename Mesh>
54 constexpr auto lattice_gf_at_k(one_body_elements_on_grid
const &obe,
double const &mu, block2_gf<Mesh, matrix_valued>
const &Sigma_dynamic,
55 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static) {
56 return [&](
auto const &k_idx,
auto const &sigma_idx) {
57 using nda::linalg::inv;
58 auto const &mesh = Sigma_dynamic(0, 0).mesh();
59 auto N_nu = obe.H.N_nu(sigma_idx, k_idx);
60 auto Glatt = gf{mesh, {N_nu, N_nu}};
61 for (
auto &&[n, w] : enumerate(mesh)) {
62 auto PSP = upfold_self_energy_at_freq(obe, obe.P, Sigma_dynamic, Sigma_static, n, k_idx, sigma_idx);
63 Glatt.data()(n, r_all, r_all) = inv(w + mu - obe.H.H(sigma_idx, k_idx) - PSP);
81 template <
typename Mesh>
83 block2_gf<Mesh, matrix_valued>
const &Sigma_dynamic,
84 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static) {
86 auto n_sigma = obe.C_space.n_sigma();
87 auto n_kpts = long(obe.H.n_k());
89 auto gloc_k = detail::local_gf_at_k(obe, mu, obe.P, Sigma_dynamic, Sigma_static);
90 auto gloc_result =
make_block2_gf(Sigma_dynamic(0, 0).mesh(), obe.C_space.Gc_block_shape());
92 mpi::communicator comm = {};
93#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)
94 for (
auto k_idx : mpi::chunk(range(n_kpts), comm)) {
95 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(); }
98 gloc_result = mpi::all_reduce(gloc_result);
100 if (
auto const &S = obe.ibz_symm_ops; S) { gloc_result = S->symmetrize(gloc_result, obe.C_space.atomic_decomposition()); }
136 template <
typename Mesh>
138 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static) {
141 if (obe.
H.
matrix_valued)
return gloc_for_matrix_valued_dispersion_impl(obe, mu, Sigma_dynamic, Sigma_static);
143 auto n_sigma = Sigma_dynamic.size2();
145 auto n_kpts = long(obe.
H.
n_k());
146 auto const &mesh = Sigma_dynamic(0, 0).mesh();
148 auto omegas = mesh | tl::to<std::vector<dcomplex>>();
156 mpi::communicator comm = {};
157#pragma omp parallel for collapse(2) reduction(block2_gf_sum : gloc_result) default(none) \
158 shared(comm, r_all, n_kpts, n_sigma, obe, mu, omegas, mesh, M, embedding_decomp, Sigma_dynamic, Sigma_static)
159 for (
auto k_idx : mpi::chunk(range(n_kpts), comm)) {
160 for (
auto sigma : range(n_sigma)) {
161 auto Y = detail::G0_C_k_sigma(obe, mu, k_idx, sigma, omegas,
false);
162 for (
auto &&[n, om] : itertools::enumerate(mesh)) {
164 auto B = detail::calc_inv_G_G0(M, embedding_decomp, Sigma_dynamic, Sigma_static, om, sigma, Y1, Y1);
170 gloc_result = mpi::all_reduce(gloc_result);
192 auto Sigma_static = nda::array<nda::matrix<dcomplex>, 2>(1, obe.
C_space.
n_sigma());
193 for (
auto [i, j] : Sigma_static.indices()) { Sigma_static(i, j) = nda::zeros<dcomplex>(obe.
C_space.
dim(), obe.
C_space.
dim()); }
194 return gloc(obe, mu, Sigma_dynamic, Sigma_static);
209 template <
typename Mesh>
210 block_gf<Mesh, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels, block_gf<Mesh, matrix_valued>
const &Gloc,
211 block_gf<Mesh, matrix_valued>
const &Sigma_dynamic,
212 std::vector<nda::matrix<dcomplex>>
const &Sigma_static) {
213 auto gf_struct = Gloc.gf_struct();
214 auto mesh = Gloc[0].mesh();
215 auto Delta = block_gf{mesh, gf_struct};
216 auto n_blocks = gf_struct.size();
217 for (
auto bl : range(n_blocks)) {
218 for (
auto &&[n, w] : enumerate(mesh))
220 (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]));
234 template <
typename Mesh>
235 block_gf<Mesh, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels, block_gf<Mesh, matrix_valued>
const &Gloc) {
236 auto Sigma_static = Gloc.gf_struct() | stdv::transform([](
auto &x) {
return nda::zeros<dcomplex>(x.second, x.second); })
237 | tl::to<std::vector<nda::matrix<dcomplex>>>();
238 auto Sigma_dynamic = block_gf{Gloc[0].mesh(), Gloc.gf_struct()};
239 return hybridization(epsilon_levels, Gloc, Sigma_dynamic, Sigma_static);
245 block2_gf<imfreq, matrix_valued>
const &Sigma_dynamic,
246 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static);
249 block2_gf<dlr_imfreq, matrix_valued>
const &Sigma_dynamic,
250 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static);
252 template block_gf<imfreq, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels,
253 block_gf<imfreq, matrix_valued>
const &Gloc);
254 template block_gf<imfreq, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels,
255 block_gf<imfreq, matrix_valued>
const &Gloc,
256 block_gf<imfreq, matrix_valued>
const &Sigma_dynamic,
257 std::vector<nda::matrix<dcomplex>>
const &Sigma_static);
258 template block_gf<dlr_imfreq, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels,
259 block_gf<dlr_imfreq, matrix_valued>
const &Gloc);
260 template block_gf<dlr_imfreq, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels,
261 block_gf<dlr_imfreq, matrix_valued>
const &Gloc,
262 block_gf<dlr_imfreq, matrix_valued>
const &Sigma_dynamic,
263 std::vector<nda::matrix<dcomplex>>
const &Sigma_static);
long n_sigma() const
Dimension of the index.
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.
std::vector< long > atomic_decomposition() const
Dimensions of each atomic shell, in order.
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 local Green's function on a mesh.
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,...
gf_struct2_t get_struct(block2_gf< Mesh, matrix_valued > const &g)
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
static constexpr auto r_all
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
nda::array< long, 2 > dims
bool matrix_valued
Is the dispersion matrix-valued?
nda::array< double, 1 > k_weights
Weight in the BZ for each k-point.
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.
std::optional< ibz_symmetry_ops > ibz_symm_ops
IBZ symmetrizer after a k-sum.
local_space C_space
Local space.
band_dispersion H
Band dispersion.