9#include <triqs/mesh.hpp>
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)))
22 template <
typename Mesh>
23 constexpr auto upfold_self_energy_at_freq(one_body_elements_on_grid
const &obe, downfolding_projector
const &Proj,
24 block2_gf<Mesh, matrix_valued>
const &Sigma_dynamic,
25 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static,
long w_idx,
long k_idx,
long sigma_idx) {
26 auto N_nu = obe.H.N_nu(sigma_idx, k_idx);
27 auto out = nda::zeros<dcomplex>(N_nu, N_nu);
29 auto P = Proj.P(sigma_idx, k_idx)(R,
r_all);
31 dagger(P) * nda::matrix<dcomplex>{Sigma_dynamic(alpha, sigma_idx).data()(w_idx,
r_all,
r_all) + Sigma_static(alpha, sigma_idx)} * P;
37 template <
typename Mesh>
38 constexpr auto local_gf_at_k(one_body_elements_on_grid
const &obe,
double const &mu, downfolding_projector
const &Proj,
39 block2_gf<Mesh, matrix_valued>
const &Sigma_dynamic, nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static) {
40 return [&](
auto const &k_idx,
auto const &sigma_idx) {
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 * inverse(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 auto const &mesh = Sigma_dynamic(0, 0).mesh();
58 auto N_nu = obe.H.N_nu(sigma_idx, k_idx);
59 auto Glatt = gf{mesh, {N_nu, N_nu}};
60 for (
auto &&[n, w] : enumerate(mesh)) {
61 auto PSP = upfold_self_energy_at_freq(obe, obe.P, Sigma_dynamic, Sigma_static, n, k_idx, sigma_idx);
62 Glatt.data()(n,
r_all,
r_all) = inverse(w + mu - obe.H.H(sigma_idx, k_idx) - PSP);
80 template <
typename Mesh>
81 block2_gf<Mesh, matrix_valued> gloc_for_matrix_valued_dispersion_impl(one_body_elements_on_grid
const &obe,
double mu,
82 block2_gf<Mesh, matrix_valued>
const &Sigma_dynamic,
83 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static) {
85 auto n_sigma = obe.C_space.n_sigma();
86 auto n_kpts = long(obe.H.n_k());
88 auto gloc_k = detail::local_gf_at_k(obe, mu, obe.P, Sigma_dynamic, Sigma_static);
89 auto gloc_result =
make_block2_gf(Sigma_dynamic(0, 0).mesh(), obe.C_space.Gc_block_shape());
91 mpi::communicator comm = {};
92#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)
93 for (
auto k_idx : mpi::chunk(range(n_kpts), comm)) {
94 for (
auto sigma : range(n_sigma)) {
95 auto P = obe.P.P(sigma, k_idx);
96 gloc_result(0, sigma).data()(
r_all,
r_all,
r_all) += obe.H.k_weights(k_idx) * gloc_k(k_idx, sigma).data();
100 gloc_result = mpi::all_reduce(gloc_result);
102 if (
auto const &S = obe.ibz_symm_ops; S) { gloc_result = S->symmetrize(gloc_result, obe.C_space.atomic_decomposition()); }
138 template <
typename Mesh>
140 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static) {
143 if (obe.
H.
matrix_valued)
return gloc_for_matrix_valued_dispersion_impl(obe, mu, Sigma_dynamic, Sigma_static);
145 auto n_sigma = Sigma_dynamic.size2();
147 auto n_kpts = long(obe.
H.
n_k());
148 auto const &mesh = Sigma_dynamic(0, 0).mesh();
150 auto omegas = mesh | tl::to<std::vector<dcomplex>>();
153 auto embedding_decomp =
get_struct(Sigma_dynamic).dims(
r_all, 0) | tl::to<std::vector>();
159 mpi::communicator comm = {};
160#pragma omp parallel for collapse(2) reduction(block2_gf_sum : gloc_result) default(none) \
161 shared(comm, r_all, n_kpts, n_sigma, obe, mu, omegas, mesh, M, embedding_decomp, Sigma_dynamic, Sigma_static)
162 for (
auto k_idx : mpi::chunk(range(n_kpts), comm)) {
163 for (
auto sigma : range(n_sigma)) {
164 auto Y = detail::G0_C_k_sigma(obe, mu, k_idx, sigma, omegas,
false);
165 for (
auto &&[n, om] : itertools::enumerate(mesh)) {
167 auto B = detail::calc_inv_G_G0(M, embedding_decomp, Sigma_dynamic, Sigma_static, om, sigma, Y1, Y1);
173 gloc_result = mpi::all_reduce(gloc_result);
195 auto Sigma_static = nda::array<nda::matrix<dcomplex>, 2>(1, obe.
C_space.
n_sigma());
196 for (
auto [i, j] : Sigma_static.indices()) { Sigma_static(i, j) = nda::zeros<dcomplex>(obe.
C_space.
dim(), obe.
C_space.
dim()); }
197 return gloc(obe, mu, Sigma_dynamic, Sigma_static);
212 template <
typename Mesh>
213 block_gf<Mesh, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels, block_gf<Mesh, matrix_valued>
const &Gloc,
214 block_gf<Mesh, matrix_valued>
const &Sigma_dynamic,
215 std::vector<nda::matrix<dcomplex>>
const &Sigma_static) {
217 auto mesh = Gloc[0].mesh();
218 auto Delta = block_gf{mesh, gf_struct};
219 auto n_blocks = gf_struct.size();
220 for (
auto bl : range(n_blocks)) {
221 for (
auto &&[n, w] : enumerate(mesh))
223 (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]));
237 template <
typename Mesh>
238 block_gf<Mesh, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels, block_gf<Mesh, matrix_valued>
const &Gloc) {
239 auto Sigma_static =
get_struct(Gloc) | stdv::transform([](
auto &x) {
return nda::zeros<dcomplex>(x.second, x.second); })
240 | tl::to<std::vector<nda::matrix<dcomplex>>>();
241 auto Sigma_dynamic = block_gf{Gloc[0].mesh(),
get_struct(Gloc)};
242 return hybridization(epsilon_levels, Gloc, Sigma_dynamic, Sigma_static);
248 block2_gf<imfreq, matrix_valued>
const &Sigma_dynamic,
249 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static);
252 block2_gf<dlr_imfreq, matrix_valued>
const &Sigma_dynamic,
253 nda::array<nda::matrix<dcomplex>, 2>
const &Sigma_static);
255 template block_gf<imfreq, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels,
256 block_gf<imfreq, matrix_valued>
const &Gloc);
257 template block_gf<imfreq, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels,
258 block_gf<imfreq, matrix_valued>
const &Gloc,
259 block_gf<imfreq, matrix_valued>
const &Sigma_dynamic,
260 std::vector<nda::matrix<dcomplex>>
const &Sigma_static);
261 template block_gf<dlr_imfreq, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels,
262 block_gf<dlr_imfreq, matrix_valued>
const &Gloc);
263 template block_gf<dlr_imfreq, matrix_valued>
hybridization(std::vector<nda::matrix<dcomplex>>
const &epsilon_levels,
264 block_gf<dlr_imfreq, matrix_valued>
const &Gloc,
265 block_gf<dlr_imfreq, matrix_valued>
const &Sigma_dynamic,
266 std::vector<nda::matrix<dcomplex>>
const &Sigma_static);
long n_sigma() const
Dimension of the index.
auto atomic_decomposition() const
Transformed view containing the dimension of each 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 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,...
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
gf_struct_t get_struct(block_gf< Mesh > const &g)
static constexpr auto r_all
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
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.
local_space C_space
Local space.
band_dispersion H
Band dispersion.
C2PY_IGNORE std::optional< ibz_symmetry_ops > ibz_symm_ops
IBZ symmetrizer after a k-sum.