22#include "./G2_iwll.hpp"
24namespace triqs_cthyb {
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) {
30 const double beta = data.config.beta();
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;
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};
43 G2_iwll_opt = make_block2_gf(mesh_wll, G2_measures.gf_struct, order);
44 G2_iwll.rebind(*G2_iwll_opt);
50 nfft_buf.resize(std::array<long, 2>{G2_iwll.size1(), G2_iwll.size2()});
52 mesh::imfreq mesh_w = std::get<0>(G2_iwll(0, 0).mesh().components());
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};
63 template <G2_channel Channel>
void measure_G2_iwll<Channel>::accumulate(mc_weight_t s) {
65 s *= data.atomic_reweighting;
68 double beta = data.config.beta();
69 int n_l = std::get<1>(G2_iwll(0, 0).mesh().components()).size();
71 for (
auto const &m : G2_measures()) {
73 if (data.dets[m.b1.idx].size() == 0 || data.dets[m.b2.idx].size() == 0)
continue;
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);
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);
89 bool diag_block = (m.b1.idx == m.b2.idx);
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);
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);
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,
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);
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,
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);
131 template <G2_channel Channel>
void measure_G2_iwll<Channel>::collect_results(mpi::communicator
const &c) {
133 for (
auto const &m : G2_measures()) { nfft_buf(m.b1.idx, m.b2.idx).flush(); }
135 G2_iwll = mpi::all_reduce(G2_iwll, c);
137 average_sign = mpi::all_reduce(average_sign, c);
139 for (
auto &G2_iwll_block : G2_iwll) {
141 for (
auto l : std::get<1>(G2_iwll_block.mesh().components())) {
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);
148 G2_iwll_block /= (real(average_sign) * data.config.beta());
152 template struct measure_G2_iwll<G2_channel::PP>;
153 template struct measure_G2_iwll<G2_channel::PH>;