7#include "./four_point.hpp"
10namespace triqs_ctseg::measures {
12 four_point::four_point(params_t
const &p, work_data_t
const &wdata, configuration_t
const &config, results_t &results)
13 : wdata{wdata}, config{config}, results{results} {
16 n_w_bosonic = p.n_w_b_vertex;
17 n_w_fermionic = p.n_w_f_vertex;
18 measure_g2w = p.measure_g2w;
19 measure_g3w = p.measure_g3w;
20 mesh_bosonic = triqs::mesh::imfreq(beta, Boson , n_w_bosonic );
21 mesh_fermionic = triqs::mesh::imfreq(beta, Fermion, n_w_fermionic);
23 if (measure_g2w) g2w.resize(wdata.gf_struct.size());
24 if (measure_g3w) g3w.resize(wdata.gf_struct.size());
25 for (
auto const &[bl1_idx, bl1] : itertools::enumerate(wdata.gf_struct)) {
26 auto &[bl1_name, bl1_size] = bl1;
27 block_names.push_back(bl1_name);
28 if (measure_g2w) g2w[bl1_idx].resize(wdata.gf_struct.size());
29 if (measure_g3w) g3w[bl1_idx].resize(wdata.gf_struct.size());
30 for (
auto const &[bl2_idx, bl2] : itertools::enumerate(wdata.gf_struct)) {
31 auto &[bl2_name, bl2_size] = bl2;
33 g2w[bl1_idx][bl2_idx] = gf<prod<imfreq, imfreq>, tensor_valued<4>>(
34 { mesh_bosonic , mesh_fermionic },
35 make_shape(bl1_size, bl1_size, bl2_size, bl2_size));
36 g2w[bl1_idx][bl2_idx]() = 0;
39 g3w[bl1_idx][bl2_idx] = gf<prod<imfreq, imfreq, imfreq>, tensor_valued<4>>(
40 { mesh_bosonic , mesh_fermionic , mesh_fermionic },
41 make_shape(bl1_size, bl1_size, bl2_size, bl2_size));
42 g3w[bl1_idx][bl2_idx]() = 0;
51 void four_point::accumulate(
double s) {
53 LOG(
"\n ============ MEASURE FOUR-POINT CORRELATION FUNCTIONS ============ \n");
81 auto Mw = compute_Mw();
82 auto const &nb_blocks = wdata.gf_struct.size();
85 auto nw = compute_nw();
86 for (
auto const &b1 : range(nb_blocks)) {
87 for (
auto const &b2 : range(nb_blocks)) {
88 auto const &block_shape = g2w[b1][b2].target_shape();
89 for (
auto const &c : range(block_shape[2])) {
90 auto col = wdata.block_to_color(b2, c);
91 for (
auto const &a : range(block_shape[0])) {
92 for (
auto const &b : range(block_shape[1])) {
93 for (
auto const &w : mesh_bosonic) {
94 for (
auto const &nu1 : mesh_fermionic) {
95 g2w[b1][b2][w, nu1](a, b, c, c) -= s * Mw[b1][-nu1, nu1 + w](a, b) * nw[col][-w];
106 for (
auto const &b1 : range(nb_blocks)) {
107 for (
auto const &b2 : range(nb_blocks)) {
108 auto const &block_shape = g3w[b1][b2].target_shape();
109 for (
auto const &a : range(block_shape[0])) {
110 for (
auto const &b : range(block_shape[1])) {
111 for (
auto const &c : range(block_shape[2])) {
112 for (
auto const &d : range(block_shape[3])) {
113 for (
auto const &nu1 : mesh_fermionic) {
114 for (
auto const &nu2 : mesh_fermionic) {
115 for (
auto const &w : mesh_bosonic) {
116 g3w[b1][b2][w, nu1, nu2](a, b, c, d) += s *
117 Mw[b1][-nu1, nu1 + w](a, b) * Mw[b2][-nu2 - w, nu2.value()](c, d);
119 g3w[b1][b2][w, nu1, nu2](a, b, c, d) -= s *
120 Mw[b1][-nu1, nu2.value()](a, d) * Mw[b2][-nu2 - w, nu1 + w](c, b);
136 void four_point::collect_results(mpi::communicator
const &c) {
138 Z = mpi::all_reduce(Z, c);
140 if (measure_g2w) g2w = mpi::all_reduce(g2w, c);
141 if (measure_g3w) g3w = mpi::all_reduce(g3w, c);
142 for (
auto const &b1 : range(wdata.gf_struct.size())) {
143 for (
auto const &b2 : range(wdata.gf_struct.size())) {
144 if (measure_g2w) g2w[b1][b2] = g2w[b1][b2] / (Z * beta);
145 if (measure_g3w) g3w[b1][b2] = g3w[b1][b2] / (Z * beta);
150 g2w_block = make_block2_gf(block_names, block_names, g2w);
151 results.g2w = std::move(g2w_block);
154 g3w_block = make_block2_gf(block_names, block_names, g3w);
155 results.g3w = std::move(g3w_block);
162 block_gf<prod<imfreq, imfreq>> four_point::compute_Mw() {
167 int n_w_aux = n_w_fermionic + n_w_bosonic - 1;
168 auto aux_mesh = triqs::mesh::imfreq(beta, Fermion, n_w_aux);
169 auto Mw = block_gf(prod(aux_mesh, aux_mesh), wdata.gf_struct);
172 auto w0 = aux_mesh[0].value();
173 auto dw = aux_mesh[1].value() - aux_mesh[0].value();
175 for (
auto const &[bl, det] : itertools::enumerate(wdata.dets)) {
177 for (
long i : range(N)) {
178 auto [tau_i, a] = det.get_x(i);
179 for (
long j : range(N)) {
180 auto [tau_j, b] = det.get_y(j);
181 auto Mij = det.inverse_matrix(j, i);
182 auto exp_i = std::exp(w0 *
double(tau_i));
183 auto exp_i_dw = std::exp(dw *
double(tau_i));
184 auto exp_j0 = std::exp(w0 *
double(tau_j));
185 auto exp_j_dw = std::exp(dw *
double(tau_j));
187 for (
auto const &nu1 : aux_mesh) {
189 auto expMij = exp_i * Mij;
190 for (
auto const &nu2 : aux_mesh) {
191 Mw[bl][nu1, nu2](a, b) += expMij * exp_j;
192 exp_j = exp_j * exp_j_dw;
194 exp_i = exp_i * exp_i_dw;
205 std::vector<gf<imfreq, scalar_valued>> four_point::compute_nw() {
212 std::vector<gf<imfreq, scalar_valued>> nw;
213 nw.resize(wdata.n_color);
214 for (
auto const &c : range(wdata.n_color)) {
215 nw[c] = gf<imfreq, scalar_valued>(mesh_bosonic);
219 for (
auto const &s: config.seglists[c]) {
221 double tau_c = double(s.tau_c);
222 double tau_cdag = double(s.tau_cdag);
225 nw[c][0] += double(s.length());
228 for (
auto const &w : mesh_bosonic) {
229 if (w.n == 0)
continue;
230 nw[c][w] += (std::exp(w.value() * tau_c) - std::exp(w.value() * tau_cdag)) / w.value();