7#include "./four_point.hpp"
9#include <triqs/utility/exceptions.hpp>
11namespace triqs_ctseg::measures {
13 four_point::four_point(params_t
const &p, work_data_t
const &wdata, configuration_t
const &config, results_t &results)
14 : wdata{wdata}, config{config}, results{results} {
17 n_w_bosonic = p.n_w_b_vertex;
18 n_w_fermionic = p.n_w_f_vertex;
19 measure_g2w = p.measure_g2w;
20 measure_g3w = p.measure_g3w;
21 mesh_bosonic = triqs::mesh::imfreq(beta, Boson , n_w_bosonic );
22 mesh_fermionic = triqs::mesh::imfreq(beta, Fermion, n_w_fermionic);
25 if (p.length_cycle_g3 <= 0 or p.length_cycle_g3 % p.length_cycle != 0)
26 TRIQS_RUNTIME_ERROR <<
"length_cycle_g3 = " << p.length_cycle_g3
27 <<
" must be a positive multiple of length_cycle = " << p.length_cycle;
28 g3w_interval = p.length_cycle_g3 / p.length_cycle;
31 if (measure_g2w) g2w.resize(wdata.gf_struct.size());
32 if (measure_g3w) g3w.resize(wdata.gf_struct.size());
33 for (
auto const &[bl1_idx, bl1] : itertools::enumerate(wdata.gf_struct)) {
34 auto &[bl1_name, bl1_size] = bl1;
35 block_names.push_back(bl1_name);
36 if (measure_g2w) g2w[bl1_idx].resize(wdata.gf_struct.size());
37 if (measure_g3w) g3w[bl1_idx].resize(wdata.gf_struct.size());
38 for (
auto const &[bl2_idx, bl2] : itertools::enumerate(wdata.gf_struct)) {
39 auto &[bl2_name, bl2_size] = bl2;
41 g2w[bl1_idx][bl2_idx] = gf<prod<imfreq, imfreq>, tensor_valued<4>>(
42 { mesh_bosonic , mesh_fermionic },
43 make_shape(bl1_size, bl1_size, bl2_size, bl2_size));
44 g2w[bl1_idx][bl2_idx]() = 0;
47 g3w[bl1_idx][bl2_idx] = gf<prod<imfreq, imfreq, imfreq>, tensor_valued<4>>(
48 { mesh_bosonic , mesh_fermionic , mesh_fermionic },
49 make_shape(bl1_size, bl1_size, bl2_size, bl2_size));
50 g3w[bl1_idx][bl2_idx]() = 0;
59 void four_point::accumulate(
double s) {
61 LOG(
"\n ============ MEASURE FOUR-POINT CORRELATION FUNCTIONS ============ \n");
91 bool const accumulate_g3w = measure_g3w and (n_cycles_done % g3w_interval == 0);
93 if (not measure_g2w and not accumulate_g3w)
return;
95 auto Mw = compute_Mw();
96 auto const &nb_blocks = wdata.gf_struct.size();
99 auto nw = compute_nw();
100 for (
auto const &b1 : range(nb_blocks)) {
101 for (
auto const &b2 : range(nb_blocks)) {
102 auto const &block_shape = g2w[b1][b2].target_shape();
103 for (
auto const &c : range(block_shape[2])) {
104 auto col = wdata.block_to_color(b2, c);
105 for (
auto const &a : range(block_shape[0])) {
106 for (
auto const &b : range(block_shape[1])) {
107 for (
auto const &w : mesh_bosonic) {
108 for (
auto const &nu1 : mesh_fermionic) {
109 g2w[b1][b2][w, nu1](a, b, c, c) -= s * Mw[b1][-nu1, nu1 + w](a, b) * nw[col][-w];
119 if (accumulate_g3w) {
121 for (
auto const &b1 : range(nb_blocks)) {
122 for (
auto const &b2 : range(nb_blocks)) {
123 auto const &block_shape = g3w[b1][b2].target_shape();
124 for (
auto const &a : range(block_shape[0])) {
125 for (
auto const &b : range(block_shape[1])) {
126 for (
auto const &c : range(block_shape[2])) {
127 for (
auto const &d : range(block_shape[3])) {
128 for (
auto const &nu1 : mesh_fermionic) {
129 for (
auto const &nu2 : mesh_fermionic) {
130 for (
auto const &w : mesh_bosonic) {
131 g3w[b1][b2][w, nu1, nu2](a, b, c, d) += s *
132 Mw[b1][-nu1, nu1 + w](a, b) * Mw[b2][-nu2 - w, nu2.value()](c, d);
134 g3w[b1][b2][w, nu1, nu2](a, b, c, d) -= s *
135 Mw[b1][-nu1, nu2.value()](a, d) * Mw[b2][-nu2 - w, nu1 + w](c, b);
151 void four_point::collect_results(mpi::communicator
const &c) {
153 Z = mpi::all_reduce(Z, c);
154 Z_g3w = mpi::all_reduce(Z_g3w, c);
156 if (measure_g2w) g2w = mpi::all_reduce(g2w, c);
157 if (measure_g3w) g3w = mpi::all_reduce(g3w, c);
158 for (
auto const &b1 : range(wdata.gf_struct.size())) {
159 for (
auto const &b2 : range(wdata.gf_struct.size())) {
160 if (measure_g2w) g2w[b1][b2] = g2w[b1][b2] / (Z * beta);
161 if (measure_g3w) g3w[b1][b2] = g3w[b1][b2] / (Z_g3w * beta);
166 g2w_block = make_block2_gf(block_names, block_names, g2w);
167 results.g2w = std::move(g2w_block);
170 g3w_block = make_block2_gf(block_names, block_names, g3w);
171 results.g3w = std::move(g3w_block);
178 block_gf<prod<imfreq, imfreq>> four_point::compute_Mw() {
183 int n_w_aux = n_w_fermionic + n_w_bosonic - 1;
184 auto aux_mesh = triqs::mesh::imfreq(beta, Fermion, n_w_aux);
185 auto Mw = block_gf(prod(aux_mesh, aux_mesh), wdata.gf_struct);
188 auto w0 = aux_mesh[0].value();
189 auto dw = aux_mesh[1].value() - aux_mesh[0].value();
191 for (
auto const &[bl, det] : itertools::enumerate(wdata.dets)) {
193 for (
long i : range(N)) {
194 auto [tau_i, a] = det.get_x(i);
195 for (
long j : range(N)) {
196 auto [tau_j, b] = det.get_y(j);
197 auto Mij = det.inverse_matrix(j, i);
198 auto exp_i = std::exp(w0 *
double(tau_i));
199 auto exp_i_dw = std::exp(dw *
double(tau_i));
200 auto exp_j0 = std::exp(w0 *
double(tau_j));
201 auto exp_j_dw = std::exp(dw *
double(tau_j));
203 for (
auto const &nu1 : aux_mesh) {
205 auto expMij = exp_i * Mij;
206 for (
auto const &nu2 : aux_mesh) {
207 Mw[bl][nu1, nu2](a, b) += expMij * exp_j;
208 exp_j = exp_j * exp_j_dw;
210 exp_i = exp_i * exp_i_dw;
221 std::vector<gf<imfreq, scalar_valued>> four_point::compute_nw() {
228 std::vector<gf<imfreq, scalar_valued>> nw;
229 nw.resize(wdata.n_color);
230 for (
auto const &c : range(wdata.n_color)) {
231 nw[c] = gf<imfreq, scalar_valued>(mesh_bosonic);
235 for (
auto const &s: config.seglists[c]) {
237 double tau_c = double(s.tau_c);
238 double tau_cdag = double(s.tau_cdag);
241 nw[c][0] += double(s.length());
244 for (
auto const &w : mesh_bosonic) {
245 if (w.n == 0)
continue;
246 nw[c][w] += (std::exp(w.value() * tau_c) - std::exp(w.value() * tau_cdag)) / w.value();