TRIQS/triqs_ctseg 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
insert_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 "insert_spin_segment.hpp"
8#include "../logs.hpp"
9#include <cmath>
10
11namespace triqs_ctseg::moves {
12
13 insert_spin_segment::insert_spin_segment(work_data_t &data_, configuration_t &config_,
14 triqs::mc_tools::random_generator &rng_)
15 : wdata(data_), config(config_), rng(rng_) {
16 ALWAYS_EXPECTS(config.n_color() == 2, "spin add/remove move only implemented for n_color == 2, got {}",
17 config.n_color());
18 }
19
20 // --------------------------------------------------
21
22 double insert_spin_segment::attempt() {
23
24 ALWAYS_EXPECTS((config.n_color() == 2),
25 "Insert spin segment only implemented for n_color = 2, but here n_color = {}", config.n_color());
26
27 LOG("\n =================== ATTEMPT INSERT SPIN ================ \n");
28
29 // ------------ Choice of segments --------------
30
31 // Select spin insertion color
32 orig_color = rng(config.n_color());
33 auto &sl = config.seglists[orig_color];
34 LOG("Inserting spin: splitting at color {}", orig_color);
35
36 if (sl.empty()) {
37 LOG("ABORT : Empty line, cannot insert spin.");
38 return 0;
39 }
40
41 dest_color = (orig_color == 0) ? 1 : 0;
42 auto &dsl = config.seglists[dest_color];
43
44 // Randomly choose one existing segment
45 prop_seg_idx = rng(sl.size());
46 prop_seg = sl[prop_seg_idx];
47
48 // Is it a full line ?
49 splitting_full_line = is_full_line(prop_seg);
50 if (splitting_full_line) LOG("Inserting spin from full line.");
51
52 auto dt1 = tau_t::random(rng, prop_seg.length());
53 auto dt2 = tau_t::random(rng, prop_seg.length());
54
55 if (dt1 == dt2) { // Almost never, but protect
56 LOG("ABORT : Generated equal times");
57 return 0;
58 }
59
60 // If splitting a full line, the order of tau_left and tau_right is not fixed
61 if (dt1 > dt2 and not splitting_full_line) std::swap(dt1, dt2);
62
63 tau_left = prop_seg.tau_c - dt1; // dt1 < dt2
64 tau_right = prop_seg.tau_c - dt2;
65 spin_seg = segment_t{tau_left, tau_right, true, true};
66 LOG("Inserting spins in segment at position {}, at tau_left = {}, tau_right = {}", prop_seg_idx, tau_left,
67 tau_right);
68
69 if (not is_insertable_into(spin_seg, dsl)) {
70 LOG("ABORT : Space is occupied on other line.");
71 return 0;
72 }
73
74 // ------------ Trace ratio -------------
75
76 double ln_trace_ratio = (wdata.mu(dest_color) - wdata.mu(orig_color)) * spin_seg.length();
77 if (wdata.has_Dt) {
78 for (auto [c, slist] : itertools::enumerate(config.seglists)) {
79 // "antisegment" - careful with order
80 ln_trace_ratio += K_overlap(slist, spin_seg.tau_cdag, spin_seg.tau_c, wdata.K, orig_color, c);
81 ln_trace_ratio += K_overlap(slist, spin_seg.tau_c, spin_seg.tau_cdag, wdata.K, dest_color, c);
82 }
83 // Add interactions of the inserted operators with themselves
84 auto Kl = wdata.K(double(spin_seg.length())); // matrix
85 ln_trace_ratio -= real(Kl(orig_color, orig_color));
86 ln_trace_ratio -= real(Kl(dest_color, dest_color));
87 ln_trace_ratio += 2 * real(Kl(orig_color, dest_color));
88 }
89 double trace_ratio = std::exp(ln_trace_ratio);
90 trace_ratio *= -(real(wdata.Jperp(double(spin_seg.length()))(0, 0)) / 2);
91
92 // ------------ Det ratio ---------------
93
94 double det_ratio = 1;
95
96 // ------------ Proposition ratio ------------
97
98 // T direct -> 1/ length(prop_seg) ^2 1/ ncolor 1/ sl.size * (splitting_full_line ? 1 : 2)
99 // # The last because of the swap we have 2 ways to get to the same (dt1, dt2) except in full line case
100 // T inverse -> 1/ Jperlist size in new config * (splitting_full_line ? 1/2 : 1) # see reverse move
101 // the (splitting_full_line ...) simplify to a ratio of 2
102 double prop_ratio = (double(config.n_color()) * sl.size() * prop_seg.length() * prop_seg.length() / 2)
103 / double(config.Jperp_list.size() + 1);
104
105 LOG("trace_ratio = {}, prop_ratio = {}, det_ratio = {}", trace_ratio, prop_ratio, det_ratio);
106
107 double prod = trace_ratio * det_ratio * prop_ratio;
108 det_sign = (det_ratio > 0) ? 1.0 : -1.0;
109 return (std::isfinite(prod) ? prod : det_sign);
110 }
111
112 //--------------------------------------------------
113
114 double insert_spin_segment::accept() {
115
116 LOG("\n - - - - - ====> ACCEPT - - - - - - - - - - -\n");
117
118 auto &sl = config.seglists[orig_color];
119 auto &dsl = config.seglists[dest_color];
120
121 // Split segment at origin
122 if (splitting_full_line) {
123 sl[prop_seg_idx] = segment_t{tau_right, tau_left, true, true};
124 } else {
125 auto new_seg_left = segment_t{prop_seg.tau_c, tau_left, prop_seg.J_c, true};
126 auto new_seg_right = segment_t{tau_right, prop_seg.tau_cdag, true, prop_seg.J_cdag};
127 // Update the proposed segment
128 sl[prop_seg_idx] = new_seg_left;
129 // Insert a new segment
130 // cf split_segment. the new_seg_right need to be insert at front if it is part of a cyclic segment and is not cyclic itself
131 bool insert_at_front = is_cyclic(prop_seg) and not is_cyclic(new_seg_right);
132 sl.insert(begin(sl) + (insert_at_front ? 0 : prop_seg_idx + 1), new_seg_right);
133 }
134
135 // Insert segment at destination
136 dsl.insert(std::upper_bound(begin(dsl), end(dsl), spin_seg), spin_seg);
137
138 // Insert Jperp line
139 auto &jl = config.Jperp_list;
140 if (dest_color == 0)
141 jl.push_back(Jperp_line_t{spin_seg.tau_c, spin_seg.tau_cdag});
142 else
143 jl.push_back(Jperp_line_t{spin_seg.tau_cdag, spin_seg.tau_c});
144
145 // Check invariant
146 if constexpr (print_logs or ctseg_debug) check_invariant(config, wdata);
147 LOG("Configuration is {}", config);
148
149 return 1.0;
150 }
151
152 //--------------------------------------------------
153 void insert_spin_segment::reject() { LOG("\n - - - - - ====> REJECT - - - - - - - - - - -\n"); }
154
155} // namespace triqs_ctseg::moves