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#include <iostream>
8#include <atomic>
9#include <stdexcept>
10
11namespace triqs::modest {
12
13 namespace detail {
14
15 // Upfold self-energy for ALL frequencies at once for a given (k, sigma)
16 // Returns array of shape (n_w, N_nu, N_nu)
17 auto upfold_self_energy_all_freq(one_body_elements_on_grid const &obe, downfolding_projector const &Proj, auto const &Sigma_w, long k_idx,
18 long sigma_idx) {
19 auto N_nu = obe.H.N_nu(sigma_idx, k_idx);
20 auto n_w = Sigma_w(0, 0).mesh().size();
21 auto out = nda::zeros<dcomplex>(n_w, N_nu, N_nu);
22
23 for (auto &&[alpha, R] : enumerated_sub_slices(get_struct(Sigma_w).dims(r_all, 0) | tl::to<std::vector>())) {
24 auto P = Proj.P(sigma_idx, k_idx)(R, r_all);
25 auto Pdag = dagger(P);
26 auto Sigma_blk = Sigma_w(alpha, sigma_idx).data();
27
28 // Batch over all frequencies
29 for (auto n : range(n_w)) { out(n, r_all, r_all) += Pdag * nda::matrix<dcomplex>{Sigma_blk(n, r_all, r_all)} * P; }
30 }
31 return out;
32 }
33
34 } // namespace detail
35
37 block2_gf<mesh::refreq, matrix_valued> const &Sigma_w, double broadening) {
38 using nda::linalg::inv;
39
40 auto const &mesh = Sigma_w(0, 0).mesh();
41 auto n_sigma = obe_theta.C_space.n_sigma();
42 auto n_k = obe_theta.H.n_k();
43 auto n_M = obe_theta.C_space.dim();
44 auto n_w = mesh.size();
45
46 // Accumulate local Green's function over k-points
47 auto gloc_result = make_block2_gf(mesh, obe_theta.C_space.Gc_block_shape());
48
49 for (auto k_idx : range(n_k)) {
50 for (auto sigma : range(n_sigma)) {
51 auto P = Proj.P(sigma, k_idx);
52 auto Pdag = dagger(P);
53 auto H_k = obe_theta.H.H(sigma, k_idx);
54 auto w_k = obe_theta.H.k_weights(k_idx);
55
56 // Precompute upfolded self-energy for all frequencies
57 auto PSP_all = detail::upfold_self_energy_all_freq(obe_theta, Proj, Sigma_w, k_idx, sigma);
58
59 for (auto &&[n, w] : enumerate(mesh)) {
60 auto G_k = inv(w + dcomplex(0, broadening) + mu - H_k - PSP_all(n, r_all, r_all));
61 gloc_result(0, sigma).data()(n, r_all, r_all) += w_k * (P * nda::matrix<dcomplex>{G_k} * Pdag);
62 }
63 }
64 }
65
66 if (auto const &S = obe_theta.ibz_symm_ops; S) { gloc_result = S->symmetrize(gloc_result, obe_theta.C_space.atomic_decomposition()); }
67
68 // Extract spectral functions from local Green's function
69 auto total = nda::array<double, 2>(n_sigma, n_w);
70 auto per_theta = nda::array<double, 4>(n_sigma, n_w, n_M, n_M);
71
72 for (auto sigma : range(n_sigma)) {
73 auto g = gloc_result(0, sigma).data();
74 auto gC = conj(gloc_result(0, sigma)).data();
75 for (auto &&[n, w] : enumerate(mesh)) {
76 total(sigma, n) = (-1.0 / M_PI) * imag(trace(g(n, r_all, r_all)));
77 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));
78 }
79 }
80 return {.total = total, .per_theta = per_theta};
81 }
82
83 nda::array<double, 4> spectral_function(one_body_elements_on_grid const &obe, double mu, block2_gf<mesh::refreq, matrix_valued> const &Sigma_w,
84 double broadening) {
85 using nda::linalg::inv;
86
87 auto const &mesh = Sigma_w(0, 0).mesh() | tl::to<std::vector>();
88 auto n_sigma = obe.C_space.n_sigma();
89 auto n_k = obe.H.n_k();
90 auto n_w = mesh.size();
91 auto n_bands = obe.H.N_nu(0, 0);
92 auto delta = dcomplex(0, broadening);
93
94 for (auto sigma : range(n_sigma)) {
95 for (auto k_idx : range(n_k)) {
96 if (obe.H.N_nu(sigma, k_idx) != n_bands)
97 throw std::runtime_error("spectral_function requires a fixed number of bands over all k and spin blocks");
98 }
99 }
100
101 auto data = nda::zeros<double>(n_sigma, n_w, n_bands, n_bands);
102
103 for (auto k_idx : range(n_k)) {
104 for (auto sigma : range(n_sigma)) {
105 auto H_k = obe.H.H(sigma, k_idx);
106 auto k_weight = obe.H.k_weights(k_idx);
107
108 auto PSP_all = detail::upfold_self_energy_all_freq(obe, obe.P, Sigma_w, k_idx, sigma);
109
110 for (auto &&[n, w] : enumerate(mesh)) {
111 auto G_k = inv(w + delta + mu - H_k - PSP_all(n, r_all, r_all));
112 auto A_k = real(dcomplex(0, 1.0) * (G_k - dagger(G_k)) / (2.0 * M_PI));
113 data(sigma, n, r_all, r_all) += k_weight * A_k;
114 }
115 }
116 }
117
118 return data;
119 }
120
122 block2_gf<mesh::refreq, matrix_valued> const &Sigma_w, double broadening) {
123 using nda::linalg::inv;
124
125 auto const &mesh = Sigma_w(0, 0).mesh() | tl::to<std::vector>();
126 auto n_sigma = obe.C_space.n_sigma();
127 auto n_w = mesh.size();
128 auto n_k = obe.H.n_k();
129 auto n_M = obe.C_space.dim();
130 auto delta = dcomplex(0, broadening);
131
132 auto data = nda::array<double, 3>(n_sigma, n_k, n_w);
133 auto proj_data = nda::array<double, 5>(n_sigma, n_k, n_w, n_M, n_M);
134
135#pragma omp parallel for default(none) shared(n_k, n_sigma, n_w, obe, mu, delta, Sigma_w, broadening, mesh, data, proj_data, r_all)
136 for (auto k_idx : range(n_k)) {
137 for (auto sigma : range(n_sigma)) {
138 auto P = obe.P.P(sigma, k_idx);
139 auto Pdag = dagger(P);
140 auto H_k = obe.H.H(sigma, k_idx);
141
142 // Precompute upfolded self-energy for all frequencies
143 auto PSP_all = detail::upfold_self_energy_all_freq(obe, obe.P, Sigma_w, k_idx, sigma);
144
145 for (auto &&[n, w] : enumerate(mesh)) {
146 auto G_k = inv(w + delta + mu - H_k - PSP_all(n, r_all, r_all));
147
148 // Total spectral function from trace
149 data(sigma, k_idx, n) = (-1.0 / M_PI) * imag(trace(G_k));
150
151 // Orbital-resolved from projection
152 auto PGP = P * nda::matrix<dcomplex>{G_k} * Pdag;
153 proj_data(sigma, k_idx, n, r_all, r_all) = (-1.0 / M_PI) * imag(PGP);
154 }
155 }
156 }
157
158 return {.data = data, .proj_data = proj_data};
159 }
160
161} // 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.
nda::array< double, 4 > spectral_function(one_body_elements_on_grid const &obe, double mu, block2_gf< mesh::refreq, matrix_valued > const &Sigma_w, double broadening)
Compute the k-summed band-resolved spectral function matrix.
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.
long N_nu(long sigma, long k_idx) const
Number of bands for a given k-point and spin .
nda::matrix_const_view< dcomplex > H(long sigma, long k_idx) const
Get for a given and .
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.