TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
mc_move_set.cpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2013-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2022 Simons Foundation
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You may obtain a copy of the License at
16// https://www.gnu.org/licenses/gpl-3.0.txt
17//
18// Authors: Michel Ferrero, Olivier Parcollet, Nils Wentzell
19
24
25#include "./concepts.hpp"
26#include "./mc_move_set.hpp"
27
28#include <fmt/ostream.h>
29#include <fmt/ranges.h>
30#include <itertools/itertools.hpp>
31#include <mpi/communicator.hpp>
32
33#include <algorithm>
34#include <cmath>
35#include <complex>
36#include <map>
37#include <numeric>
38#include <stdexcept>
39#include <string>
40#include <type_traits>
41
42namespace triqs::mc_tools {
43
44 template <DoubleOrComplex MCSignType> double move_set<MCSignType>::attempt() {
45 assert(std::abs(acc_probs_.back() - 1.0) < 1e-13);
46
47 // choose a move
48 current_ = std::ranges::lower_bound(acc_probs_, rng_()) - acc_probs_.begin();
49 assert(current_ < moves_.size());
50
51 // attempt the move and return the absolute value of the acceptance ratio
52 return check_ratio(moves_[current_].attempt());
53 }
54
55 template <DoubleOrComplex MCSignType> void move_set<MCSignType>::clear_statistics() {
56 for (auto &m : moves_) m.clear_statistics();
57 }
58
59 template <DoubleOrComplex MCSignType> void move_set<MCSignType>::collect_statistics(mpi::communicator const &c) {
60 for (auto &m : moves_) m.collect_statistics(c);
61 }
62
63 template <DoubleOrComplex MCSignType> void move_set<MCSignType>::calibrate(mpi::communicator const &c) {
64 for (auto &m : moves_) m.calibrate(c);
65 }
66
67 template <DoubleOrComplex MCSignType> std::map<std::string, double> move_set<MCSignType>::get_acceptance_rates() const {
68 std::map<std::string, double> res;
69 for (auto const &[m, name] : itertools::zip(moves_, names_)) {
70 res.insert({name, m.acceptance_rate()});
71 auto tmp_map = m.get_acceptance_rates();
72 res.insert(tmp_map.begin(), tmp_map.end());
73 }
74 return res;
75 }
76
77 template <DoubleOrComplex MCSignType> std::string move_set<MCSignType>::get_statistics(std::string const &prefix) const {
78 std::string str;
79 for (auto const &[m, name] : itertools::zip(moves_, names_)) { str += m.get_statistics(name, prefix); }
80 return str;
81 }
82
83 template <DoubleOrComplex MCSignType> std::string move_set<MCSignType>::get_timings(std::string const &prefix) const {
84 std::string str;
85 for (auto const &[m, name] : itertools::zip(moves_, names_)) { str += m.get_timings(name, prefix); }
86 return str;
87 }
88
89 template <DoubleOrComplex MCSignType> void move_set<MCSignType>::initialize() {
90 // initialize is called in add, so we need to resize the vectors
91 probs_.resize(weights_.size());
92 acc_probs_.resize(weights_.size());
93
94 // normalize weights to get probabilities
95 auto norm = std::accumulate(weights_.begin(), weights_.end(), 0.0);
96 std::transform(weights_.begin(), weights_.end(), probs_.begin(), [norm](auto w) { return w / norm; });
97
98 // partial sum probabilities to get accumulated probabilities
99 std::partial_sum(probs_.begin(), probs_.end(), acc_probs_.begin());
100 }
101
102 template <DoubleOrComplex MCSignType> double move_set<MCSignType>::check_ratio(MCSignType ratio) {
103 // handle infinities in case of double MC weights
104 if constexpr (std::is_same_v<MCSignType, double>) {
105 if (std::isinf(ratio)) {
106 attempt_sign_ = (std::signbit(ratio) ? -1 : 1);
107 return 100;
108 }
109 }
110
111 // throw an exception, if the absolute ratio is still non-finite
112 const auto abs_ratio = std::abs(ratio);
113 if (!std::isfinite(abs_ratio)) {
114 const auto cplx_ratio = std::complex<double>{ratio};
115 throw std::runtime_error(fmt::format("Error in move_set::check_ratio: Non-finite absolute ratio in move {}: ({},{})", names_[current_],
116 std::real(cplx_ratio), std::imag(cplx_ratio)));
117 }
118
119 // set the sign of the current attempt (why can't we always use ratio / abs_ratio?)
120 attempt_sign_ = (abs_ratio > 1e-14 ? ratio / abs_ratio : 1);
121 return abs_ratio;
122 }
123
124 // Explicit template instantiations.
125 template class move_set<double>;
126 template class move_set<std::complex<double>>;
127
128} // namespace triqs::mc_tools
std::map< std::string, double > get_acceptance_rates() const
Get the acceptance rates of all moves in the set.
std::string get_statistics(std::string const &prefix="") const
Get a formatted string showing the acceptance rates of all moves.
void clear_statistics()
Clear the statistics of all the moves in the set.
void calibrate(mpi::communicator const &c)
Calibrate all the moves in the set.
void collect_statistics(mpi::communicator const &c)
Collect statistics for all the moves in the set from multiple MPI processes.
double attempt()
Propose a new MC configuration.
std::string get_timings(std::string const &prefix="") const
Get a formatted string with the timings of all moves.
Provides a set of MC moves.
Provides concepts for the MC tools.