TRIQS/triqs_cthyb 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
G2_iwll.cpp
1/*******************************************************************************
2 *
3 * TRIQS: a Toolbox for Research in Interacting Quantum Systems
4 *
5 * Copyright (C) 2016, P. Seth, I. Krivenko, M. Ferrero and O. Parcollet
6 *
7 * TRIQS is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later
10 * version.
11 *
12 * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 * details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * TRIQS. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ******************************************************************************/
21
22#include "./G2_iwll.hpp"
23
24namespace triqs_cthyb {
25
26 template <G2_channel Channel>
27 measure_G2_iwll<Channel>::measure_G2_iwll(std::optional<G2_iwll_t> &G2_iwll_opt, qmc_data const &data, G2_measures_t &G2_measures)
28 : data(data), G2_measures(G2_measures), average_sign(0) {
29
30 const double beta = data.config.beta();
31
32 order = G2_measures.params.measure_G2_block_order;
33 long n_l = G2_measures.params.measure_G2_n_l;
34 int n_bosonic = G2_measures.params.measure_G2_n_bosonic;
35 int nfft_buf_size = G2_measures.params.measure_G2_iwll_nfft_buf_size;
36
37 // Allocate the two-particle Green's function
38 {
39 mesh::imfreq mesh_w{beta, Boson, n_bosonic};
40 mesh::legendre mesh_l{beta, Fermion, n_l};
41 mesh::prod<imfreq, legendre, legendre> mesh_wll{mesh_w, mesh_l, mesh_l};
42
43 G2_iwll_opt = make_block2_gf(mesh_wll, G2_measures.gf_struct, order);
44 G2_iwll.rebind(*G2_iwll_opt);
45 G2_iwll() = 0;
46 }
47
48 // Allocate the nfft buffers
49 {
50 nfft_buf.resize(std::array<long, 2>{G2_iwll.size1(), G2_iwll.size2()});
51
52 mesh::imfreq mesh_w = std::get<0>(G2_iwll(0, 0).mesh().components());
53
54 for (auto const &m : G2_measures()) {
55 auto s = m.target_shape;
56 array<int, 6> buf_sizes(n_l, n_l, s[0], s[1], s[2], s[3]);
57 buf_sizes() = nfft_buf_size;
58 nfft_buf(m.b1.idx, m.b2.idx) = nfft_array_t<1, 6>{mesh_w, G2_iwll(m.b1.idx, m.b2.idx).data(), buf_sizes};
59 }
60 }
61 }
62
63 template <G2_channel Channel> void measure_G2_iwll<Channel>::accumulate(mc_weight_t s) {
64
65 s *= data.atomic_reweighting;
66 average_sign += s;
67
68 double beta = data.config.beta();
69 int n_l = std::get<1>(G2_iwll(0, 0).mesh().components()).size();
70
71 for (auto const &m : G2_measures()) {
72
73 if (data.dets[m.b1.idx].size() == 0 || data.dets[m.b2.idx].size() == 0) continue;
74
75 auto accumulate_impl = [&](op_t const &i, op_t const &j, op_t const &k, op_t const &l, mc_weight_t val) {
76 tilde_p_gen p_l1_gen(beta), p_l2_gen(beta);
77 double dtau = setup_times(p_l1_gen, p_l2_gen, i, j, k, l);
78
79 for (int l1 : range(n_l)) {
80 double p_l1 = p_l1_gen.next();
81 for (int l2 : range(n_l)) {
82 double p_l2 = p_l2_gen.next();
83 std::array<int, 6> vec{l1, l2, i.second, j.second, k.second, l.second};
84 nfft_buf(m.b1.idx, m.b2.idx).push_back({dtau}, vec, val * p_l1 * p_l2);
85 }
86 }
87 };
88
89 bool diag_block = (m.b1.idx == m.b2.idx);
90
91 // Perform the accumulation looping over both determinants
92 if (order == block_order::AABB || diag_block) {
93 foreach (data.dets[m.b1.idx], [&](op_t const &i, op_t const &j, mc_weight_t M_ij) {
94 foreach (data.dets[m.b2.idx], [&](op_t const &k, op_t const &l, mc_weight_t M_kl) {
95 accumulate_impl(i, j, k, l, s * M_ij * M_kl); // Accumulate in legendre-nfft buffer
96 })
97 ;
98 })
99 ;
100 }
101 if (order == block_order::ABBA || diag_block) {
102 foreach (data.dets[m.b1.idx], [&](op_t const &i, op_t const &l, mc_weight_t M_il) {
103 foreach (data.dets[m.b2.idx], [&](op_t const &k, op_t const &j, mc_weight_t M_kj) {
104 accumulate_impl(i, j, k, l, -s * M_il * M_kj); // Accumulate in legendre-nfft buffer
105 })
106 ;
107 })
108 ;
109 }
110 }
111 }
112
113 template <>
114 double measure_G2_iwll<G2_channel::PH>::setup_times(tilde_p_gen &p_l1_gen, tilde_p_gen &p_l2_gen, op_t const &i, op_t const &j, op_t const &k,
115 op_t const &l) {
116 p_l1_gen.reset(i.first, j.first);
117 p_l2_gen.reset(k.first, l.first);
118 double dtau = 0.5 * double(i.first + j.first - k.first - l.first);
119 return dtau;
120 }
121
122 template <>
123 double measure_G2_iwll<G2_channel::PP>::setup_times(tilde_p_gen &p_l1_gen, tilde_p_gen &p_l2_gen, op_t const &i, op_t const &j, op_t const &k,
124 op_t const &l) {
125 p_l1_gen.reset(i.first, k.first);
126 p_l2_gen.reset(j.first, l.first);
127 double dtau = 0.5 * double(i.first + mult_by_int(j.first, 3) - mult_by_int(k.first, 3) - l.first);
128 return dtau;
129 }
130
131 template <G2_channel Channel> void measure_G2_iwll<Channel>::collect_results(mpi::communicator const &c) {
132
133 for (auto const &m : G2_measures()) { nfft_buf(m.b1.idx, m.b2.idx).flush(); }
134
135 G2_iwll = mpi::all_reduce(G2_iwll, c);
136
137 average_sign = mpi::all_reduce(average_sign, c);
138
139 for (auto &G2_iwll_block : G2_iwll) {
140
141 for (auto l : std::get<1>(G2_iwll_block.mesh().components())) {
142 auto _ = all_t{};
143 double s = std::sqrt(2 * l.index() + 1);
144 G2_iwll_block[_, l, _] *= s;
145 G2_iwll_block[_, _, l] *= s * (l.index() % 2 ? 1 : -1);
146 }
147
148 G2_iwll_block /= (real(average_sign) * data.config.beta());
149 }
150 }
151
152 template struct measure_G2_iwll<G2_channel::PP>;
153 template struct measure_G2_iwll<G2_channel::PH>;
154} // namespace triqs_cthyb