TRIQS/triqs_cthyb 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
qmc_data.hpp
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#pragma once
22#include "impurity_trace.hpp"
23#include <triqs/gfs.hpp>
24#include <triqs/mesh.hpp>
25#include <triqs/det_manip.hpp>
26
27namespace triqs_cthyb {
28 using namespace triqs::gfs;
29 using namespace triqs::mesh;
30 using namespace nda;
31
32 /************************
33 * The Monte Carlo data
34 ***********************/
35 struct qmc_data {
36
37 configuration config; // Configuration
38 time_segment tau_seg;
39 std::map<std::pair<int, int>, int> linindex; // Linear index constructed from block and inner indices
40 atom_diag const &h_diag; // Diagonalization of the atomic problem
41 mutable impurity_trace imp_trace; // Calculator of the trace
42 std::vector<int> n_inner;
43 block_gf<imtime, delta_target_t> delta; // Hybridization function
44
46 struct delta_block_adaptor {
47 gf<imtime, delta_target_t> delta_block; // make a copy. Needed in the real case anyway.
48
49 delta_block_adaptor(gf_const_view<imtime, delta_target_t> delta_block) : delta_block(std::move(delta_block)) {}
50 delta_block_adaptor(delta_block_adaptor const &) = default;
51 delta_block_adaptor(delta_block_adaptor &&) = default;
52 delta_block_adaptor &operator=(delta_block_adaptor const &) = delete;
53 delta_block_adaptor &operator=(delta_block_adaptor &&) = default;
54
55 det_scalar_t operator()(std::pair<time_pt, int> const &x, std::pair<time_pt, int> const &y) const {
56 det_scalar_t res = delta_block[closest_mesh_pt(double(x.first - y.first))](x.second, y.second);
57 return (x.first >= y.first ? res : -res); // x,y first are time_pt, wrapping is automatic in the - operation, but need to
58 // compute the sign
59 }
60
61 friend void swap(delta_block_adaptor &dba1, delta_block_adaptor &dba2) noexcept { std::swap(dba1.delta_block, dba2.delta_block); }
62 };
63
64 std::vector<det_manip::det_manip<delta_block_adaptor>> dets; // The determinants
65 int current_sign, old_sign; // Permutation prefactor
66 h_scalar_t atomic_weight; // The current value of the trace or norm
67 h_scalar_t atomic_reweighting; // The current value of the reweighting
68
69 // Construction
70 qmc_data(double beta, solve_parameters_t const &p, atom_diag const &h_diag, std::map<std::pair<int, int>, int> linindex,
71 block_gf_const_view<imtime> delta, std::vector<int> n_inner, histo_map_t *histo_map)
72 : config(beta),
73 tau_seg(beta),
74 linindex(linindex),
75 h_diag(h_diag),
76 imp_trace(beta, h_diag, histo_map, p.use_norm_as_weight, p.measure_density_matrix, p.performance_analysis),
77 n_inner(n_inner),
78 delta(map([](gf_const_view<imtime> d) { return real(d); }, delta)),
79 current_sign(1),
80 old_sign(1) {
81
82 std::vector<std::vector<std::pair<time_pt, int>>> X(delta.size()), Y(delta.size());
83
84 // When initial_configuration is given, fill imp_trace and config accordingly
85 if (p.initial_configuration) {
86
87 // check that the current beta and beta of the initial configuration are equal
88 if (p.initial_configuration->beta() != beta) {
89 TRIQS_RUNTIME_ERROR << "Beta of initial configuration not equal current beta: " << p.initial_configuration->beta() << " != " << beta;
90 }
91
92 for (auto const &[tau, op] : p.initial_configuration.value()) {
93 // check that the block structure is consistent
94 if (op.block_index >= delta.size() || op.inner_index >= n_inner[op.block_index]
95 || op.linear_index != linindex.at({op.block_index, op.inner_index})) {
96 TRIQS_RUNTIME_ERROR << "Inconsistency in the block structure of the initial configuration";
97 }
98
99 // insert operators into the impurity trace
100 imp_trace.try_insert(tau, op);
101 imp_trace.confirm_insert();
102
103 // store tau points and inner block indices for initializing the determinants later
104 if (op.dagger)
105 X[op.block_index].emplace_back(tau, op.inner_index);
106 else
107 Y[op.block_index].emplace_back(tau, op.inner_index);
108
109 // insert the operator into the configuration
110 config.insert(tau, op);
111 }
112
113 for (auto bl : range(delta.size())) {
114 if (X[bl].size() != Y[bl].size())
115 TRIQS_RUNTIME_ERROR << "Unequal number of c_dag and c operators in bl " << bl << " of the initial configuration";
116 }
117 }
118
119 // initialize the atomic weight
120 std::tie(atomic_weight, atomic_reweighting) = imp_trace.compute();
121
122 // initialize hybridization determinants
123 dets.clear();
124 dets.reserve(delta.size());
125 for (auto const &bl : range(delta.size())) {
126#ifdef HYBRIDISATION_IS_COMPLEX
127 auto delta_functor = delta_block_adaptor(delta[bl]);
128#else
129 if (!is_gf_real(delta[bl], 1e-10)) {
130 if (p.verbosity >= 2) {
131 std::cerr << "WARNING: The Delta(tau) block number " << bl << " is not real in tau space\n";
132 std::cerr << "WARNING: max(Im[Delta(tau)]) = " << max_element(abs(imag(delta[bl].data()))) << "\n";
133 std::cerr << "WARNING: Dissregarding the imaginary component in the calculation.\n";
134 }
135 }
136 auto delta_functor = delta_block_adaptor(real(delta[bl]));
137#endif
138 if (X[bl].empty()) {
139 dets.emplace_back(delta_functor, p.det_init_size);
140 } else {
141 dets.emplace_back(delta_functor, X[bl], Y[bl]);
142 }
143 dets.back().set_singular_threshold(p.det_singular_threshold);
144 dets.back().set_n_operations_before_check(p.det_n_operations_before_check);
145 dets.back().set_precision_warning(p.det_precision_warning);
146 dets.back().set_precision_error(p.det_precision_error);
147 }
148 update_sign();
149 }
150
151 qmc_data(qmc_data const &) = delete; // Member imp_trace is not copyable
152 qmc_data &operator=(qmc_data const &) = delete;
153
154 void update_sign() {
155
156 int s = 0;
157 size_t num_blocks = dets.size();
158 std::vector<int> n_op_with_a_equal_to(num_blocks, 0), n_ndag_op_with_a_equal_to(num_blocks, 0);
159
160 // In this first part we compute the sign to bring the configuration to
161 // d^_1 d^_1 d^_1 ... d_1 d_1 d_1 d^_2 d^_2 ... d_2 d_2 ... d^_n .. d_n
162
163 // loop over the operators "op" in the trace (right to left)
164 for (auto const &op : config) {
165
166 // how many operators with an 'a' larger than "op" are there on the left of "op"?
167 for (int a = op.second.block_index + 1; a < num_blocks; ++a) s += n_op_with_a_equal_to[a];
168 n_op_with_a_equal_to[op.second.block_index]++;
169
170 // if "op" is not a dagger how many operators of the same a but with a dagger are there on his right?
171 if (op.second.dagger)
172 s += n_ndag_op_with_a_equal_to[op.second.block_index];
173 else
174 n_ndag_op_with_a_equal_to[op.second.block_index]++;
175 }
176
177 // Now we compute the sign to bring the configuration to
178 // d_1 d^_1 d_1 d^_1 ... d_1 d^_1 ... d_n d^_n ... d_n d^_n
179 for (int block_index = 0; block_index < num_blocks; block_index++) {
180 int n = dets[block_index].size();
181 s += n * (n + 1) / 2;
182 }
183
184 old_sign = current_sign;
185 current_sign = (s % 2 == 0 ? 1 : -1);
186 }
187 };
188
189 //--------- DEBUG ---------
190
191 using det_type = det_manip::det_manip<qmc_data::delta_block_adaptor>;
192
193 // Print taus of operator sequence in dets
194 inline void print_det_sequence(qmc_data const &data) {
195 int i;
196 int block_index;
197 for (block_index = 0; block_index < data.dets.size(); ++block_index) {
198 auto det = data.dets[block_index];
199 if (det.size() == 0) return;
200 std::cout << "BLOCK = " << block_index << std::endl;
201 for (i = 0; i < det.size(); ++i) { // c_dag
202 std::cout << " ic_dag = " << i << ": tau = " << det.get_x(i).first << std::endl;
203 }
204 for (i = 0; i < det.size(); ++i) { // c
205 std::cout << " ic = " << i << ": tau = " << det.get_y(i).first << std::endl;
206 }
207 }
208 }
209
210 inline void print_det_sequence(det_type const &det) {
211 int i;
212 for (i = 0; i < det.size(); ++i) { // c_dag
213 std::cout << " ic_dag = " << i << ": tau = " << det.get_x(i).first << std::endl;
214 }
215 for (i = 0; i < det.size(); ++i) { // c
216 std::cout << " ic = " << i << ": tau = " << det.get_y(i).first << std::endl;
217 }
218 }
219
220 // Check if dets are correctly ordered, otherwise complain
221 inline void check_det_sequence(det_type const &det, int config_id) {
222 if (det.size() == 0) return;
223 auto tau = det.get_x(0).first;
224 for (auto ic_dag = 0; ic_dag < det.size(); ++ic_dag) { // c_dag
225 if (tau < det.get_x(ic_dag).first) {
226 std::cout << "ERROR in det order in config " << config_id << std::endl;
227 print_det_sequence(det);
228 TRIQS_RUNTIME_ERROR << "Det ordering wrong: tau(ic_dag = " << ic_dag << ") = " << double(det.get_x(ic_dag).first);
229 }
230 tau = det.get_x(ic_dag).first;
231 }
232 tau = det.get_y(0).first;
233 for (auto ic = 0; ic < det.size(); ++ic) { // c
234 if (tau < det.get_y(ic).first) {
235 std::cout << "ERROR in det order in config " << config_id << std::endl;
236 print_det_sequence(det);
237 TRIQS_RUNTIME_ERROR << "Det ordering wrong: tau(ic = " << ic << ") = " << double(det.get_y(ic).first);
238 }
239 tau = det.get_y(ic).first;
240 }
241 }
242} // namespace triqs_cthyb
This callable object adapts the Delta function for the call of the det.
Definition qmc_data.hpp:46
Parameters passed to the solve method of the solver class.