TRIQS/triqs_ctseg 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
insert_segment.cpp
1// Copyright (c) 2022--present, The Simons Foundation
2// Copyright (c) 2022--present, Max Planck Institute for Polymer Research, Mainz, Germany
3// This file is part of TRIQS/ctseg and is licensed under the terms of GPLv3 or later.
4// SPDX-License-Identifier: GPL-3.0-or-later
5// See LICENSE in the root of this distribution for details.
6
7#include "insert_segment.hpp"
8#include "../logs.hpp"
9#include <cmath>
10
11namespace triqs_ctseg::moves {
12
13 double insert_segment::attempt() {
14
15 LOG("\n =================== ATTEMPT INSERT ================ \n");
16
17 // ------------ Choice of segment --------------
18 // Select insertion color
19 color = rng(config.n_color());
20 auto &sl = config.seglists[color];
21 LOG("Inserting at color {}", color);
22
23 // Select insertion window [tau_left,tau_right]
24 tau_t tau_left = tau_t::beta(), tau_right = tau_t::zero();
25
26 // If sl.empty, no segment, we have the window.
27 // Otherwise, we pick up one segment at random
28 if (not sl.empty()) {
29 if (is_full_line(sl.back())) {
30 LOG("Full line, cannot insert.");
31 return 0;
32 }
33 // Randomly choose one existing segment
34 long seg_idx = rng(sl.size());
35 tau_left = sl[seg_idx].tau_cdag; // tau_left is cdag of this segment
36 tau_right = sl[modulo(seg_idx + 1, sl.size())].tau_c; // tau_right is c of next segment, possibly cyclic
37 }
38
39 // We now have the insertion window [tau_left,tau_right]
40 // Warning : it can be cyclic !
41 LOG("Insertion window is tau_left = {}, tau_right = {}", tau_left, tau_right);
42 tau_t window_length = tau_left - tau_right;
43
44 // Choose two random times in insertion window
45 auto dt1 = tau_t::random(rng, window_length);
46 auto dt2 = tau_t::random(rng, window_length);
47 if (dt1 == dt2) {
48 LOG("Insert_segment: generated equal times. Rejecting");
49 return 0;
50 }
51 // We ensure that dt1 < dt2, unless inserting in empty line because :
52 // 1- in non empty line, we insert a segment in a void so a [c cdag]
53 // 2- in an empty line, we can insert [c cdag] or [cdag c]
54 // BEWARE in the reverse move.
55 if (dt1 > dt2 and not sl.empty()) std::swap(dt1, dt2); // if inserting into an empty line, two ways to insert
56
57 // Here is the segment we propose to insert
58 prop_seg = segment_t{tau_left - dt1, tau_left - dt2};
59 LOG("Inserting segment with c at {}, cdag at {}", prop_seg.tau_c, prop_seg.tau_cdag);
60
61 // ------------ Trace ratio -------------
62 double ln_trace_ratio = wdata.mu(color) * prop_seg.length(); // chemical potential
63 // Overlaps
64 for (auto c : range(config.n_color())) {
65 if (c != color) ln_trace_ratio += -wdata.U(color, c) * overlap(config.seglists[c], prop_seg);
66 if (wdata.has_Dt)
67 ln_trace_ratio += K_overlap(config.seglists[c], prop_seg.tau_c, prop_seg.tau_cdag, wdata.K, color, c);
68 }
69 if (wdata.has_Dt)
70 ln_trace_ratio += -real(wdata.K(double(prop_seg.length()))(color, color)); // Correct double counting
71 double trace_ratio = std::exp(ln_trace_ratio);
72
73 // ------------ Det ratio ---------------
74 // insert tau_cdag as a line (first index) and tau_c as a column (second index).
75 auto &bl = wdata.block_number[color];
76 auto &bl_idx = wdata.index_in_block[color];
77 auto &D = wdata.dets[bl];
78 if (wdata.offdiag_Delta) {
79 if (cdag_in_det(prop_seg.tau_cdag, D) or c_in_det(prop_seg.tau_c, D)) {
80 LOG("One of the proposed times already exists in another line of the same block. Rejecting.");
81 return 0;
82 }
83 }
84 auto det_ratio = D.try_insert(det_lower_bound_x(D, prop_seg.tau_cdag), //
85 det_lower_bound_y(D, prop_seg.tau_c), //
86 {prop_seg.tau_cdag, bl_idx}, {prop_seg.tau_c, bl_idx});
87
88 // ------------ Proposition ratio ------------
89
90 double current_number_intervals = std::max(long(1), long(sl.size()));
91 double future_number_segments = sl.size() + 1;
92 // T direct = 1 / current_number_intervals * 1/window_length^2 *
93 // * (2 iif not empty as the proba to get the dt1, dt2 coupled is x 2)
94 // T inverse = 1 / future_number_segments
95 double prop_ratio =
96 (current_number_intervals * window_length * window_length / (sl.empty() ? 1 : 2)) / future_number_segments;
97 // Account for absence of time swapping when inserting into empty line.
98
99 LOG("trace_ratio = {}, prop_ratio = {}, det_ratio = {}", trace_ratio, prop_ratio, det_ratio);
100
101 double prod = trace_ratio * det_ratio * prop_ratio;
102 det_sign = (det_ratio > 0) ? 1.0 : -1.0;
103
104 return (std::isfinite(prod) ? prod : det_sign);
105 }
106
107 //--------------------------------------------------
108
109 double insert_segment::accept() {
110
111 LOG("\n - - - - - ====> ACCEPT - - - - - - - - - - -\n");
112
113 double initial_sign = trace_sign(wdata);
114 LOG("Initial sign is {}. Initial configuration: {}", initial_sign, config);
115
116 // Insert the times into the det
117 wdata.dets[wdata.block_number[color]].complete_operation();
118
119 // Insert the segment in an ordered list
120 auto &sl = config.seglists[color];
121 sl.insert(std::upper_bound(sl.begin(), sl.end(), prop_seg), prop_seg);
122
123 // Check invariant
124 if constexpr (print_logs or ctseg_debug) check_invariant(config, wdata);
125
126 double final_sign = trace_sign(wdata);
127 double sign_ratio = final_sign / initial_sign;
128 LOG("Final sign is {}", final_sign);
129
130 if (sign_ratio * det_sign == -1.0) wdata.minus_sign = true;
131
132 LOG("Configuration is {}", config);
133
134 return sign_ratio;
135 }
136
137 //--------------------------------------------------
138 void insert_segment::reject() {
139 LOG("\n - - - - - ====> REJECT - - - - - - - - - - -\n");
140 wdata.dets[wdata.block_number[color]].reject_last_try();
141 }
142
143} // namespace triqs_ctseg::moves
static tau_t beta()
tau_t at tau = beta
Definition tau_t.hpp:67
static tau_t zero()
$\tau = 0$
Definition tau_t.hpp:70