TRIQS/triqs_cthyb 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
global.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 "./global.hpp"
23
24namespace triqs_cthyb {
25
26 move_global::move_global(std::string const &name, indices_map_t const &substitution_map, qmc_data &data, mc_tools::random_generator &rng)
27 : name(name),
28 data(data),
29 config(data.config),
30 rng(rng),
31 substitute_c(data.linindex.size()),
32 substitute_c_dag(data.linindex.size()),
33 x(data.dets.size()),
34 y(data.dets.size()) {
35
36 auto const &fops = data.h_diag.get_fops();
37
38 // Inverse of data.linindex
39 std::vector<std::pair<int, int>> lin_to_block_inner(data.linindex.size());
40 for (auto const &l : data.linindex) lin_to_block_inner[l.second] = l.first;
41
42 bool identity = true;
43 for (int lin = 0; lin < lin_to_block_inner.size(); ++lin) {
44 int new_lin, new_block, new_inner;
45
46 // Does operator with linear index lin have a mapping in substitution_map?
47 auto it = std::find_if(std::begin(substitution_map), std::end(substitution_map),
48 [&fops, lin](indices_map_t::value_type const &kv) { return fops[kv.first] == lin; });
49
50 // If it does not, it is substituted by itself (subst_linear = lin)
51 new_lin = (it != std::end(substitution_map)) ? fops[it->second] : lin;
52 std::tie(new_block, new_inner) = lin_to_block_inner[new_lin];
53
54 if (new_lin != lin) {
55 identity = false;
56 affected_blocks.insert(lin_to_block_inner[lin].first);
57 affected_blocks.insert(new_block);
58 }
59
60 substitute_c[lin] = op_desc{new_block, new_inner, false, new_lin};
61 substitute_c_dag[lin] = op_desc{new_block, new_inner, true, new_lin};
62 }
63
64 if (identity) std::cerr << "WARNING: global move '" << name << "' changes no operator indices, therefore is useless." << std::endl;
65 }
66
67 mc_weight_t move_global::attempt() {
68
69#ifdef EXT_DEBUG
70 std::cerr << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
71 std::cerr << "In config " << config.get_id() << std::endl;
72 std::cerr << "* Attempt for move move_global (" << name << ")" << std::endl;
73#endif
74
75 updated_ops.clear();
76 for (auto const &o : data.config) {
77 auto const &tau = o.first;
78 auto const &old_op = o.second;
79 auto const &new_op = (old_op.dagger ? substitute_c_dag : substitute_c)[old_op.linear_index];
80 if (old_op.linear_index != new_op.linear_index) updated_ops.emplace(tau, new_op);
81 }
82
83#ifdef EXT_DEBUG
84 std::cerr << updated_ops.size() << " out of " << data.config.size() << " operators can be changed" << std::endl;
85#endif
86
87 // No operators can be updated...
88 if (!updated_ops.size()) return 0;
89
90 // Choose a random number of operators, which will not actually be updated
91 // (we always update at least one operator)
92 int n_no_update = rng(updated_ops.size());
93 // Remove some operators
94 for (int i = 0; i < n_no_update; ++i) {
95 auto it = std::begin(updated_ops);
96 std::advance(it, rng(updated_ops.size()));
97 updated_ops.erase(it);
98 }
99
100#ifdef EXT_DEBUG
101 std::cerr << updated_ops.size() << " operators will actually be changed" << std::endl;
102#endif
103
104 // Derive new arguments of the dets
105 for (auto block_index : affected_blocks) {
106 x[block_index].clear();
107 y[block_index].clear();
108 }
109
110 for (auto const &o : data.config) {
111 auto const &tau = o.first;
112 auto it = updated_ops.find(tau);
113 auto const &new_op = it == updated_ops.end() ? o.second : it->second;
114 (new_op.dagger ? x : y)[new_op.block_index].emplace_back(tau, new_op.inner_index);
115 }
116
117 for (auto block_index : affected_blocks) {
118 // New configuration is not compatible with gf_struct
119 if (x[block_index].size() != y[block_index].size()) return 0;
120 }
121
122 // Try refill determinants
123 mc_weight_t det_ratio = 1;
124 for (auto block_index : affected_blocks) {
125 auto &det = data.dets[block_index];
126 mc_weight_t block_det_ratio = det.try_refill(x[block_index], y[block_index]);
127 if (block_det_ratio == .0) {
128#ifdef EXT_DEBUG
129 std::cerr << "block_det_ratio[" << block_index << "] = 0" << std::endl;
130#endif
131 return 0;
132 }
133 det_ratio *= block_det_ratio;
134 }
135
136 // For quick abandon
137 double random_number = rng.preview();
138 if (random_number == 0.0) return 0;
139 double p_yee = std::abs(det_ratio / data.atomic_weight);
140
141 data.imp_trace.try_replace(updated_ops);
142
143 // computation of the new trace after insertion
144 std::tie(new_atomic_weight, new_atomic_reweighting) = data.imp_trace.compute(p_yee, random_number);
145 if (new_atomic_weight == 0.0) {
146#ifdef EXT_DEBUG
147 std::cerr << "trace == 0" << std::endl;
148#endif
149 return 0;
150 }
151 auto atomic_weight_ratio = new_atomic_weight / data.atomic_weight;
152 if (!isfinite(atomic_weight_ratio))
153 TRIQS_RUNTIME_ERROR << "atomic_weight_ratio not finite " << new_atomic_weight << " " << data.atomic_weight << " "
154 << new_atomic_weight / data.atomic_weight << " in config " << config.get_id();
155
156 mc_weight_t p = atomic_weight_ratio * det_ratio;
157
158#ifdef EXT_DEBUG
159 std::cerr << "Trace ratio: " << atomic_weight_ratio << '\t';
160 std::cerr << "Det ratio: " << det_ratio << '\t';
161 std::cerr << "p_yee: " << p_yee << std::endl;
162 std::cerr << "Weight: " << p << std::endl;
163#endif
164
165 return p;
166 }
167
168 mc_weight_t move_global::accept() {
169
170 for (auto const &o : updated_ops) data.config.replace(o.first, o.second);
171 config.finalize();
172
173 for (auto block_index : affected_blocks) data.dets[block_index].complete_operation();
174
175 data.update_sign();
176 data.atomic_weight = new_atomic_weight;
177 data.atomic_reweighting = new_atomic_reweighting;
178
179 data.imp_trace.confirm_replace();
180
181#ifdef EXT_DEBUG
182 std::cerr << "* Move move_global '" << name << "' accepted" << std::endl;
183 std::cerr << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
184 for (int block_index : affected_blocks) check_det_sequence(data.dets[block_index], config.get_id());
185#endif
186
187 return data.current_sign / data.old_sign;
188 }
189
190 void move_global::reject() {
191
192 config.finalize();
193 data.imp_trace.cancel_replace();
194 for (auto block_index : affected_blocks) data.dets[block_index].reject_last_try();
195
196#ifdef EXT_DEBUG
197 std::cerr << "* Move move_global '" << name << "' rejected" << std::endl;
198 std::cerr << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
199 for (int block_index : affected_blocks) check_det_sequence(data.dets[block_index], config.get_id());
200#endif
201 }
202}