TRIQS/triqs_cthyb 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
solver_core.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 * Copyright (C) 2017, H. UR Strand, P. Seth, I. Krivenko,
7 * M. Ferrero and O. Parcollet
8 *
9 * TRIQS is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * TRIQS. If not, see <http://www.gnu.org/licenses/>.
21 *
22 ******************************************************************************/
23#include "./solver_core.hpp"
24#include "./qmc_data.hpp"
25
26#include <triqs/utility/callbacks.hpp>
27#include <triqs/utility/exceptions.hpp>
28#include <triqs/gfs.hpp>
29#include <triqs/mesh.hpp>
30#include <fstream>
31#include <variant>
32
33#include "./moves/insert.hpp"
34#include "./moves/remove.hpp"
35#include "./moves/double_insert.hpp"
36#include "./moves/double_remove.hpp"
37#include "./moves/shift.hpp"
38#include "./moves/global.hpp"
39#include "./measures/G_tau.hpp"
40#include "./measures/G_l.hpp"
41#include "./measures/O_tau_ins.hpp"
42#include "./measures/perturbation_hist.hpp"
43#include "./measures/density_matrix.hpp"
44#include "./measures/average_sign.hpp"
45#include "./measures/average_order.hpp"
46#include "./measures/auto_corr_time.hpp"
47#ifdef CTHYB_G2_NFFT
48#include "./measures/G2_tau.hpp"
49#include "./measures/G2_iw.hpp"
50#include "./measures/G2_iw_nfft.hpp"
51#include "./measures/G2_iwll.hpp"
52#endif
53#include "./measures/util.hpp"
54
55namespace triqs_cthyb {
56
57 struct index_visitor {
58 std::vector<std::string> indices;
59 void operator()(int i) { indices.push_back(std::to_string(i)); }
60 void operator()(std::string s) { indices.push_back(s); }
61 };
62
64 : beta(p.beta), gf_struct(p.gf_struct), n_iw(p.n_iw), n_tau(p.n_tau), n_l(p.n_l), delta_interface(p.delta_interface), constr_parameters(p) {
65
66 if (p.n_tau < 2 * p.n_iw)
67 TRIQS_RUNTIME_ERROR
68 << "Must use as least twice as many tau points as Matsubara frequencies: n_iw = " << p.n_iw
69 << " but n_tau = " << p.n_tau << ".";
70
71 // Allocate single particle greens functions
72 if (not delta_interface) _G0_iw = block_gf<imfreq>({beta, Fermion, n_iw}, gf_struct);
73 _Delta_tau = block_gf<imtime>({beta, Fermion, n_tau}, gf_struct);
74 }
75
77
78 void solver_core::solve(solve_parameters_t const &solve_parameters_) {
79
80 solve_parameters = solve_parameters_;
81 solve_parameters_t params(solve_parameters_);
82
83 // Merge constr_params and solve_params
84 //params_t params(constr_parameters, solve_parameters);
85
86 // http://patorjk.com/software/taag/#p=display&f=Calvin%20S&t=TRIQS%20cthyb
87 if (params.verbosity >= 2)
88 std::cout << "\n"
89 "╔╦╗╦═╗╦╔═╗ ╔═╗ ┌─┐┌┬┐┬ ┬┬ ┬┌┐ \n"
90 " ║ ╠╦╝║║═╬╗╚═╗ │ │ ├─┤└┬┘├┴┐\n"
91 " ╩ ╩╚═╩╚═╝╚╚═╝ └─┘ ┴ ┴ ┴ ┴ └─┘\n\n";
92
93 // determine basis of operators to use
94 fundamental_operator_set fops;
95 for (auto const &[bl, bl_size] : gf_struct) {
96 for (auto idx : range(bl_size)) { fops.insert(bl, idx); }
97 }
98
99 // setup the linear index map
100 std::map<std::pair<int, int>, int> linindex;
101 int block_index = 0;
102 for (auto const &[bl, bl_size] : gf_struct) {
103 int inner_index = 0;
104 for (auto idx : range(bl_size)) {
105 linindex[std::make_pair(block_index, inner_index)] = fops[{bl, idx}];
106 inner_index++;
107 }
108 block_index++;
109 }
110
111 // Make list of block sizes
112 std::vector<int> n_inner;
113 for (auto const &[bl, bl_size] : gf_struct) { n_inner.push_back(bl_size); }
114
115 if (not delta_interface) {
116
117 // ==== Assert that G0_iw fulfills the fundamental property G(iw)[i,j] = G(-iw)*[j,i] ====
118
119 if (not is_gf_hermitian(_G0_iw.value())) {
120 if (params.verbosity >= 2)
121 std::cout << "!-------------------------------------------------------------------------------------------!\n"
122 "! WARNING: S.G0_iw violates fundamental Green Function property G0(iw)[i,j] = G0(-iw)*[j,i] !\n"
123 "! Symmetrizing S.G0_iw ... !\n"
124 "!-------------------------------------------------------------------------------------------!\n\n";
125 _G0_iw = make_hermitian(_G0_iw.value());
126 }
127
128 // ==== Compute Delta from G0_iw ====
129
130 // Initialize Delta with iw - inv(G0[iw])
131 auto Delta_iw = inverse(_G0_iw.value());
132 for (auto bl : range(gf_struct.size()))
133 for (auto iw : Delta_iw[bl].mesh()) Delta_iw[bl][iw] = iw - Delta_iw[bl][iw];
134
135 // Compute the constant part of Delta
136 Delta_infty_vec = map(
137 // Compute 0th moment of one block
138 [imag_threshold = params.imag_threshold](gf_const_view<imfreq> d) {
139 auto [tail, err] = fit_hermitian_tail(d);
140 if (err > 1e-5) std::cerr << "WARNING: Tail fit in extraction of delta(infty) has large error of: " << err << std::endl;
141 auto Delta_infty = matrix<dcomplex>{tail(0, ellipsis())};
142#ifndef HYBRIDISATION_IS_COMPLEX
143 double max_imag = max_element(abs(imag(Delta_infty)));
144 if (max_imag > imag_threshold)
145 TRIQS_RUNTIME_ERROR << "Largest imaginary element of delta(infty) e.g. of the local part of G0: " << max_imag
146 << ", is larger than the set parameter imag_threshold " << imag_threshold;
147#endif
148 return Delta_infty;
149 },
150 Delta_iw);
151
152 // Subtract constant part from Delta and perform Fourier transform
153 for (auto bl : range(gf_struct.size())) {
154 for (auto iw : Delta_iw[bl].mesh()) Delta_iw[bl][iw] = Delta_iw[bl][iw] - Delta_infty_vec.value()[bl];
155 auto [Delta_tail_b, tail_err] = fit_hermitian_tail(Delta_iw[bl]);
156 _Delta_tau[bl]() = fourier(Delta_iw[bl], Delta_tail_b);
157 }
158
159 // ==== Compute h_loc ====
160
161 _h_loc0 = {};
162
163 // Add non-interacting terms to h_loc
164 for (auto bl : range(gf_struct.size())) {
165 for (auto [n1, n2] : Delta_iw[bl].target_indices()) {
166#ifdef LOCAL_HAMILTONIAN_IS_COMPLEX
167 dcomplex e_ij;
168 double max_imag = max_element(abs(imag(Delta_infty_vec.value()[bl])));
169 if (max_imag > params.imag_threshold)
170 e_ij = Delta_infty_vec.value()[bl](n1, n2);
171 else
172 e_ij = Delta_infty_vec.value()[bl](n1, n2).real();
173#else
174 double e_ij = Delta_infty_vec.value()[bl](n1, n2).real();
175#endif
176 // Set off diagonal terms to 0 if they are below off_diag_threshold
177 if (n1 != n2 && abs(Delta_infty_vec.value()[bl](n1, n2)) < params.off_diag_threshold) e_ij = 0.0;
178
179 auto bl_name = gf_struct[bl].first;
180 _h_loc0 = _h_loc0 + e_ij * c_dag<h_scalar_t>(bl_name, n1) * c<h_scalar_t>(bl_name, n2);
181 }
182 }
183
184 } else { // Delta Interface
185 if (not is_gf_hermitian(_Delta_tau)) {
186 if (params.verbosity >= 2)
187 std::cout << "!---------------------------------------------------------------------------------------!\n"
188 "! WARNING: S.Delta_tau violates fundamental symmetry Delta(tau)[i,j] = Delta(tau)*[j,i] !\n"
189 "! Symmetrizing S.Delta_tau ... !\n"
190 "!---------------------------------------------------------------------------------------!\n\n";
191 _Delta_tau = make_hermitian(_Delta_tau);
192 }
193 if (not params.h_loc0.has_value()) TRIQS_RUNTIME_ERROR << "h_loc0 must be provided when using the Delta interface";
194 _h_loc0 = params.h_loc0.value();
195 }
196
197 _h_loc = params.h_int + _h_loc0;
198
199#ifndef HYBRIDISATION_IS_COMPLEX
200 // Check that diagonal components of Delta_tau are real
201 for (auto bl : range(gf_struct.size())) {
202 long bl_size = gf_struct[bl].second;
203 // Force all diagonal elements to be real
204 auto _ = range::all;
205 for (auto [i, j] : product_range(bl_size, bl_size)) {
206 auto Delta_tau_bl_ij = _Delta_tau[bl].data()(_, i, j);
207 double max_imag = max_element(abs(imag(Delta_tau_bl_ij)));
208 if (i == j && max_imag > 1e-10) {
209 std::cout << "WARNING: max(abs(imag(S.Delta_tau[" << bl << "][" << i << ", " << j << "]))) = "
210 << max_imag << " setting to zero.\n";
211 Delta_tau_bl_ij = real(Delta_tau_bl_ij);
212 } else if (max_imag < params.imag_threshold) {
213 Delta_tau_bl_ij = real(Delta_tau_bl_ij);
214 }
215 }
216 }
217#endif
218
219 // Report what h_loc we are using
220 if (params.verbosity >= 2)
221 std::cout << "The local Hamiltonian of the problem:" << std::endl << _h_loc << std::endl;
222 // Reset the histograms
223 _performance_analysis.clear();
224 histo_map_t *histo_map = params.performance_analysis ? &_performance_analysis : nullptr;
225
226 // Determine block structure
227 if (params.partition_method == "autopartition") {
228 if (params.verbosity >= 2)
229 std::cout << "Using autopartition algorithm to partition the local Hilbert space"
230 << std::endl;
231 if (params.loc_n_min == 0 && params.loc_n_max == INT_MAX)
232 h_diag = {_h_loc, fops};
233 else {
234 if (params.verbosity >= 2)
235 std::cout << "Restricting the local Hilbert space to states with [" << params.loc_n_min
236 << ";" << params.loc_n_max << "] particles" << std::endl;
237 h_diag = {_h_loc, fops, params.loc_n_min, params.loc_n_max};
238 }
239 } else if (params.partition_method == "quantum_numbers") {
240 if (params.quantum_numbers.empty()) TRIQS_RUNTIME_ERROR << "No quantum numbers provided.";
241 if (params.verbosity >= 2)
242 std::cout << "Using quantum numbers to partition the local Hilbert space" << std::endl;
243 h_diag = {_h_loc, fops, params.quantum_numbers};
244 } else if (params.partition_method == "none") { // give empty quantum numbers list
245 std::cout << "Not partitioning the local Hilbert space" << std::endl;
246 h_diag = {_h_loc, fops, std::vector<many_body_op_t>{}};
247 } else
248 TRIQS_RUNTIME_ERROR << "Partition method " << params.partition_method << " not recognised.";
249
250 // FIXME save h_loc to be able to rebuild h_diag in an analysis program.
251 //if (_comm.rank() ==0) h5_write(h5::file("h_loc.h5",'w'), "h_loc", _h_loc, fops);
252
253 if (params.verbosity >= 2)
254 std::cout << "Found " << h_diag.n_subspaces() << " subspaces." << std::endl;
255
256 if (params.performance_analysis) std::ofstream("impurity_blocks.dat") << h_diag;
257
258 // If one is interested only in the atomic problem
259 if (params.n_warmup_cycles == 0 && params.n_cycles == 0) {
260 if (params.measure_density_matrix) _density_matrix = atomic_density_matrix(h_diag, beta);
261 return;
262 }
263
264 // Initialise Monte Carlo quantities
265 qmc_data data(beta, params, h_diag, linindex, _Delta_tau, n_inner, histo_map);
266 auto qmc =
267 mc_tools::mc_generic<mc_weight_t>(params.random_name, params.random_seed, params.verbosity);
268
269 // --------------------------------------------------------------------------
270 // Moves
271 // --------------------------------------------------------------------------
272
273 using move_set_type = mc_tools::move_set<mc_weight_t>;
274 move_set_type inserts(qmc.get_rng());
275 move_set_type removes(qmc.get_rng());
276 move_set_type double_inserts(qmc.get_rng());
277 move_set_type double_removes(qmc.get_rng());
278
279 auto &delta_names = _Delta_tau.block_names();
280 auto get_prob_prop = [&params](std::string const &block_name) {
281 auto f = params.proposal_prob.find(block_name);
282 return (f != params.proposal_prob.end() ? f->second : 1.0);
283 };
284
285 for (size_t block = 0; block < _Delta_tau.size(); ++block) {
286 int block_size = _Delta_tau[block].data().shape()[1];
287 auto const &block_name = delta_names[block];
288 double prop_prob = get_prob_prop(block_name);
289 inserts.add(move_insert_c_cdag(block, block_size, block_name, data, qmc.get_rng(), histo_map),
290 "Insert Delta_" + block_name, prop_prob);
291 removes.add(move_remove_c_cdag(block, block_size, block_name, data, qmc.get_rng(), histo_map),
292 "Remove Delta_" + block_name, prop_prob);
293 if (params.move_double) {
294 for (size_t block2 = 0; block2 < _Delta_tau.size(); ++block2) {
295 int block_size2 = _Delta_tau[block2].data().shape()[1];
296 auto const &block_name2 = delta_names[block2];
297 double prop_prob2 = get_prob_prop(block_name2);
298 double_inserts.add(
299 move_insert_c_c_cdag_cdag(block, block2, block_size, block_size2, block_name,
300 block_name2, data, qmc.get_rng(), histo_map),
301 "Insert Delta_" + block_name + "_" + block_name2, prop_prob * prop_prob2);
302 double_removes.add(
303 move_remove_c_c_cdag_cdag(block, block2, block_size, block_size2, block_name,
304 block_name2, data, qmc.get_rng(), histo_map),
305 "Remove Delta_" + block_name + "_" + block_name2, prop_prob * prop_prob2);
306 }
307 }
308 }
309
310 qmc.add_move(std::move(inserts), "Insert two operators", 1.0);
311 qmc.add_move(std::move(removes), "Remove two operators", 1.0);
312 if (params.move_double) {
313 qmc.add_move(std::move(double_inserts), "Insert four operators", 1.0);
314 qmc.add_move(std::move(double_removes), "Remove four operators", 1.0);
315 }
316
317 if (params.move_shift)
318 qmc.add_move(move_shift_operator(data, qmc.get_rng(), histo_map), "Shift one operator", 1.0);
319
320 if (params.move_global.size()) {
321 move_set_type global(qmc.get_rng());
322 for (auto const &mv : params.move_global) {
323 auto const &name = mv.first;
324 auto const &substitutions = mv.second;
325 global.add(move_global(name, substitutions, data, qmc.get_rng()), name, 1.0);
326 }
327 qmc.add_move(std::move(global), "Global moves", params.move_global_prob);
328 }
329
330 // --------------------------------------------------------------------------
331 // Measurements
332 // --------------------------------------------------------------------------
333
334 // --------------------------------------------------------------------------
335 // Two-particle correlators
336
337 G2_measures_t G2_measures(_Delta_tau, gf_struct, params);
338
339#ifdef CTHYB_G2_NFFT
340 // Imaginary-time binning
341 if (params.measure_G2_tau)
342 qmc.add_measure(measure_G2_tau{G2_tau, data, G2_measures},
343 "G2_tau imaginary-time measurement");
344
345 // NFFT Matsubara frequency measures
346
347 if (params.measure_G2_iw_nfft)
348 qmc.add_measure(measure_G2_iw_nfft<G2_channel::AllFermionic>{G2_iw_nfft, data, G2_measures},
349 "G2_iw nfft fermionic measurement");
350 if (params.measure_G2_iw_pp_nfft)
351 qmc.add_measure(measure_G2_iw_nfft<G2_channel::PP>{G2_iw_pp_nfft, data, G2_measures},
352 "G2_iw_pp nfft particle-particle measurement");
353 if (params.measure_G2_iw_ph_nfft)
354 qmc.add_measure(measure_G2_iw_nfft<G2_channel::PH>{G2_iw_ph_nfft, data, G2_measures},
355 "G2_iw_ph nfft particle-hole measurement");
356
357 // Direct Matsubara frequency measurement
358
359 if (params.measure_G2_iw)
360 qmc.add_measure(measure_G2_iw<G2_channel::AllFermionic>{G2_iw, data, G2_measures},
361 "G2_iw fermionic measurement");
362 if (params.measure_G2_iw_pp)
363 qmc.add_measure(measure_G2_iw<G2_channel::PP>{G2_iw_pp, data, G2_measures},
364 "G2_iw_pp particle-particle measurement");
365 if (params.measure_G2_iw_ph)
366 qmc.add_measure(measure_G2_iw<G2_channel::PH>{G2_iw_ph, data, G2_measures},
367 "G2_iw_ph particle-hole measurement");
368
369 // Legendre mixed basis measurements
370 if (params.measure_G2_iwll_pp)
371 qmc.add_measure(measure_G2_iwll<G2_channel::PP>{G2_iwll_pp, data, G2_measures},
372 "G2_iwll_pp Legendre particle-particle measurement");
373 if (params.measure_G2_iwll_ph)
374 qmc.add_measure(measure_G2_iwll<G2_channel::PH>{G2_iwll_ph, data, G2_measures},
375 "G2_iwll_ph Legendre particle-hole measurement");
376#endif
377
378 // --------------------------------------------------------------------------
379 // Single-particle correlators
380
381 if (params.measure_O_tau) {
382
383 const auto &[O1, O2] = *params.measure_O_tau;
384 auto comm_0 = O1 * O2 - O2 * O1;
385 auto comm_1 = O1 * _h_loc - _h_loc * O1;
386 auto comm_2 = O2 * _h_loc - _h_loc * O2;
387
388 if (!comm_0.is_zero() || !comm_1.is_zero() || !comm_2.is_zero()) {
389 if (params.verbosity >= 2) {
390 TRIQS_RUNTIME_ERROR << "Error: measure_O_tau, supplied operators does not commute with "
391 "the local Hamiltonian.\n"
392 << "[O1, O2] = " << comm_0 << "\n"
393 << "[O1, H_loc] = " << comm_1 << "\n"
394 << "[O2, H_loc] = " << comm_2 << "\n";
395 }
396 }
397 qmc.add_measure(
398 measure_O_tau_ins{O_tau, data, n_tau, O1, O2, params.measure_O_tau_min_ins, qmc.get_rng()},
399 "O_tau insertion measure");
400 }
401
402 if (params.measure_G_tau) {
403 G_tau = block_gf<imtime>{{beta, Fermion, n_tau}, gf_struct};
404 qmc.add_measure(measure_G_tau{data, n_tau, gf_struct, container_set()}, "G_tau measure");
405 }
406
407 if (params.measure_G_l) qmc.add_measure(measure_G_l{G_l, data, n_l, gf_struct}, "G_l measure");
408
409 // Other measurements
410 if (params.measure_pert_order) {
411 auto &g_names = _Delta_tau.block_names();
412 perturbation_order = histo_map_t{};
413 perturbation_order_total = histogram{};
414 for (size_t block = 0; block < _Delta_tau.size(); ++block) {
415 auto const &block_name = g_names[block];
416 qmc.add_measure(measure_perturbation_hist(block, data, (*perturbation_order)[block_name]), "Perturbation order (" + block_name + ")");
417 }
418 qmc.add_measure(measure_perturbation_hist_total(data, *perturbation_order_total), "Perturbation order");
419 }
420 if (params.measure_density_matrix) {
421 if (!params.use_norm_as_weight)
422 TRIQS_RUNTIME_ERROR << "To measure the density_matrix of atomic states, you need to set "
423 "use_norm_as_weight to True, i.e. to reweight the QMC";
424 qmc.add_measure(measure_density_matrix{data, _density_matrix},
425 "Density Matrix for local static observable");
426 }
427
428 qmc.add_measure(measure_average_sign{data, _average_sign}, "Average sign");
429 qmc.add_measure(measure_average_order{data, _average_order}, "Average order");
430 qmc.add_measure(measure_auto_corr_time{data, _auto_corr_time, _auto_corr_time_converged}, "Auto-correlation time");
431
432 // --------------------------------------------------------------------------
433
434 // set the correct sign in case a user-provided initial configuration is used
435 if (std::abs(data.atomic_weight) == 0) TRIQS_RUNTIME_ERROR << "Error: Atomic weight of initial configuration is zero";
436 mc_weight_t sign = data.current_sign * data.atomic_weight / std::abs(data.atomic_weight);
437
438 for (size_t block = 0; block < _Delta_tau.size(); ++block) {
439 auto det = data.dets[block].determinant();
440 if (std::abs(det) == 0) TRIQS_RUNTIME_ERROR << "Error: Determinant of block " << block << " is zero";
441 sign *= det / std::abs(det);
442 }
443
444 // Run! The empty (starting) configuration has sign = 1.
445 // Note: mc_generic continues running after the requested cycles are done until all
446 // MPI ranks have finished (continue_after_ncycles_done defaults to true in triqs).
447 _solve_status =
448 qmc.warmup_and_accumulate(params.n_warmup_cycles, params.n_cycles, params.length_cycle,
449 triqs::utility::clock_callback(params.max_time), sign);
450 qmc.collect_results(_comm);
451
452 // set the last configuration
453 _last_configuration = data.config;
454
455 if (params.verbosity >= 2) {
456 std::cout << "Average sign: " << _average_sign << std::endl;
457 std::cout << "Average order: " << _average_order << std::endl;
458 if (_auto_corr_time_converged)
459 std::cout << "Auto-correlation time: " << _auto_corr_time << " cycles" << std::endl;
460 else
461 std::cout << "Auto-correlation time: >~ " << _auto_corr_time << " cycles (not converged, run longer)" << std::endl;
462 }
463
464 // Copy local (real or complex) G_tau back to complex G_tau
465 if (G_tau && G_tau_accum) *G_tau = *G_tau_accum;
466 }
467} // namespace triqs_cthyb
constr_parameters_t constr_parameters
Parameters used for constructing the solver.
solve_parameters_t solve_parameters
Parameters passed to the solve method.
void solve(solve_parameters_t const &p)
std::vector< matrix< dcomplex > > Delta_infty()
in Matsubara frequencies.
solver_core(constr_parameters_t const &p)
Auto-correlation time from the partition function (one sample per cycle, so tau is in units of MC cyc...
Measure of the average perturbation order.
Parameters used for constructing the solver class.
int n_iw
Number of Matsubara frequencies.
int n_tau
Number of imaginary-time points.
Parameters passed to the solve method of the solver class.
double imag_threshold
Threshold below which imaginary components of and are set to zero.
double off_diag_threshold
Threshold below which off-diagonal components of are set to zero.