TRIQS/triqs_ctseg 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
split_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 "split_segment.hpp"
8#include "../logs.hpp"
9
10namespace triqs_ctseg::moves {
11
12 double split_segment::attempt() {
13
14 LOG("\n =================== ATTEMPT SPLIT ================ \n");
15
16 // ------------ Choice of segment --------------
17 // Select color
18 color = rng(config.n_color());
19 auto &sl = config.seglists[color];
20 LOG("Splitting at color {}", color);
21
22 if (sl.empty()) {
23 LOG("Nothing to split");
24 return 0;
25 }
26
27 // Select segment to split
28 prop_seg_idx = rng(sl.size());
29 auto prop_seg = sl[prop_seg_idx];
30 splitting_full_line = is_full_line(prop_seg);
31 if (splitting_full_line) LOG("Splitting full line.");
32
33 // Select splitting points (tau_left,tau_right)
34 auto dt1 = tau_t::random(rng, prop_seg.length());
35 auto dt2 = tau_t::random(rng, prop_seg.length());
36 if (dt1 == dt2) {
37 LOG("Generated equal times");
38 return 0;
39 }
40 // If splitting a full line, the order of tau_left and tau_right is not fixed
41 if (dt1 > dt2 and not splitting_full_line) std::swap(dt1, dt2);
42
43 tau_left = prop_seg.tau_c - dt1; // dt1 < dt2
44 tau_right = prop_seg.tau_c - dt2;
45
46 LOG("Splitting at position {} : adding c at {}, cdag at {}", prop_seg_idx, tau_right, tau_left);
47
48 // ------------ Trace ratio -------------
49
50 auto removed_segment = segment_t{tau_left, tau_right}; // "antisegment" : careful with order of c, cdag
51
52 double ln_trace_ratio = -wdata.mu(color) * removed_segment.length();
53 for (auto c : range(config.n_color())) {
54 if (c != color) { ln_trace_ratio -= -wdata.U(color, c) * overlap(config.seglists[c], removed_segment); }
55 if (wdata.has_Dt) { ln_trace_ratio += K_overlap(config.seglists[c], tau_right, tau_left, wdata.K, color, c); }
56 }
57 if (wdata.has_Dt)
58 ln_trace_ratio += -real(wdata.K(double(tau_left - tau_right))(color, color)); // Correct double counting
59 double trace_ratio = std::exp(ln_trace_ratio);
60
61 // ------------ Det ratio ---------------
62 auto &bl = wdata.block_number[color];
63 auto &bl_idx = wdata.index_in_block[color];
64 auto &D = wdata.dets[bl];
65 if (wdata.offdiag_Delta) {
66 if (cdag_in_det(tau_left, D) or c_in_det(tau_right, D)) {
67 LOG("One of the proposed times already exists in another line of the same block. Rejecting.");
68 return 0;
69 }
70 }
71 auto det_ratio = D.try_insert(det_lower_bound_x(D, tau_left), //
72 det_lower_bound_y(D, tau_right), //
73 {tau_left, bl_idx}, {tau_right, bl_idx});
74
75 // ------------ Proposition ratio ------------
76
77 double current_number_segments = sl.size();
78 double future_number_intervals = splitting_full_line ? 1 : sl.size() + 1;
79 // T direct 1/ # segment 1/ len(prop_seg) ^2 * (2 iif !full line)
80 // T inverse : 1/ # interval
81 double prop_ratio =
82 (current_number_segments * prop_seg.length() * prop_seg.length() / (splitting_full_line ? 1 : 2))
83 / (future_number_intervals);
84
85 LOG("trace_ratio = {}, prop_ratio = {}, det_ratio = {}", trace_ratio, prop_ratio, det_ratio);
86
87 det_sign = (det_ratio > 0) ? 1.0 : -1.0;
88 double prod = trace_ratio * det_ratio * prop_ratio;
89
90 return (std::isfinite(prod) ? prod : det_sign);
91 }
92
93 //--------------------------------------------------
94
95 double split_segment::accept() {
96
97 LOG("\n - - - - - ====> ACCEPT - - - - - - - - - - -\n");
98
99 double initial_sign = trace_sign(wdata);
100 LOG("Initial sign is {}. Initial configuration: {}", initial_sign, config);
101
102 // Update the dets
103 wdata.dets[wdata.block_number[color]].complete_operation();
104
105 // Split the segment
106 auto &sl = config.seglists[color];
107 if (splitting_full_line) {
108 sl[prop_seg_idx] = segment_t{tau_right, tau_left};
109 } else {
110 auto prop_seg = sl[prop_seg_idx];
111 auto new_seg_left = segment_t{prop_seg.tau_c, tau_left, prop_seg.J_c, false};
112 auto new_seg_right = segment_t{tau_right, prop_seg.tau_cdag, false, prop_seg.J_cdag};
113 // Update the proposed segment
114 sl[prop_seg_idx] = new_seg_left;
115 // Insert the new seg at the right
116 // if the splitting of a cyclic segment produces a non cyclic one, i.e. at the front, we need to insert it at the
117 // front of the list
118 bool insert_at_front = is_cyclic(prop_seg) and not is_cyclic(new_seg_right);
119 sl.insert(sl.begin() + (insert_at_front ? 0 : prop_seg_idx + 1), new_seg_right);
120 }
121
122 double final_sign = trace_sign(wdata);
123 double sign_ratio = final_sign / initial_sign;
124 LOG("Final sign is {}", final_sign);
125
126 // Check invariant
127 if constexpr (print_logs or ctseg_debug) check_invariant(config, wdata);
128
129 if (sign_ratio * det_sign == -1.0) wdata.minus_sign = true;
130
131 LOG("Configuration is {}", config);
132
133 return sign_ratio;
134 }
135
136 //--------------------------------------------------
137 void split_segment::reject() {
138 LOG("\n - - - - - ====> REJECT - - - - - - - - - - -\n");
139 wdata.dets[wdata.block_number[color]].reject_last_try();
140 }
141
142} // namespace triqs_ctseg::moves