TRIQS/triqs_ctseg 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
configuration.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 "configuration.hpp"
8
9namespace triqs_ctseg {
10
11 // =================== Functions to manipulate segments ===================
12
13 // Split a cyclic segment into 2 segment, attached to beta and 0
14 std::pair<segment_t, segment_t> split_cyclic_segment(segment_t const &s) {
15 return {{tau_t::beta(), s.tau_cdag}, {s.tau_c, tau_t::zero()}};
16 }
17
18 // -------------- internal -------------
19
20 // Checks if two segments are completely disjoint.
21 // !! s2 might be cyclic, not s1
22 bool disjoint(segment_t const &s1, segment_t const &s2) {
23 if (is_cyclic(s2)) {
24 auto [sl, sr] = split_cyclic_segment(s2);
25 return disjoint(s1, sl) and disjoint(s1, sr);
26 }
27 return s1.tau_cdag > s2.tau_c or s2.tau_cdag > s1.tau_c; // symmetric s1 s2
28 }
29
30 // ---------------------------
31
32 // Check whether time is in segment [tau_c,tau_cdag[.
33 bool tau_in_seg(tau_t const &tau, segment_t const &seg) {
34 // if the segment is cyclic, we check if tau in the 2 parts
35 if (is_cyclic(seg)) {
36 auto [sl, sr] = split_cyclic_segment(seg);
37 return tau_in_seg(tau, sl) or tau_in_seg(tau, sr);
38 }
39 return (tau <= seg.tau_c and tau > seg.tau_cdag); // ! decreasing time order
40 }
41
42 // ---------------------------
43
44 // Overlap between two (possibly cyclic) segments.
45 double overlap(segment_t const &s1, segment_t const &s2) {
46 // first treat the cyclic case
47 if (is_cyclic(s1)) {
48 auto [sl, sr] = split_cyclic_segment(s1);
49 return overlap(sl, s2) + overlap(sr, s2);
50 }
51 if (is_cyclic(s2)) return overlap(s2, s1); // s1 is not cyclic any more
52 // [c1 cd1] [c1 cd1]
53 // [c2 cd2] OR [c2 cd2]
54 if (s1.tau_cdag >= s2.tau_c or s2.tau_cdag >= s1.tau_c) return 0;
55 // last case
56 // [c1 cd1] [c1 cd1]
57 // [c2 cd2] [c2 cd2]
58 tau_t tau_start = std::min(s1.tau_c, s2.tau_c); // ! most RIGHT as ordered by > !
59 tau_t tau_end = std::max(s1.tau_cdag, s2.tau_cdag); // most LEFT
60 assert(tau_start >= tau_end);
61 return double(tau_start - tau_end);
62 };
63
64 // =================== Functions to manipulate std::vector<segment_t> ========
65
66 vec_seg_iter_t lower_bound(std::vector<segment_t> const &seglist, tau_t const &tau) {
67 // comparison is s.tau > tau as in the tau_t comparison
68 return std::lower_bound(seglist.begin(), seglist.end(), tau, [](auto &&s, auto &&t) { return s.tau_c > t; });
69 }
70
71 // ------------ internal ---------------
72
73 // Iterator on the closest segment on the left of seg.
74 // If there is none, returns the first on the right (or end)
75 // the list shoud not be empty
76 vec_seg_iter_t find_segment_left(std::vector<segment_t> const &seglist, segment_t const &seg) {
77 auto seg_iter = std::upper_bound(seglist.begin(), seglist.end(), seg);
78 return (seg_iter == seglist.begin()) ? seg_iter : --seg_iter;
79 }
80
81 // ---------------------------
82
83 int n_at_boundary(std::vector<segment_t> const &sl) {
84 if (sl.empty()) return 0;
85 return (is_cyclic(sl.back()) or is_full_line(sl.back())) ? 1 : 0;
86 }
87
88 // ---------------------------
89
90 // Find density in seglist to the right of time tau.
91 int n_tau(tau_t const &tau, std::vector<segment_t> const &seglist) {
92 if (seglist.empty()) return 0;
93 auto it = find_segment_left(seglist, segment_t{tau, tau});
94 return (tau_in_seg(tau, *it) or tau_in_seg(tau, seglist.back())) ? 1 : 0;
95 }
96
97 // ---------------------------
98 // Flip seglist
99 std::vector<segment_t> flip(std::vector<segment_t> const &sl) {
100 if (sl.empty()) // Flipped seglist is full line
101 return {segment_t::full_line()};
102
103 if (sl.size() == 1 and is_full_line(sl[0])) // Do nothing: flipped config empty
104 return {};
105
106 long N = sl.size();
107 auto fsl = std::vector<segment_t>(N); // NB must be () here, not {} !
108 if (is_cyclic(sl.back()))
109 for (auto i : range(N)) {
110 long ind = (i == 0) ? N - 1 : i - 1;
111 fsl[i] = segment_t{sl[ind].tau_cdag, sl[i].tau_c, sl[ind].J_cdag, sl[i].J_c};
112 }
113 else
114 for (auto i : range(N)) {
115 long ind = (i == N - 1) ? 0 : i + 1;
116 fsl[i] = segment_t{sl[i].tau_cdag, sl[ind].tau_c, sl[i].J_cdag, sl[ind].J_c};
117 }
118 return fsl;
119 }
120
121 // ---------------------------
122
123 // Overlap between segment and a list of segments.
124 double overlap(std::vector<segment_t> const &seglist, segment_t const &seg) {
125 if (seglist.empty()) return 0;
126 // If seg is cyclic, need to split it because of the condition in the for later
127 if (is_cyclic(seg)) {
128 auto [sl, sr] = split_cyclic_segment(seg);
129 return overlap(seglist, sl) + overlap(seglist, sr);
130 }
131
132 // Compute overlap with all segments
133 double result = 0;
134 // first loop on all segment but the last one
135 auto last = seglist.end() - 1;
136 for (auto it = find_segment_left(seglist, seg); it != last and it->tau_c > seg.tau_cdag; ++it) //
137 result += overlap(*it, seg);
138
139 // the last can be cyclic, hence be unreached due to it->tau_c condition
140 // nb : overlap is ok to call on cyclic segment
141 result += overlap(*last, seg);
142 return result;
143 }
144
145 // ---------------------------
146
147 // Checks if segment is insertable to a given color
148 bool is_insertable_into(segment_t const &seg, std::vector<segment_t> const &seglist) {
149 if (seglist.empty()) return true;
150
151 // If seg is cyclic, split it
152 if (is_cyclic(seg)) {
153 auto [sl, sr] = split_cyclic_segment(seg);
154 return is_insertable_into(sl, seglist) and is_insertable_into(sr, seglist);
155 }
156
157 // R is the iterator on the segment strictly after seg or end.
158 // L the segment before or begin
159 // Then the segment is insertable iif it does not overlap with L not with R (if not end)
160 // Proof : it overlaps with any segment before of equal L iff it does with L
161 // it overlaps with any segment after of equal L iif it does with R
162 // see all cases.
163 // 1- L------ R----- : s in [L,R]
164 // s------
165 auto R = std::upper_bound(seglist.begin(), seglist.end(), seg);
166 auto L = (R == seglist.begin()) ? R : R - 1;
167 if (not disjoint(seg, *L)) return false;
168 if (R != seglist.end() and not disjoint(seg, *R)) return false;
169 // We must recheck the last segment as it may be cyclic (it might also have been R, in which case it is superfluous but ok)
170 if (not disjoint(seg, seglist.back())) return false;
171 return true;
172 }
173 // ---------------------------
174 // FIXME : do we have TESTS ???
175 // Find the indices of the segments whose cdag are in ]wtau_left,wtau_right[
176 std::vector<long> cdag_in_window(tau_t const &wtau_left, tau_t const &wtau_right,
177 std::vector<segment_t> const &seglist) {
178 if (seglist.empty()) return {}; // should never happen, but protect
179
180 if (wtau_left < wtau_right) {
181 auto left_list = cdag_in_window(tau_t::beta(), wtau_right, seglist);
182 auto right_list = cdag_in_window(wtau_left, tau_t::zero(), seglist);
183 // concatenate
184 left_list.insert(left_list.end(), right_list.begin(), right_list.end());
185 return left_list;
186 }
187 std::vector<long> found_indices;
188 found_indices.reserve(seglist.size());
189 auto last = seglist.end() - 1;
190 auto it = find_segment_left(seglist, segment_t{wtau_left, wtau_left});
191 for (; it->tau_cdag > wtau_right and it != last; ++it)
192 if (it->tau_cdag < wtau_left) found_indices.push_back(std::distance(seglist.cbegin(), it));
193
194 // Check separately for last segment (may be cyclic)
195 if (seglist.back().tau_cdag < wtau_left and seglist.back().tau_cdag > wtau_right)
196 found_indices.push_back(seglist.size() - 1);
197 return found_indices;
198 }
199
200 // ---------------------------
201
202 // Contribution of the dynamical interaction kernel K to the overlap between a segment and a list of segments.
203 // Computes the sum of the s_a s_b K(tau_a - tau_b) where s_a is 1 for cdag and - 1 for c
204 double K_overlap(std::vector<segment_t> const &seglist, tau_t const &tau_c, tau_t const &tau_cdag,
205 gf<imtime, matrix_valued> const &K, int c1, int c2) {
206
207 auto Ks = slice_target_to_scalar(K, c1, c2);
208
209 // seglist empty covered by the loop
210 double result = 0;
211 for (auto const &s : seglist) {
212 result += real(Ks(double(tau_c - s.tau_c)) + Ks(double(tau_cdag - s.tau_cdag)) - Ks(double(tau_cdag - s.tau_c))
213 - Ks(double(tau_c - s.tau_cdag)));
214 }
215 return result;
216 }
217
218 // ---------------------------
219
220 // Contribution of the dynamical interaction kernel K to the overlap between an operator and a list of segments.
221 // Computes the sum of the s_a s_b K(tau_a - tau_b) where s_a is 1 for cdag and - 1 for c
222 double K_overlap(std::vector<segment_t> const &seglist, tau_t const &tau, bool is_c,
223 gf<imtime, matrix_valued> const &K, int c1, int c2) {
224 auto Ks = slice_target_to_scalar(K, c1, c2);
225
226 double result = 0;
227 // The order of the times is important for the measure of F
228 for (auto const &s : seglist) { result += real(Ks(double(s.tau_c - tau)) - Ks(double(s.tau_cdag - tau))); }
229 return is_c ? result : -result;
230 }
231
232 // ---------------------------
233
234 // List of operators containing all colors.
235 // Time are ordered in decreasing order, in agreement with the whole physic literature.
236 std::vector<colored_ops_t> colored_ordered_ops(std::vector<std::vector<segment_t>> const &seglists) {
237 int c = 0; // index of color
238 std::vector<colored_ops_t> ops_list; // list of all the operators
239 for (auto const &seglist : seglists) {
240 for (auto const &s : seglist) {
241 ops_list.push_back({s.tau_c, c, false});
242 ops_list.push_back({s.tau_cdag, c, true});
243 if (is_cyclic(s)) {
244 ops_list.push_back({tau_t::beta(), c, false});
245 ops_list.push_back({tau_t::zero(), c, true});
246 }
247 }
248 ++c;
249 }
250 std::sort(ops_list.begin(), ops_list.end(), [](const colored_ops_t &a, const colored_ops_t &b) {
251 return b.tau < a.tau; // Note the order of b and a for descending sort
252 });
253 return ops_list;
254 }
255
256 // =================== PRINTING ========================
257
258 std::ostream &operator<<(std::ostream &out, std::vector<segment_t> const &sl) {
259 out << '\n';
260 for (auto const &[i, seg] : itertools::enumerate(sl))
261 out << ". Position " << i << " : [ J:" << seg.J_c << " " << seg.tau_c << ", " << seg.tau_cdag
262 << " J:" << seg.J_cdag << "]\n";
263 return out;
264 }
265
266 // ---------------------------
267
268 std::ostream &operator<<(std::ostream &out, configuration_t const &config) {
269 for (auto const &[c, sl] : itertools::enumerate(config.seglists)) {
270 out << '\n';
271 for (auto const &[i, seg] : itertools::enumerate(sl))
272 out << "Color " << c << ". Position " << i << " : [ J:" << seg.J_c << " " << seg.tau_c << ", " << seg.tau_cdag
273 << " J:" << seg.J_cdag << "]\n";
274 }
275 out << "\nSpin lines : \n";
276 for (auto const &[i, line] : itertools::enumerate(config.Jperp_list)) {
277 out << "S_minus : [" << line.tau_Sminus << "] S_plus : [" << line.tau_Splus << "]\n";
278 }
279 return out;
280 }
281
282 // ---------------------------
283
284 std::ostream &operator<<(std::ostream &out, std::vector<colored_ops_t> const &col) {
285 for (auto const &[i, co] : itertools::enumerate(col))
286 out << "\n"
287 << "i: " << i << ", tau: " << co.tau << ", color: " << co.color << ", " << (co.is_cdag ? "cdag" : "c");
288 return out;
289 }
290
291} // namespace triqs_ctseg
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