TRIQS/triqs_ctint 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
M3pp_tau.cpp
1// Copyright (c) 2017--present, The Simons Foundation
2// This file is part of TRIQS/ctint 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 "./M3pp_tau.hpp"
7
8namespace triqs_ctint::measures {
9
10 M3pp_tau::M3pp_tau(params_t const &params_, qmc_config_t const &qmc_config_, container_set *results, g_tau_cv_t G0_tau_)
11 : params(params_), qmc_config(qmc_config_), G0_tau(std::move(G0_tau_)), tau_mesh{params_.beta, Fermion, params_.n_tau_M3} {
12
13 // Construct Matsubara mesh
14 mesh::prod<imtime, imtime> M3pp_tau_mesh{tau_mesh, tau_mesh};
15
16 // Init measurement container and capture view
17 results->M3pp_tau = make_block2_gf(M3pp_tau_mesh, params.gf_struct);
18 M3pp_tau_.rebind(results->M3pp_tau.value());
19 M3pp_tau_() = 0;
20
21 // Init measurement container for equal-time component of M3pp
22 auto mesh_b = mesh::imtime({params.beta, Boson, params.n_tau});
23 results->M3pp_delta = make_block2_gf(mesh_b, params.gf_struct);
24 M3pp_delta_.rebind(*results->M3pp_delta);
25 M3pp_delta_() = 0;
26 }
27
28 void M3pp_tau::accumulate(mc_weight_t sign) {
29 // Accumulate sign
30 Z += sign;
31
32 // Vectors containing the binned tau-values vec[bl][i]
33 std::vector<std::vector<idx_t>> c_vec, cdag_vec;
34
35 // The two tau meshes in one dimension
36 auto const &G0_tau_mesh = G0_tau[0].mesh();
37 auto const &M_tau_mesh = tau_mesh;
38
39 // Precompute binned tau-points
40 for (auto &det : qmc_config.dets) {
41
42 // Consider shifted time here as need in fourier transform (for the transform of unbarred index of M)
43 auto x_to_mesh = [beta = params.beta, &M_tau_mesh](c_t const &c_i) {
44 return idx_t{M_tau_mesh.to_index(closest_mesh_pt(beta - double(c_i.tau))), c_i.u, c_i.tau};
45 };
46
47 auto y_to_mesh = [beta = params.beta, &G0_tau_mesh](cdag_t const &cdag_j) {
48 return idx_t{G0_tau_mesh.to_index(closest_mesh_pt(beta - double(cdag_j.tau))), cdag_j.u, cdag_j.tau};
49 };
50
51 // Careful: Use the row and column indices of the matrix in their internal storage order
52 c_vec.push_back(make_vector_from_range(transform(det.get_x_internal_order(), x_to_mesh)));
53 cdag_vec.push_back(make_vector_from_range(transform(det.get_y_internal_order(), y_to_mesh)));
54 }
55
56 // The intermediate scattering matrix
57 std::vector<matrix<dcomplex>> GM_vec(params.n_blocks()); // GM_vec[bl](u, i)
58
59 // Calculate intermediate scattering matrix
60 for (int bl : range(params.n_blocks())) {
61
62 auto const &det = qmc_config.dets[bl];
63 int det_size = det.size();
64
65 if (det.size() == 0) continue;
66
67 auto const &cdag = cdag_vec[bl];
68 int bl_size = G0_tau[bl].target_shape()[0];
69 auto G = matrix<dcomplex>(bl_size, det_size);
70
71 for (int b_u : range(bl_size))
72 for (int j : range(det_size)) G(b_u, j) = G0_tau[bl][cdag[j].tau_idx](b_u, cdag[j].u);
73
74 GM_vec[bl] = G * det.inverse_matrix_internal_order();
75 }
76
77 // Calculate M3pp
78 for (int bl1 : range(params.n_blocks())) {
79
80 int det1_size = qmc_config.dets[bl1].size();
81
82 // Do not consider empty blocks
83 if (det1_size == 0) continue;
84
85 auto const &GM1 = GM_vec[bl1];
86 auto const &c1 = c_vec[bl1];
87 int bl1_size = G0_tau[bl1].target_shape()[0];
88
89 // Crossing term (equal blocks)
90 auto &M3pp_tau = M3pp_tau_(bl1, bl1);
91 auto &M3pp_delta = M3pp_delta_(bl1, bl1);
92
93 for (auto [j, l, i, k] : product_range(bl1_size, bl1_size, det1_size, det1_size)) {
94 // Take care of equal-time peak separately
95 if (c1[i].tau_pt == c1[k].tau_pt) {
96 M3pp_delta[cdag_vec[bl1][i].tau_idx](c1[i].u, j, c1[k].u, l) += -sign * GM1(l, i) * GM1(j, k);
97 } else {
98 // Since the crossing term is negative by itself, we get a negative sign here
99 M3pp_tau[c1[i].tau_idx, c1[k].tau_idx](c1[i].u, j, c1[k].u, l) += -sign * GM1(l, i) * GM1(j, k);
100 }
101 }
102
103 for (int bl2 : range(params.n_blocks())) {
104
105 int det2_size = qmc_config.dets[bl2].size();
106
107 // Do not consider empty blocks
108 if (det2_size == 0) continue;
109
110 auto const &GM2 = GM_vec[bl2];
111 auto const &c2 = c_vec[bl2];
112 int bl2_size = G0_tau[bl2].target_shape()[0];
113 auto &M3pp_tau_bl = M3pp_tau_(bl1, bl2);
114 auto &M3pp_delta_bl = M3pp_delta_(bl1, bl2);
115
116 // Direct term
117 for (auto [j, l, i, k] : product_range(bl1_size, bl2_size, det1_size, det2_size)) {
118 // Take care of equal-time peak separately
119 if (c1[i].tau_pt == c2[k].tau_pt) {
120 M3pp_delta_bl[cdag_vec[bl1][i].tau_idx](c1[i].u, j, c2[k].u, l) += sign * GM1(j, i) * GM2(l, k);
121 } else {
122 M3pp_tau_bl[c1[i].tau_idx, c2[k].tau_idx](c1[i].u, j, c2[k].u, l) += sign * GM1(j, i) * GM2(l, k);
123 }
124 }
125 }
126 }
127 }
128
129 void M3pp_tau::collect_results(mpi::communicator const &comm) {
130 // Collect results and normalize
131 Z = mpi::all_reduce(Z, comm);
132 M3pp_tau_ = mpi::all_reduce(M3pp_tau_, comm);
133 M3pp_delta_ = mpi::all_reduce(M3pp_delta_, comm);
134
135 // Normalize
136 int n = params.n_tau_M3 - 1;
137 double dtau = params.beta / n;
138 M3pp_tau_ = M3pp_tau_ / (Z * dtau * dtau);
139
140 int n_del = params.n_tau - 1;
141 double dtau_del = params.beta / n_del;
142 M3pp_delta_ = M3pp_delta_ / (Z * dtau_del);
143
144 // Account for edge bins beeing smaller
145 auto _ = all_t{};
146 for (auto [M, M_del] : zip(M3pp_tau_, M3pp_delta_)) {
147 M[0, _] *= 2.0;
148 M[_, 0] *= 2.0;
149 M[n, _] *= 2.0;
150 M[_, n] *= 2.0;
151 M_del[0] *= 2.0;
152 M_del[n_del] *= 2.0;
153 }
154 }
155
156} // namespace triqs_ctint::measures
void accumulate(mc_weight_t sign)
Accumulate M_tau using binning.
Definition M3pp_tau.cpp:28
void collect_results(mpi::communicator const &comm)
Collect results and normalize.
Definition M3pp_tau.cpp:129