TRIQS/triqs_ctseg 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
regroup_spin_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 "regroup_spin_segment.hpp"
8#include "../logs.hpp"
9#include "../configuration.hpp"
10#include <cmath>
11
12namespace triqs_ctseg::moves {
13
14 double regroup_spin_segment::attempt() {
15
16 LOG("\n =================== ATTEMPT REGROUP SPIN ================ \n");
17
18 ln_trace_ratio = 0;
19 prop_ratio = 1 / (double(config.Jperp_list.size()) + 1);
20
21 // ----------- Propose move in each color ----------
22 bool prop_failed;
23 std::tie(idx_c_up, idx_cdag_dn, tau_up, prop_failed) = propose(0); // spin up
24 if (prop_failed) return 0;
25 std::tie(idx_c_dn, idx_cdag_up, tau_dn, prop_failed) = propose(1); // spin down
26 if (prop_failed) return 0;
27
28 // ----------- Trace ratio -----------
29 // Correct for the overlap between the two modified segments
30 auto &sl_up = config.seglists[0];
31 auto &sl_dn = config.seglists[1];
32 auto old_seg_up = sl_up[idx_c_up];
33 auto old_seg_dn = sl_dn[idx_c_dn];
34 auto new_seg_up = segment_t{tau_up, old_seg_up.tau_cdag};
35 auto new_seg_dn = segment_t{tau_dn, old_seg_dn.tau_cdag};
36
37 ln_trace_ratio += -wdata.U(0, 1)
38 * (overlap(new_seg_up, new_seg_dn) + overlap(old_seg_up, old_seg_dn) //
39 - overlap(new_seg_up, old_seg_dn) - overlap(new_seg_dn, old_seg_up));
40
41 // Correct for the dynamical interaction between the two operators that have been moved
42 if (wdata.has_Dt) {
43 ln_trace_ratio -= real(wdata.K(double(tau_up - old_seg_dn.tau_c))(0, 1));
44 ln_trace_ratio -= real(wdata.K(double(tau_dn - old_seg_up.tau_c))(0, 1));
45 ln_trace_ratio += real(wdata.K(double(tau_dn - tau_up))(0, 1));
46 ln_trace_ratio += real(wdata.K(double(old_seg_up.tau_c - old_seg_dn.tau_c))(0, 1));
47 }
48
49 double trace_ratio = std::exp(ln_trace_ratio);
50 trace_ratio *= -real(wdata.Jperp(double(tau_up - tau_dn))(0, 0)) / 2;
51
52 // ----------- Det ratio -----------
53 double det_ratio = 1;
54
55 // Spin up
56 auto &D_up = wdata.dets[0];
57 det_ratio *= D_up.try_remove(det_lower_bound_x(D_up, sl_up[idx_cdag_up].tau_cdag),
58 det_lower_bound_y(D_up, sl_up[idx_c_up].tau_c));
59
60 // Spin down
61 auto &D_dn = wdata.dets[1];
62 det_ratio *= D_dn.try_remove(det_lower_bound_x(D_dn, sl_dn[idx_cdag_dn].tau_cdag),
63 det_lower_bound_y(D_dn, sl_dn[idx_c_dn].tau_c));
64
65 LOG("trace_ratio = {}, prop_ratio = {}, det_ratio = {}", trace_ratio, prop_ratio, det_ratio);
66
67 double prod = trace_ratio * det_ratio * prop_ratio;
68 det_sign = (det_ratio > 0) ? 1.0 : -1.0;
69
70 return (std::isfinite(prod) ? prod : det_sign);
71 }
72
73 //--------------------------------------------------
74
75 double regroup_spin_segment::accept() {
76
77 LOG("\n - - - - - ====> ACCEPT - - - - - - - - - - -\n");
78
79 double initial_sign = trace_sign(wdata);
80 LOG("Initial sign is {}. Initial configuration: {}", initial_sign, config);
81
82 // Update dets
83 wdata.dets[0].complete_operation();
84 wdata.dets[1].complete_operation();
85
86 // Update the segments
87 auto &sl_up = config.seglists[0];
88 auto &sl_dn = config.seglists[1];
89
90 // Update tau_c
91 sl_up[idx_c_up].tau_c = tau_up;
92 sl_dn[idx_c_dn].tau_c = tau_dn;
93
94 // Update spin tags
95 sl_up[idx_c_up].J_c = true;
96 sl_dn[idx_cdag_dn].J_cdag = true;
97 sl_dn[idx_c_dn].J_c = true;
98 sl_up[idx_cdag_up].J_cdag = true;
99
100 fix_ordering_first_last(sl_up);
101 fix_ordering_first_last(sl_dn);
102
103 // Add spin line
104 config.Jperp_list.push_back(Jperp_line_t{tau_up, tau_dn});
105
106 // Compute sign
107 double final_sign = trace_sign(wdata);
108 double sign_ratio = final_sign / initial_sign;
109 LOG("Final sign is {}", final_sign);
110
111 // Check invariant
112 if constexpr (print_logs or ctseg_debug) check_invariant(config, wdata);
113
114 if (sign_ratio * det_sign == -1.0) wdata.minus_sign = true;
115 LOG("Configuration is {}", config);
116
117 return sign_ratio;
118 }
119
120 //--------------------------------------------------
121
122 void regroup_spin_segment::reject() {
123
124 LOG("\n - - - - - ====> REJECT - - - - - - - - - - -\n");
125 wdata.dets[0].reject_last_try();
126 wdata.dets[1].reject_last_try();
127 }
128
129 //--------------------------------------------------
130
131 std::tuple<long, long, tau_t, bool> regroup_spin_segment::propose(int color) {
132
133 auto &sl = config.seglists[color];
134 int other_color = 1 - color;
135 auto &dsl = config.seglists[other_color];
136
137 // --------- Eliminate cases where move is impossible ---------
138 if (sl.empty() or dsl.empty()) {
139 LOG("Line is empty, cannot regroup spin.");
140 return {0, 0, tau_t::zero(), true};
141 }
142 if (is_full_line(sl[0]) or is_full_line(dsl[0])) {
143 LOG("Line is full, cannot regroup spin.");
144 return {0, 0, tau_t::zero(), true};
145 }
146
147 // --------- Randomly choose a c operator -----------
148
149 auto idx_c = rng(sl.size());
150 LOG("Spin {}: regrouping c at position {}.", (color == 0) ? "up" : "down", idx_c);
151 if (sl[idx_c].J_c) {
152 LOG("Spin {}: cannot regroup because c is connected to a spin line.", (color == 0) ? "up" : "down");
153 return {0, 0, tau_t::zero(), true};
154 }
155
156 auto tau_c = sl[idx_c].tau_c;
157
158 // -------- Propose new position for the c ---------
159
160 // Determine window in which the c can be moved
161 auto idx_left = (idx_c == 0) ? sl.size() - 1 : idx_c - 1;
162 auto wtau_left = sl[idx_left].tau_cdag;
163 auto wtau_right = sl[idx_c].tau_cdag;
164 if (idx_c == idx_left) {
165 wtau_left = tau_t::beta();
166 wtau_right = tau_t::zero();
167 }
168
169 // Find the cdag in opposite spin that are within the window
170 auto cdag_list = cdag_in_window(wtau_left, wtau_right, dsl);
171 if (cdag_list.empty()) {
172 LOG("Spin {}: cannot regroup because there are no suitable cdag operators.", (color == 0) ? "up" : "down");
173 return {0, 0, tau_t::zero(), true};
174 }
175 // Choose one of them randomly
176 auto idx_cdag = cdag_list[rng(cdag_list.size())];
177 if (dsl[idx_cdag].J_cdag) {
178 LOG("Spin {}: cannot regroup because chosen cdag is connected to a spin line.", (color == 0) ? "up" : "down");
179 return {0, 0, tau_t::zero(), true};
180 }
181 auto tau_c_new = dsl[idx_cdag].tau_cdag;
182 auto new_seg = segment_t{tau_c_new, sl[idx_c].tau_cdag};
183 LOG("Spin {}: moving c from {} to {}.", (color == 0) ? "up" : "down", tau_c, tau_c_new);
184
185 // -------- Trace ratio ---------
186 ln_trace_ratio += wdata.mu(color) * (double(new_seg.length()) - double(sl[idx_c].length()));
187 LOG("Spin {}: ln trace ratio = {}", (color == 0) ? "up" : "down", ln_trace_ratio);
188 for (auto const &[c, slc] : itertools::enumerate(config.seglists)) {
189 if (c != color) {
190 ln_trace_ratio += -wdata.U(c, color) * overlap(slc, new_seg);
191 ln_trace_ratio -= -wdata.U(c, color) * overlap(slc, sl[idx_c]);
192 }
193 if (wdata.has_Dt) {
194 ln_trace_ratio += K_overlap(slc, tau_c_new, true, wdata.K, c, color);
195 ln_trace_ratio -= K_overlap(slc, tau_c, true, wdata.K, c, color);
196 }
197 }
198 if (wdata.has_Dt) ln_trace_ratio -= real(wdata.K(double(tau_c_new - tau_c))(color, color));
199
200 // --------- Prop ratio ---------
201 auto window_length = double(wtau_left - wtau_right);
202 prop_ratio *= double(sl.size()) * cdag_list.size() / window_length;
203
204 return {idx_c, idx_cdag, tau_c_new, false};
205 }
206
207} // 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