TRIQS/triqs_modest 3.3.0
Modular Electronic Structure Toolkit
Loading...
Searching...
No Matches
postprocess.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 "./postprocess.hpp"
7
8namespace triqs::modest {
9
10 namespace detail {
11
12 constexpr auto upfold_self_energy_at_freq(one_body_elements_on_grid const &obe, downfolding_projector const &Proj, auto const &Sigma_w,
13 long w_idx, long k_idx, long sigma_idx) {
14 auto N_nu = obe.H.N_nu(sigma_idx, k_idx);
15 auto out = nda::zeros<dcomplex>(N_nu, N_nu);
16 for (auto &&[alpha, R] : enumerated_sub_slices(get_struct(Sigma_w).dims(r_all, 0) | tl::to<std::vector>())) {
17 auto P = Proj.P(sigma_idx, k_idx)(R, r_all);
18 out(r_all, r_all) += dagger(P) * nda::matrix<dcomplex>{Sigma_w(alpha, sigma_idx).data()(w_idx, r_all, r_all)} * P;
19 }
20 return out;
21 }
22
23 template <bool Trace>
24 constexpr auto lattice_gf_at_k(auto const &mesh, one_body_elements_on_grid const &obe, downfolding_projector const &Proj, double mu,
25 auto const &Sigma_w, dcomplex broadening) {
26 return [&, mu, broadening](auto &k_idx, auto &sigma) {
27 using nda::linalg::inv;
28 if constexpr (Trace) {
29 auto out = gf{mesh};
30 for (auto &&[n, w] : enumerate(mesh)) {
31 auto PSP = upfold_self_energy_at_freq(obe, Proj, Sigma_w, n, k_idx, sigma);
32 out.data()(n) = trace(inv(w + broadening + mu - obe.H.H(sigma, k_idx) - PSP));
33 }
34 return out;
35 } else {
36 auto N_nu = obe.H.N_nu(sigma, k_idx);
37 auto out = gf{mesh, {N_nu, N_nu}};
38 for (auto &&[n, w] : enumerate(mesh)) {
39 auto PSP = upfold_self_energy_at_freq(obe, Proj, Sigma_w, n, k_idx, sigma);
40 out.data()(n, r_all, r_all) = inv(w + broadening + mu - obe.H.H(sigma, k_idx) - PSP);
41 }
42 return out;
43 }
44 };
45 }
46
47 constexpr auto local_gf_at_k(auto const &mesh, one_body_elements_on_grid const &obe, downfolding_projector const &Proj, double mu,
48 auto const &Sigma_w, dcomplex broadening) {
49 return [&, mu, broadening](auto &k_idx, auto &sigma) {
50 using nda::linalg::inv;
51 auto n_M = obe.C_space.dim();
52 auto out = gf{mesh, {n_M, n_M}};
53 auto P = obe.P.P(sigma, k_idx);
54 for (auto &&[n, w] : enumerate(mesh)) {
55 auto PSP = upfold_self_energy_at_freq(obe, Proj, Sigma_w, n, k_idx, sigma);
56 out.data()(n, r_all, r_all) = P * inv(w + broadening + mu - obe.H.H(sigma, k_idx) - PSP) * dagger(P);
57 }
58 return out;
59 };
60 }
61
62 } // namespace detail
63
65 block2_gf<mesh::refreq, matrix_valued> const &Sigma_w, double broadening) {
66
67 auto const &mesh = Sigma_w(0, 0).mesh();
68
69 auto n_sigma = obe_theta.C_space.n_sigma();
70 auto n_k = obe_theta.H.n_k();
71
72 auto gloc_at_k = detail::local_gf_at_k(mesh, obe_theta, Proj, mu, Sigma_w, dcomplex(0, broadening));
73
74 auto gloc_result = make_block2_gf(mesh, obe_theta.C_space.Gc_block_shape());
75
76 for (auto const &k_idx : range(n_k)) {
77 for (auto const &sigma : range(n_sigma)) {
78 gloc_result(0, sigma).data()(r_all, r_all, r_all) += obe_theta.H.k_weights(k_idx) * gloc_at_k(k_idx, sigma).data();
79 }
80 }
81
82 gloc_result = mpi::all_reduce(gloc_result);
83
84 if (auto const &S = obe_theta.ibz_symm_ops; S) { gloc_result = S->symmetrize(gloc_result, obe_theta.C_space.atomic_decomposition()); }
85
86 auto n_M = obe_theta.C_space.dim();
87 auto n_w = mesh.size();
88
89 auto total = nda::array<double, 2>(n_sigma, n_w);
90 auto per_theta = nda::array<double, 4>(n_sigma, n_w, n_M, n_M);
91
92 for (auto const &sigma : nda::range(n_sigma)) {
93 auto g = gloc_result(0, sigma).data();
94 auto gC = conj(gloc_result(0, sigma)).data();
95 for (auto [n, w] : enumerate(mesh)) {
96 // auto g = gloc_result(0, sigma).data()(n, r_all, r_all);
97 //FIXME: can trace ignore the mesh dimension (or in general the first axis dimension and broadcast over all the w-mesh points)
98 total(sigma, n) = (-1.0 / M_PI) * imag(trace(g(n, r_all, r_all)));
99 // missing sign?
100 per_theta(sigma, n, r_all, r_all) = real(dcomplex(0, 1.0) * (g(n, r_all, r_all) - transpose(gC(n, r_all, r_all))) / (2.0 * M_PI));
101 }
102 }
103 return {.total = total, .per_theta = per_theta};
104 }
105
107 block2_gf<mesh::refreq, matrix_valued> const &Sigma_w, double broadening) {
108 auto const &mesh = Sigma_w(0, 0).mesh();
109 auto n_sigma = obe.C_space.n_sigma();
110 auto n_w = mesh.size();
111 auto n_k = obe.H.n_k();
112 auto n_M = obe.C_space.dim();
113
114 auto data = nda::array<double, 3>(n_sigma, n_k, n_w);
115 auto proj_data = nda::array<double, 5>(n_sigma, n_k, n_w, n_M, n_M);
116
117 auto trglatt_at_k = detail::lattice_gf_at_k<true>(mesh, obe, obe.P, mu, Sigma_w, broadening);
118 auto glatt_at_k = detail::lattice_gf_at_k<false>(mesh, obe, obe.P, mu, Sigma_w, broadening);
119
120 for (auto k_idx : range(n_k)) {
121 for (auto sigma : range(n_sigma)) {
122 data(sigma, k_idx, r_all) = (-1.0 / M_PI) * imag(trglatt_at_k(k_idx, sigma).data());
123 auto P = obe.P.P(sigma, k_idx);
124
125 for (auto n : range(n_w)) {
126 auto PGP = P * nda::matrix<dcomplex>{glatt_at_k(k_idx, sigma).data()(n, r_all, r_all)} * dagger(P);
127 proj_data(sigma, k_idx, n, r_all, r_all) = (-1.0 / M_PI) * imag(PGP);
128 }
129 }
130 }
131 return {.data = data, .proj_data = proj_data};
132 }
133
134} // namespace triqs::modest
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.
spectral_function_w projected_spectral_function(one_body_elements_on_grid const &obe_theta, downfolding_projector const &Proj, double mu, block2_gf< mesh::refreq, matrix_valued > const &Sigma_w, double broadening)
Compute the atom- and orbital-resolved spectral function (interacting density of states).
spectral_function_kw spectral_function_on_high_symmetry_path(one_body_elements_on_grid const &obe, double mu, block2_gf< mesh::refreq, matrix_valued > const &Sigma_w, double broadening)
Compute momentum-resolved spectral function along high-symmetry path.
gf_struct2_t get_struct(block2_gf< Mesh, matrix_valued > const &g)
Definition gf_supp.hpp:52
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
Definition gf_supp.hpp:41
static constexpr auto r_all
Definition defs.hpp:40
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
std::complex< double > dcomplex
Definition nda_supp.hpp:8
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.
The projector that downfolds the energy bands onto a set of localized atomic-like orbitals.
nda::matrix_const_view< dcomplex > P(long sigma, long k_idx) const
Get for a given and .
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.
band_dispersion H
Band dispersion.
downfolding_projector P
Downfolding projector .
Returns Tr (A) [σ,k,ω] for all k points in obe grid and all omega in Sigma mesh.
Store data of spectral functions.