TRIQS/triqs_cthyb 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
shift.cpp
1/*******************************************************************************
2 *
3 * TRIQS: a Toolbox for Research in Interacting Quantum Systems
4 *
5 * Copyright (C) 2014, P. Seth, I. Krivenko, M. Ferrero and O. Parcollet
6 *
7 * TRIQS is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later
10 * version.
11 *
12 * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 * details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * TRIQS. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ******************************************************************************/
21
22#include "./shift.hpp"
23
24namespace triqs_cthyb {
25
26 histogram *move_shift_operator::add_histo(std::string const &name, histo_map_t *histos) {
27 if (!histos) return nullptr;
28 auto new_histo = histos->insert({name, {.0, config.beta(), 100}});
29 return &(new_histo.first->second);
30 }
31
32 move_shift_operator::move_shift_operator(qmc_data &data, mc_tools::random_generator &rng, histo_map_t *histos)
33 : data(data),
34 config(data.config),
35 rng(rng),
36 histo_proposed(add_histo("shift_length_proposed", histos)),
37 histo_accepted(add_histo("shift_length_accepted", histos)),
38 block_index(0) {}
39
40 mc_weight_t move_shift_operator::attempt() {
41
42#ifdef EXT_DEBUG
43 std::cerr << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
44 std::cerr << "In config " << config.get_id() << std::endl;
45 std::cerr << "* Attempt for move_shift_operator ";
46#endif
47
48 // --- Choose an operator in configuration to shift at random
49 // By choosing an *operator* in config directly, not bias based on det size introduced
50 auto config_size = config.size();
51 if (config_size == 0) {
52#ifdef EXT_DEBUG
53 std::cerr << "(empty configuration)" << std::endl;
54 block_index = -1;
55#endif
56 return 0;
57 }
58 const int op_pos_in_config = rng(config_size);
59
60 // --- Find operator (and its characteristics) from the configuration
61 auto itconfig = config.begin();
62 for (int i = 0; i < op_pos_in_config; ++i, ++itconfig)
63 ; // Get to right position in config
64 tau_old = (*itconfig).first;
65 op_old = (*itconfig).second;
66 block_index = op_old.block_index;
67 auto is_dagger = op_old.dagger;
68
69#ifdef EXT_DEBUG
70 std::cerr << "(block " << block_index << ")" << std::endl;
71#endif
72
73 // Properties corresponding to det
74 auto &det = data.dets[block_index];
75 auto det_size = det.size();
76 if (det_size == 0) return 0; // nothing to shift
77
78 // Construct new operator
79 // Choose a new inner index (this is done here for compatibility)
80 auto inner_new = rng(data.n_inner[block_index]);
81 op_new = op_desc{block_index, inner_new, is_dagger, data.linindex[std::make_pair(block_index, inner_new)]};
82
83 // --- Determine new time to shift the operator to.
84 // The time must fall in the range between the closest operators on the left and
85 // right belonging to the same block. First determine these.
86
87 time_pt tR, tL;
88 int ic_dag = 0, ic = 0;
89 int op_pos_in_det;
90
91 if (det_size > 1) {
92
93 // Get the position op_pos_in_det of op_old in the det.
94 // Find the c and c_dag operators at the right of op_old (at smaller times)
95 // They could be the last entries (earliest times)
96
97 for (ic_dag = 0; ic_dag < det_size; ++ic_dag) { // c_dag
98 if (det.get_x(ic_dag).first < tau_old) break;
99 }
100 for (ic = 0; ic < det_size; ++ic) { // c
101 if (det.get_y(ic).first < tau_old) break;
102 }
103
104 op_pos_in_det = (is_dagger ? ic_dag : ic); // This finds the operator on the right
105 --op_pos_in_det; // Rewind by one to find the operator
106
107 // Find the times of the operator at the right of op_old with cyclicity
108 auto tRdag = (ic_dag != det_size ? det.get_x(ic_dag).first : det.get_x(0).first);
109 auto tRnodag = (ic != det_size ? det.get_y(ic).first : det.get_y(0).first);
110 // Then deduce the closest one and put its distance to op_old in tR
111 tR = ((tau_old - tRdag) > (tau_old - tRnodag) ? tRnodag : tRdag);
112
113 // Reset iterator to op_old position
114 if (is_dagger)
115 --ic_dag;
116 else
117 --ic;
118
119 // Find the times of the operator at the left of op_old with cyclicity
120 auto tLdag = (ic_dag != 0 ? det.get_x(--ic_dag).first : det.get_x(det_size - 1).first);
121 auto tLnodag = (ic != 0 ? det.get_y(--ic).first : det.get_y(det_size - 1).first);
122 // Then deduce the closest one and put its distance to op_old in tL
123 tL = ((tLdag - tau_old) > (tLnodag - tau_old) ? tLnodag : tLdag);
124 // Choose new random time
125 tau_new = tR + data.tau_seg.get_random_pt(rng, tL - tR);
126
127 } else { // det_size = 1
128
129 op_pos_in_det = 0;
130 // Choose new random time, can be anywhere between beta and 0
131 tau_new = data.tau_seg.get_random_pt(rng);
132 }
133
134 // Record the length of the proposed shift
135 dtau = double(tau_new - tau_old);
136 if (histo_proposed) *histo_proposed << dtau;
137
138#ifdef EXT_DEBUG
139 std::cerr << "* Proposing to shift:" << std::endl;
140 std::cerr << op_old << " tau = " << tau_old << std::endl;
141 std::cerr << " to " << std::endl;
142 std::cerr << op_new << " tau = " << tau_new << std::endl;
143#endif
144
145 // --- Modify the tree
146
147 // Mark the operator at original time for deletion in the tree
148 data.imp_trace.try_delete(op_pos_in_det, block_index, is_dagger);
149
150 // Try to insert the new operator at shifted time in the tree
151 try {
152 data.imp_trace.try_insert(tau_new, op_new);
153 } catch (rbt_insert_error const &) {
154 std::cerr << "Insert error : recovering ... " << std::endl;
155 data.imp_trace.cancel_delete();
156 data.imp_trace.cancel_insert();
157 std::cerr << "Insert error : recovered ... " << std::endl;
158 return 0;
159 }
160
161 // --- Compute the det ratio
162
163 // Do we need to roll the determinant?
164 roll_direction = det_type::None;
165
166 // Check if we went through \tau = 0 or \tau = \beta
167 if (det_size > 1) {
168 if ((tau_old > tL) && (tau_new < tL)) roll_direction = (is_dagger ? det_type::Up : det_type::Left);
169 if ((tau_old < tL) && (tau_new > tL)) roll_direction = (is_dagger ? det_type::Down : det_type::Right);
170 }
171
172 // Replace old row/column with new operator time/inner_index. Returns the ratio of dets (Cf det_manip doc).
173 auto det_ratio = (is_dagger ? det.try_change_row(op_pos_in_det, {tau_new, op_new.inner_index}) :
174 det.try_change_col(op_pos_in_det, {tau_new, op_new.inner_index}));
175
176 // for quick abandon
177 double random_number = rng.preview();
178 if (random_number == 0.0) return 0;
179 double p_yee = std::abs(det_ratio / data.atomic_weight);
180
181 // --- Compute the atomic_weight ratio
182 std::tie(new_atomic_weight, new_atomic_reweighting) = data.imp_trace.compute(p_yee, random_number);
183 if (new_atomic_weight == 0.0) {
184#ifdef EXT_DEBUG
185 std::cerr << "atomic_weight == 0" << std::endl;
186#endif
187 return 0;
188 }
189 auto atomic_weight_ratio = new_atomic_weight / data.atomic_weight;
190 if (!isfinite(atomic_weight_ratio))
191 TRIQS_RUNTIME_ERROR << "atomic_weight_ratio not finite " << new_atomic_weight << " " << data.atomic_weight << " "
192 << new_atomic_weight / data.atomic_weight << " in config " << config.get_id();
193
194 // --- Compute the weight
195 mc_weight_t p = atomic_weight_ratio * det_ratio;
196
197#ifdef EXT_DEBUG
198 std::cerr << "Trace ratio: " << atomic_weight_ratio << '\t';
199 std::cerr << "Det ratio: " << det_ratio << '\t';
200 std::cerr << "Weight: " << p << std::endl;
201 std::cerr << "p_yee * newtrace: " << p_yee * new_atomic_weight << std::endl;
202#endif
203
204 return p;
205 }
206
207 mc_weight_t move_shift_operator::accept() {
208
209 // Update the tree
210 data.imp_trace.confirm_shift();
211
212 // Update the configuration
213 config.erase(tau_old);
214 config.insert(tau_new, op_new);
215 config.finalize();
216
217 // Update the determinant
218 data.dets[block_index].complete_operation();
219 data.update_sign();
220
221 data.atomic_weight = new_atomic_weight;
222 data.atomic_reweighting = new_atomic_reweighting;
223
224 if (histo_accepted) *histo_accepted << dtau;
225
226 auto result = data.current_sign / data.old_sign * data.dets[block_index].roll_matrix(roll_direction);
227
228#ifdef EXT_DEBUG
229 std::cerr << "* Move move_shift_operator accepted" << std::endl;
230 std::cerr << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
231 check_det_sequence(data.dets[block_index], config.get_id());
232#endif
233
234 return result;
235 }
236
237 void move_shift_operator::reject() {
238
239 config.finalize();
240 data.imp_trace.cancel_shift();
241 data.dets[block_index].reject_last_try();
242
243#ifdef EXT_DEBUG
244 std::cerr << "* Move move_shift_operator rejected" << std::endl;
245 std::cerr << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
246 if (block_index != -1) check_det_sequence(data.dets[block_index], config.get_id());
247#endif
248 }
249}