TRIQS/triqs_cthyb 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
G2_iw.cpp
1/*******************************************************************************
2 *
3 * TRIQS: a Toolbox for Research in Interacting Quantum Systems
4 *
5 * Copyright (C) 2018, The Simons Foundation
6 * Author: H. U.R. Strand
7 *
8 * TRIQS is free software: you can redistribute it and/or modify it under the
9 * terms of the GNU General Public License as published by the Free Software
10 * Foundation, either version 3 of the License, or (at your option) any later
11 * version.
12 *
13 * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * TRIQS. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ******************************************************************************/
22
23#include <nda/nda.hpp>
24#include <triqs/utility/itertools.hpp>
25
26#include "./G2_iw.hpp"
27
28namespace triqs_cthyb {
29
30 using namespace G2_iw;
31
32 template <G2_channel Channel>
33 measure_G2_iw<Channel>::measure_G2_iw(std::optional<G2_iw_t> &G2_iw_opt, qmc_data const &data,
34 G2_measures_t const &G2_measures)
35 : measure_G2_iw_base<Channel>(G2_iw_opt, data, G2_measures) {
36
37 // Accumulation buffer for scattering matrix
38 for (auto const &m : M) {
39 auto norb1 = static_cast<size_t>(m.target_shape()[0]);
40 auto norb2 = static_cast<size_t>(m.target_shape()[1]);
41 size_t nfreq_pts = static_cast<size_t>(std::get<0>(M_mesh.components()).size());
42 M_block_arr.push_back(M_arr_t(norb1, norb2, nfreq_pts, nfreq_pts));
43 }
44 }
45
46 template <G2_channel Channel> void measure_G2_iw<Channel>::accumulate(mc_weight_t s) {
47
48 if (true)
49 accumulate_M_opt(); // FLOPS Optimized scattering matrix accumulation
50 else {
51
52 // ---------------------------------------------------------------
53 // Base line scattering matrix computation in two frequencies
54
55 auto M_ww_fill = [this](det_type const &det, M_t &M_ww) {
56 const double beta = this->data.config.beta();
57 foreach (det, [&M_ww, beta](op_t const &x, op_t const &y, det_scalar_t M_xy) {
58 // insert accumulation
59 double t1 = double(x.first);
60 double t2 = double(y.first);
61 for (auto [w1, w2] : M_ww.mesh()) { M_ww[w1, w2](x.second, y.second) += exp((beta - t1) * w1) * M_xy * std::exp(t2 * w2); }
62 })
63 ;
64 };
65
66 timer_M.start();
67 // Intermediate M matrices for all blocks
68 M() = 0;
69 for (auto bidx : range(M.size())) { M_ww_fill(data.dets[bidx], M[bidx]); }
70 timer_M.stop();
71
72 } // end accumulate_M
73
74 // ---------------------------------------------------------------
75 // Recombine products of scattering matrices
76 // to accumulate two particle quantities
77
78 accumulate_G2(s);
79 }
80
81 template <G2_channel Channel> void measure_G2_iw<Channel>::accumulate_M_opt() {
82
83 // ---------------------------------------------------------------
84 // Scattering matrix accumulation with minimal exponent evaluations
85 // using product relations for imaginary time + frequenc exponents
86
87 const double beta = data.config.beta();
88 const double pi_beta = M_PI / beta;
89
90 auto M_arr_fill = [pi_beta, beta](det_type const &det, M_arr_t &M_arr, M_mesh_t const &M_mesh) {
91 foreach (det,
92 [&M_mesh, &M_arr, pi_beta, beta](op_t const &x, op_t const &y, det_scalar_t M_xy) {
93 double t1 = double(x.first);
94 double t2 = double(y.first);
95
96 const auto &mesh1 = std::get<0>(M_mesh.components());
97 const auto &mesh2 = std::get<1>(M_mesh.components());
98
99 std::complex<double> dWt1(0., 2 * pi_beta * (beta - t1));
100 std::complex<double> dWt2(0., 2 * pi_beta * t2);
101
102 auto dexp1 = std::exp(dWt1);
103 auto dexp2 = std::exp(dWt2);
104
105 auto exp1 = std::exp(dWt1 * (mesh1.first_index() + 0.5));
106
107 for (auto const i1 : range(M_arr.shape()[2])) {
108
109 auto exp2 = std::exp(dWt2 * (mesh2.first_index() + 0.5));
110 auto exp1_M_xy = exp1 * M_xy;
111
112 for (auto const i2 : range(M_arr.shape()[3])) {
113
114 M_arr(x.second, y.second, i1, i2) += exp1_M_xy * exp2;
115 exp2 *= dexp2;
116 }
117 exp1 *= dexp1;
118 }
119 })
120 ;
121 };
122
123 timer_M.start();
124
125 // Intermediate M matrices for all blocks
126 for (auto bidx : range(M_block_arr.size())) {
127 M_block_arr[bidx]() = 0;
128 M_arr_fill(data.dets[bidx], M_block_arr[bidx], M_mesh);
129 }
130
131 // Reshuffle the accumulated scattering matrix into a Green's function object
132 for (auto bidx : range(M_block_arr.size()))
133 for (auto [n1, n2, i, j] : product_range(M[bidx].data().shape()))
134 M[bidx].data()(n1, n2, i, j) = M_block_arr[bidx](i, j, n1, n2);
135
136 timer_M.stop();
137 }
138
139 template class measure_G2_iw<G2_channel::AllFermionic>;
140 template class measure_G2_iw<G2_channel::PP>;
141 template class measure_G2_iw<G2_channel::PH>;
142
143} // namespace triqs_cthyb