TRIQS/triqs_ctseg 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
move_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 "move_segment.hpp"
8#include "../logs.hpp"
9
10namespace triqs_ctseg::moves {
11
12 double move_segment::attempt() {
13
14 LOG("\n =================== ATTEMPT MOVE ================ \n");
15
16 // ------------ Choice of segment and colors --------------
17 // Select origin color
18 origin_color = rng(config.n_color());
19 LOG("Moving from color {}", origin_color);
20
21 // Select destination color, different from origin_color
22 dest_color = rng(config.n_color() - 1);
23 if (dest_color >= origin_color) ++dest_color; // little trick to select another color
24 LOG("Moving to color {}", dest_color);
25
26 // Reject if colors within the same block because no appropriate det_manip function (FIXME)
27 auto const &origin_bl = wdata.block_number[origin_color];
28 auto const &destination_bl = wdata.block_number[dest_color];
29 auto const &idx_dest = wdata.index_in_block[dest_color];
30 if (origin_bl == destination_bl) {
31 LOG("Reject: colors are within the same block.");
32 return 0;
33 }
34
35 // Do we want to move an antisegment ?
36 flipped = (rng(2) == 0);
37
38 if (flipped) {
39 // if we want to move an antisegment, we simply flip the configuration
40 sl = flip(config.seglists[origin_color]);
41 dsl = flip(config.seglists[dest_color]);
42 LOG("Moving antisegment.");
43 } else {
44 sl = config.seglists[origin_color];
45 dsl = config.seglists[dest_color];
46 }
47
48 // If color has no segments, nothing to move
49 if (sl.empty()) {
50 LOG("Nothing to move!");
51 return 0;
52 }
53
54 // Select segment to move
55 origin_index = rng(sl.size());
56 origin_segment = sl[origin_index];
57 LOG("Moving segment at position {}", origin_index);
58
59 // Reject if the segment has spin lines attached
60 if (origin_segment.J_c or origin_segment.J_cdag) {
61 LOG("Segment has spin line attached: cannot move.");
62 return 0;
63 }
64
65 // Reject if chosen segment overlaps with destination color
66 if (not is_insertable_into(origin_segment, dsl)) {
67 LOG("Space is occupied in destination color.");
68 return 0;
69 }
70
71 // Find where origin segment should be inserted in destination color
72 dest_index = std::upper_bound(dsl.begin(), dsl.end(), origin_segment) - dsl.cbegin();
73 LOG("Moving to position {}", dest_index);
74
75 // ------------ Trace ratio -------------
76
77 double ln_trace_ratio =
78 (flipped ? -1 : 1) * (wdata.mu(dest_color) - wdata.mu(origin_color)) * double(origin_segment.length());
79
80 for (auto const &[c, slist] : itertools::enumerate(config.seglists)) {
81 if (c != dest_color && c != origin_color) {
82 ln_trace_ratio += -wdata.U(dest_color, c) * overlap(slist, origin_segment) * (flipped ? -1 : 1);
83 ln_trace_ratio -= -wdata.U(origin_color, c) * overlap(slist, origin_segment) * (flipped ? -1 : 1);
84 }
85 }
86
87 if (wdata.has_Dt) {
88 auto tau_c = origin_segment.tau_c;
89 auto tau_cdag = origin_segment.tau_cdag;
90 if (flipped) std::swap(tau_c, tau_cdag);
91
92 for (auto const &[c, slist] : itertools::enumerate(config.seglists)) {
93 ln_trace_ratio += K_overlap(slist, tau_c, tau_cdag, wdata.K, dest_color, c);
94 ln_trace_ratio -= K_overlap(slist, tau_c, tau_cdag, wdata.K, origin_color, c);
95 }
96 // Correct double counting
97 auto Kl = wdata.K(double(origin_segment.length())); // matrix
98 ln_trace_ratio -= real(Kl(origin_color, origin_color));
99 ln_trace_ratio -= real(Kl(dest_color, dest_color));
100 ln_trace_ratio += 2 * real(Kl(origin_color, dest_color));
101 }
102 double trace_ratio = std::exp(ln_trace_ratio);
103
104 // ------------ Det ratio ---------------
105 // Times are ordered in det. We insert tau_cdag as a line (first index) and tau_c as a column.
106 // c and cdag are inverted if we flip
107 double det_ratio = 1;
108 auto seg = (flipped ? flip(origin_segment) : origin_segment);
109 auto &D_dest = wdata.dets[destination_bl];
110 auto &D_orig = wdata.dets[origin_bl];
111 if (wdata.offdiag_Delta) {
112 if (cdag_in_det(seg.tau_cdag, D_dest) or c_in_det(seg.tau_c, D_dest)) {
113 LOG("Proposed times already exist in destination block.");
114 return 0;
115 }
116 }
117 if (not is_full_line(origin_segment))
118 det_ratio = D_dest.try_insert(det_lower_bound_x(D_dest, seg.tau_cdag), det_lower_bound_y(D_dest, seg.tau_c),
119 {seg.tau_cdag, idx_dest}, {seg.tau_c, idx_dest})
120 * D_orig.try_remove(det_lower_bound_x(D_orig, seg.tau_cdag), det_lower_bound_y(D_orig, seg.tau_c));
121
122 // ------------ Proposition ratio -----------
123
124 double prop_ratio = double(sl.size()) / (dsl.size() + 1);
125
126 LOG("trace_ratio = {}, prop_ratio = {}, det_ratio = {}", trace_ratio, prop_ratio, det_ratio);
127
128 double prod = trace_ratio * det_ratio * prop_ratio;
129 det_sign = (det_ratio > 0) ? 1.0 : -1.0;
130 return (std::isfinite(prod) ? prod : det_sign);
131 }
132
133 //--------------------------------------------------
134
135 double move_segment::accept() {
136
137 LOG("\n - - - - - ====> ACCEPT - - - - - - - - - - -\n");
138
139 double initial_sign = trace_sign(wdata);
140 LOG("Initial sign is {}. Initial configuration: {}", initial_sign, config);
141
142 // Update the dets
143 auto const &origin_bl = wdata.block_number[origin_color];
144 auto const &destination_bl = wdata.block_number[dest_color];
145 wdata.dets[origin_bl].complete_operation();
146 wdata.dets[destination_bl].complete_operation();
147
148 // Add the segment at destination
149 dsl.insert(begin(dsl) + dest_index, origin_segment);
150
151 // Remove the segment at origin
152 sl.erase(begin(sl) + origin_index);
153
154 if (flipped) {
155 config.seglists[origin_color] = flip(sl);
156 config.seglists[dest_color] = flip(dsl);
157 } else {
158 config.seglists[origin_color] = std::move(sl);
159 config.seglists[dest_color] = std::move(dsl);
160 }
161 // WARNING : do not use sl, dsl AFTER !
162
163 double final_sign = trace_sign(wdata);
164 double sign_ratio = final_sign / initial_sign;
165 LOG("Final sign is {}", final_sign);
166
167 // Check invariant
168 if constexpr (print_logs or ctseg_debug) check_invariant(config, wdata);
169
170 if (sign_ratio * det_sign == -1.0) wdata.minus_sign = true;
171
172 LOG("Configuration is {}", config);
173
174 return sign_ratio;
175 }
176
177 //--------------------------------------------------
178 void move_segment::reject() {
179 LOG("\n - - - - - ====> REJECT - - - - - - - - - - -\n");
180 auto const &origin_bl = wdata.block_number[origin_color];
181 auto const &destination_bl = wdata.block_number[dest_color];
182 wdata.dets[origin_bl].reject_last_try();
183 wdata.dets[destination_bl].reject_last_try();
184 }
185
186} // namespace triqs_ctseg::moves