TRIQS/triqs_cthyb 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
double_insert.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 "./double_insert.hpp"
23
24namespace triqs_cthyb {
25
26 histogram *move_insert_c_c_cdag_cdag::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_insert_c_c_cdag_cdag::move_insert_c_c_cdag_cdag(int block_index1, int block_index2, int block_size1, int block_size2,
33 std::string const &block_name1, std::string const &block_name2, qmc_data &data,
34 mc_tools::random_generator &rng, histo_map_t *histos)
35 : data(data),
36 config(data.config),
37 rng(rng),
38 block_index1(block_index1),
39 block_index2(block_index2),
40 block_size1(block_size1),
41 block_size2(block_size2),
42 histo_proposed1(add_histo("double_insert_length_proposed_" + block_name1, histos)),
43 histo_proposed2(add_histo("double_insert_length_proposed_" + block_name2, histos)),
44 histo_accepted1(add_histo("double_insert_length_accepted_" + block_name1, histos)),
45 histo_accepted2(add_histo("double_insert_length_accepted_" + block_name2, histos)) {}
46
47 mc_weight_t move_insert_c_c_cdag_cdag::attempt() {
48
49#ifdef EXT_DEBUG
50 std::cerr << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
51 std::cerr << "In config " << config.get_id() << std::endl;
52 std::cerr << "* Attempt for move_insert_c_c_cdag_cdag (blocks " << block_index1 << ", " << block_index2 << ")" << std::endl;
53#endif
54
55 // Pick up the value of alpha and choose the operators
56 auto rs1 = rng(block_size1), rs2 = rng(block_size1), rs3 = rng(block_size2), rs4 = rng(block_size2);
57 op1 = op_desc{block_index1, rs1, true, data.linindex[std::make_pair(block_index1, rs1)]};
58 op2 = op_desc{block_index1, rs2, false, data.linindex[std::make_pair(block_index1, rs2)]};
59 op3 = op_desc{block_index2, rs3, true, data.linindex[std::make_pair(block_index2, rs3)]};
60 op4 = op_desc{block_index2, rs4, false, data.linindex[std::make_pair(block_index2, rs4)]};
61
62 // Choice of times for insertion. Find the time as double and them put them on the grid.
63 tau1 = data.tau_seg.get_random_pt(rng);
64 tau2 = data.tau_seg.get_random_pt(rng);
65 tau3 = data.tau_seg.get_random_pt(rng);
66 tau4 = data.tau_seg.get_random_pt(rng);
67 if ((tau1 == tau3) or (tau2 == tau4)) return 0; // trying to insert/remove two operators at exactly the same time
68
69#ifdef EXT_DEBUG
70 std::cerr << "* Proposing to insert:" << std::endl;
71 std::cerr << op1 << " at " << tau1 << std::endl;
72 std::cerr << op2 << " at " << tau2 << std::endl;
73 std::cerr << op3 << " at " << tau3 << std::endl;
74 std::cerr << op4 << " at " << tau4 << std::endl;
75#endif
76
77 // record the length of the proposed insertion
78 dtau1 = double(tau2 - tau1);
79 dtau2 = double(tau4 - tau3);
80 if (histo_proposed1) {
81 *histo_proposed1 << dtau1;
82 *histo_proposed2 << dtau2;
83 }
84
85 // Insert the operators op1, op2, op3, op4 at time tau1, tau2, tau3, tau4
86 // 1- In the very exceptional case where the insert has failed because an operator is already sitting here
87 // (cf std::map doc for insert return), we reject the move.
88 // 2- If ok, we store the iterator to the inserted operators for later removal in reject if necessary
89 try {
90 data.imp_trace.try_insert(tau1, op1);
91 data.imp_trace.try_insert(tau2, op2);
92 data.imp_trace.try_insert(tau3, op3);
93 data.imp_trace.try_insert(tau4, op4);
94 } catch (rbt_insert_error const &) {
95 std::cerr << "Insert error : recovering ... " << std::endl;
96 data.imp_trace.cancel_insert();
97 return 0;
98 }
99
100 // Computation of det ratio
101 auto &det1 = data.dets[block_index1];
102 auto &det2 = data.dets[block_index2];
103 int det1_size = det1.size();
104 int det2_size = det2.size();
105 det_scalar_t det_ratio;
106
107 // Find the position for insertion in the determinant
108 // NB : the determinant stores the C in decreasing time order.
109 int num_c_dag1, num_c1, num_c_dag2, num_c2;
110 for (num_c_dag1 = 0; num_c_dag1 < det1_size; ++num_c_dag1) {
111 if (det1.get_x(num_c_dag1).first < tau1) break;
112 }
113 for (num_c1 = 0; num_c1 < det1_size; ++num_c1) {
114 if (det1.get_y(num_c1).first < tau2) break;
115 }
116 for (num_c_dag2 = 0; num_c_dag2 < det2_size; ++num_c_dag2) {
117 if (det2.get_x(num_c_dag2).first < tau3) break;
118 }
119 for (num_c2 = 0; num_c2 < det2_size; ++num_c2) {
120 if (det2.get_y(num_c2).first < tau4) break;
121 }
122
123 // Insert in the det. Returns the ratio of dets (Cf det_manip doc).
124 if (block_index1 == block_index2) {
125 // The determinant positions that need to be passed to det_manip are those in the *final* det of size N+2.
126 // Shift the operator at the smaller time one step further in the determinant to account for the larger operator.
127 // This shfit must be done in general, and not only when num_c(_dag)1 and num_c(dag_)2 are the same!!
128 if (tau1 < tau3)
129 num_c_dag1++;
130 else
131 num_c_dag2++;
132 if (tau2 < tau4)
133 num_c1++;
134 else
135 num_c2++;
136 det_ratio = det1.try_insert2(num_c_dag1, num_c_dag2, num_c1, num_c2, {tau1, op1.inner_index}, {tau3, op3.inner_index}, {tau2, op2.inner_index},
137 {tau4, op4.inner_index});
138 } else {
139 auto det_ratio1 = det1.try_insert(num_c_dag1, num_c1, {tau1, op1.inner_index}, {tau2, op2.inner_index});
140 auto det_ratio2 = det2.try_insert(num_c_dag2, num_c2, {tau3, op3.inner_index}, {tau4, op4.inner_index});
141 det_ratio = det_ratio1 * det_ratio2;
142 }
143
144 // proposition probability
145 mc_weight_t t_ratio;
146 if (block_index1 == block_index2) {
147 // (ways to insert 4 operators in det1)/((ways to remove 4 operators from det that is larger by two))
148 // Here, we use the fact that the two cdag/c proposed to be removed in the det can be at the same
149 // positions in the det, and thus remove prob is NOT (detsize+2)*(detsize+1)
150 t_ratio = std::pow(block_size1 * config.beta() / double(det1.size() + 2), 4);
151 } else {
152 // product of two separate inserts, one in det1 and one in det2
153 t_ratio =
154 std::pow(block_size1 * config.beta() / double(det1.size() + 1), 2) * std::pow(block_size2 * config.beta() / double(det2.size() + 1), 2);
155 }
156
157 // For quick abandon
158 double random_number = rng.preview();
159 if (random_number == 0.0) return 0;
160 double p_yee = std::abs(t_ratio * det_ratio / data.atomic_weight);
161
162 // computation of the new atomic_weight after insertion
163 std::tie(new_atomic_weight, new_atomic_reweighting) = data.imp_trace.compute(p_yee, random_number);
164 if (new_atomic_weight == 0.0) {
165#ifdef EXT_DEBUG
166 std::cerr << "atomic_weight == 0" << std::endl;
167#endif
168 return 0;
169 }
170 auto atomic_weight_ratio = new_atomic_weight / data.atomic_weight;
171 if (!isfinite(atomic_weight_ratio))
172 TRIQS_RUNTIME_ERROR << "atomic_weight_ratio not finite " << new_atomic_weight << " " << data.atomic_weight << " "
173 << new_atomic_weight / data.atomic_weight << " in config " << config.get_id();
174
175 mc_weight_t p = atomic_weight_ratio * det_ratio;
176
177#ifdef EXT_DEBUG
178 std::cerr << "Trace ratio: " << atomic_weight_ratio << '\t';
179 std::cerr << "Det ratio: " << det_ratio << '\t';
180 std::cerr << "Prefactor: " << t_ratio << '\t';
181 std::cerr << "Weight: " << p * t_ratio << std::endl;
182 std::cerr << "p_yee * newtrace: " << p_yee * new_atomic_weight << std::endl;
183#endif
184
185 if (!isfinite(p * t_ratio))
186 TRIQS_RUNTIME_ERROR << "p * t_ratio not finite p : " << p << " t_ratio : " << t_ratio << " in config " << config.get_id();
187 return p * t_ratio;
188 }
189
190 mc_weight_t move_insert_c_c_cdag_cdag::accept() {
191
192 // insert in the tree
193 data.imp_trace.confirm_insert();
194
195 // insert in the configuration
196 config.insert(tau1, op1);
197 config.insert(tau2, op2);
198 config.insert(tau3, op3);
199 config.insert(tau4, op4);
200 config.finalize();
201
202 // insert in the determinant
203 if (block_index1 == block_index2) {
204 data.dets[block_index1].complete_operation();
205 } else {
206 data.dets[block_index1].complete_operation();
207 data.dets[block_index2].complete_operation();
208 }
209 data.update_sign();
210
211 data.atomic_weight = new_atomic_weight;
212 data.atomic_reweighting = new_atomic_reweighting;
213
214 if (histo_accepted1) {
215 *histo_accepted1 << dtau1;
216 *histo_accepted2 << dtau2;
217 }
218
219#ifdef EXT_DEBUG
220 std::cerr << "* Move move_insert_c_c_cdag_cdag accepted" << std::endl;
221 std::cerr << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
222 check_det_sequence(data.dets[block_index1], config.get_id());
223 check_det_sequence(data.dets[block_index2], config.get_id());
224#endif
225
226 return data.current_sign / data.old_sign;
227 }
228
229 //----------------
230
231 void move_insert_c_c_cdag_cdag::reject() {
232
233 config.finalize();
234 data.imp_trace.cancel_insert();
235 if (block_index1 == block_index2) {
236 data.dets[block_index1].reject_last_try();
237 } else {
238 data.dets[block_index1].reject_last_try();
239 data.dets[block_index2].reject_last_try();
240 }
241
242#ifdef EXT_DEBUG
243 std::cerr << "* Move move_insert_c_c_cdag_cdag rejected" << std::endl;
244 std::cerr << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
245 check_det_sequence(data.dets[block_index1], config.get_id());
246 check_det_sequence(data.dets[block_index2], config.get_id());
247#endif
248 }
249}