6#include "./solver_core.hpp"
7#include "./measures.hpp"
8#include "./moves/insert.hpp"
9#include "./moves/remove.hpp"
10#include "./moves/spinflip.hpp"
11#include "./post_process.hpp"
12#include "./qmc_config.hpp"
13#include "./vertex_factories.hpp"
15namespace triqs_ctint {
30 auto D_mesh = mesh::dlr_imfreq{p.beta, Boson, p.dlr_wmax, p.dlr_eps, true};
33 auto g0 = gf<mesh::dlr_imfreq, matrix_valued>{D_mesh, make_shape(bl_sz, bl_sz)};
34 D0_iw = block2_gf<mesh::dlr_imfreq, matrix_valued>{{bl, bl}, std::vector(bl.size(), std::vector(bl.size(), g0))};
39 auto [bl, bl_size] = p.gf_struct[0];
40 Jperp_iw = gf<mesh::dlr_imfreq, matrix_valued>{{p.beta, Boson, p.dlr_wmax, p.dlr_eps, true}, make_shape(bl_size, bl_size)};
54 triqs::utility::report_stream report(&std::cout, params.
verbosity);
58 "╔╦╗╦═╗╦╔═╗ ╔═╗ ┌─┐┌┬┐┬ ┌┐┌┌┬┐\n"
59 " ║ ╠╦╝║║═╬╗╚═╗ │ │ │ │││ │ \n"
60 " ╩ ╩╚═╩╚═╝╚╚═╝ └─┘ ┴ ┴ ┘└┘ ┴ \n";
63 if (!is_gf_hermitian(
G0_iw)) TRIQS_RUNTIME_ERROR <<
"Please make sure that G0_iw fullfills the hermiticity relation G_ij[iw] = G_ji[-iw]*";
86 auto &rng = mc.get_rng();
92 const std::vector<vertex_factory_t> vertex_factories = make_vertex_factories(params, rng,
D0_iw,
Jperp_iw);
100 mc.add_move(
moves::insert{&qmc_config, vertex_factories, rng, num_insert, params.
max_order},
"insert " + std::to_string(num_insert));
101 mc.add_move(
moves::remove{&qmc_config, vertex_factories, rng, num_insert, params.
max_order},
"remove " + std::to_string(num_insert));
104 TRIQS_ASSERT2(params.
n_s == 2,
"ERROR: Auxiliary spin-flip move requires n_s = 2.");
110 mc.add_measure(
measures::average_k{params, qmc_config, &result_set()},
"perturbation order measure",
true,
true);
113 report(3) <<
"\nWarming up ..." << std::endl;
115 double warmup_time_ = mc.get_accumulation_time();
125 mc.add_measure(
measures::average_k{params, qmc_config, &result_set()},
"perturbation order measure",
true,
129 report(3) <<
"You selected Sign only mode" << std::endl;
131 if (params.
measure_histogram) mc.add_measure(measures::histogram{params, qmc_config, &result_set()},
"perturbation order histogram measure");
149 report(3) <<
"\nAccumulating ..." << std::endl;
151 double accumulation_time_ = mc.get_accumulation_time();
152 mc.collect_results(world);
153 warmup_time = mpi::all_reduce(warmup_time_, world, MPI_MAX);
174 long n_h_int = std::distance(p.
h_int.begin(), p.
h_int.end());
178 long R = (*D0_iw)(0, 0).target_shape()[0];
179 n_D0_total = n_bl * n_bl * R * R;
181 if (p.
alpha.shape() != std::array<long, 4>{n_h_int + n_D0_total, 2, 2, p.n_s})
182 TRIQS_RUNTIME_ERROR <<
"Alpha tensor shape " << p.
alpha.shape() <<
" incompatible with h_int (" << n_h_int <<
" terms) + D0 (" << n_D0_total
186 for (
auto const &[n, term] : enumerate(p.
h_int)) {
187 auto &m = term.monomial;
189 if (m[0].indices[0] != m[3].indices[0] or m[1].indices[0] != m[2].indices[0])
190 TRIQS_RUNTIME_ERROR <<
"Interaction term with incompatible block structure: cdag_1 cdag_2 c_2 c_1 required";
192 auto [bl_0, idx_cdag_0] = get_int_indices(m[0], p.
gf_struct);
193 auto [bl_1, idx_cdag_1] = get_int_indices(m[1], p.
gf_struct);
194 auto [bl_c_1, idx_c_1] = get_int_indices(m[2], p.
gf_struct);
195 auto [bl_c_0, idx_c_0] = get_int_indices(m[3], p.
gf_struct);
198 for (
long s : range(p.
n_s)) {
199 G0_shift_iw_inv[bl_0].data()(range::all, idx_cdag_0, idx_c_0) -= p.
alpha(n, 1, 1, s) * U_scalar_t(term.coef) / p.
n_s;
200 G0_shift_iw_inv[bl_1].data()(range::all, idx_cdag_1, idx_c_1) -= p.
alpha(n, 0, 0, s) * U_scalar_t(term.coef) / p.
n_s;
202 G0_shift_iw_inv[bl_0].data()(range::all, idx_cdag_0, idx_c_1) += p.
alpha(n, 1, 0, s) * U_scalar_t(term.coef) / p.
n_s;
203 G0_shift_iw_inv[bl_1].data()(range::all, idx_cdag_1, idx_c_0) += p.
alpha(n, 0, 1, s) * U_scalar_t(term.coef) / p.
n_s;
211 int R = (*D0_iw)(0, 0).target_shape()[0];
217 std::vector<std::vector<double>> block_density(n_bl);
218 for (
int sigp : range(n_bl)) {
219 block_density[sigp].resize(R, 0.0);
220 for (
int j : range(R)) {
221 long label = n_h_int + sigp * n_bl * R * R + 0 * R * R + j * R + 0;
222 for (
int s : range(p.
n_s)) block_density[sigp][j] += p.
alpha(label, 0, 0, s);
223 block_density[sigp][j] /= p.
n_s;
228 std::vector<std::vector<matrix<dcomplex>>> D0_static(n_bl, std::vector<matrix<dcomplex>>(n_bl));
229 for (
int b1 : range(n_bl))
230 for (
int b2 : range(n_bl)) D0_static[b1][b2] = make_gf_imfreq(make_gf_dlr((*
D0_iw)(b1, b2)), 1)(0);
232 for (
int sig : range(n_bl)) {
233 for (
int i : range(R)) {
234 dcomplex shift = 0.0;
235 for (
int sigp : range(n_bl))
236 for (
int j : range(R)) shift += (D0_static[sig][sigp](i, j) + D0_static[sigp][sig](j, i)) * block_density[sigp][j];
237 G0_shift_iw_inv[sig].data()(range::all, i, i) -= shift;
248 void solver_core::post_process(
params_t const &p) {
250 if (world.rank() == 0)
252 "Post-processing ... \n";
256 M_iw = g_iw_t{M_iw_nfft.value()};
260 auto const &mt = *M_tau;
261 std::vector<gf<imtime, matrix_valued>> gf_vec;
262 for (
int b = 0; b < mt.size(); ++b) gf_vec.emplace_back(mt[b]);
263 auto M_tau_cast = block_gf<imtime, matrix_valued>{mt.block_names(), std::move(gf_vec)};
265 M_iw = g_iw_t{make_gf_dlr_imfreq(M_dlr)};
269 auto make_M_full = [&]() {
270 g_iw_t M_full = M_iw.value();
271 for (
auto [M_bl, M_h_bl] : zip(M_full, M_hartree.value()))
272 for (
long d = 0; d < M_bl.mesh().size(); ++d) M_bl.data()(d, ellipsis()) += M_h_bl;
280 Sigma_dyn_iw = G0_shift_iw;
282 auto M_full = make_M_full();
285 for (
auto [G_bl, G0_bl, M_bl] : zip(G_iw, G0_shift_iw, M_full))
286 for (
auto iw : G_bl.mesh()) G_bl[iw] = G0_bl[iw] + G0_bl[iw] * M_bl[iw] * G0_bl[iw];
289 auto G0_shift_iw_inv = inverse(G0_shift_iw);
290 auto G_iw_inv = inverse(G_iw);
291 for (
auto [S_bl, G0s_bl, Gi_bl, M_h_bl] : zip(Sigma_dyn_iw, G0_shift_iw_inv, G_iw_inv, M_hartree.value()))
292 for (
auto iw : S_bl.mesh()) S_bl[iw] = G0s_bl[iw] - Gi_bl[iw] - M_h_bl;
295 Sigma_hartree = make_block_vector<M_tau_scalar_t>(p.
gf_struct);
296 for (
int bl : range(p.
n_blocks())) {
297 Sigma_hartree.value()[bl] = real(matrix<dcomplex>(G0_iw_inv[bl].data()(0, ellipsis()) - G0_shift_iw_inv[bl].data()(0, ellipsis())))
298 + M_hartree.value()[bl];
304 g_reg_iw_t G0_shift_iw_reg = make_gf_imfreq(G0_shift_iw, n_iw_pp);
306 std::optional<g_reg_iw_t> M_iw_reg;
307 if (M_iw) M_iw_reg = make_gf_imfreq(make_M_full(), n_iw_pp);
308 g_reg_iw_t G_iw_reg = make_gf_imfreq(G_iw, n_iw_pp);
313 auto iW_mesh = mesh::imfreq{p.
beta, Boson, p.
n_iW_M3};
314 auto iw_mesh = mesh::imfreq{p.
beta, Fermion, p.
n_iw_M3};
316 auto M3pp_ferm_iw = make_gf_from_fourier<0, 1>(M3pp_tau.value(), iw_mesh, iw_mesh_large);
317 auto M3pp_del_iW = make_gf_from_fourier(M3pp_delta.value(), iW_mesh, make_zero_tail(M3pp_delta.value()));
318 M3pp_iw = make_block2_gf(prod{iW_mesh, iw_mesh}, p.
gf_struct);
321 M3pp_iw.value()(bl1_, bl2_)(iW_, iw_)(i_, j_, k_, l_)
322 << M3pp_ferm_iw(bl1_, bl2_)(iw_, iW_ - iw_)(i_, j_, k_, l_) + M3pp_del_iW(bl1_, bl2_)(iW_)(i_, j_, k_, l_);
325 if (M_iw_reg && density) {
326 chi2pp_conn_tau_from_M3 = chi2_conn_from_M3<Chan_t::PP>(M3pp_tau.value(), M3pp_delta.value(), M_iw_reg.value(), G0_shift_iw_reg, M_tau.value(),
327 M_hartree.value(), G0_shift_tau);
328 chi2pp_tau_from_M3 = chi2_from_chi2_conn<Chan_t::PP>(chi2pp_conn_tau_from_M3.value(), G_iw_reg, density.value());
330 chi2pp_iw_from_M3 = make_gf_from_fourier(chi2pp_tau_from_M3.value(), iw_mesh, make_zero_tail(chi2pp_tau_from_M3.value()));
335 auto iW_mesh = mesh::imfreq{p.
beta, Boson, p.
n_iW_M3};
336 auto iw_mesh = mesh::imfreq{p.
beta, Fermion, p.
n_iw_M3};
338 auto M3ph_ferm_iw = make_gf_from_fourier<0, 1>(M3ph_tau.value(), iw_mesh, iw_mesh_large);
339 auto M3ph_del_iW = make_gf_from_fourier(M3ph_delta.value(), iW_mesh, make_zero_tail(M3ph_delta.value()));
340 M3ph_iw = make_block2_gf(prod{iW_mesh, iw_mesh}, p.
gf_struct);
345 M3ph_iw.value()(bl1_, bl2_)(iW_, iw_)(i_, j_, k_, l_)
346 << M3ph_ferm_iw(bl1_, bl2_)(-iw_, iW_ + iw_)(i_, j_, k_, l_) + M3ph_del_iW(bl1_, bl2_)(iW_)(i_, j_, k_, l_);
349 if (M_iw_reg && density) {
350 chi2ph_conn_tau_from_M3 = chi2_conn_from_M3<Chan_t::PH>(M3ph_tau.value(), M3ph_delta.value(), M_iw_reg.value(), G0_shift_iw_reg, M_tau.value(),
351 M_hartree.value(), G0_shift_tau);
352 chi2ph_tau_from_M3 = chi2_from_chi2_conn<Chan_t::PH>(chi2ph_conn_tau_from_M3.value(), G_iw_reg, density.value());
354 chi2ph_iw_from_M3 = make_gf_from_fourier(chi2ph_tau_from_M3.value(), iw_mesh, make_zero_tail(chi2ph_tau_from_M3.value()));
359 auto iw_mesh = mesh::imfreq{p.
beta, Fermion, p.
n_iw_M3};
360 auto iW_mesh = mesh::imfreq{p.
beta, Boson, p.
n_iW_M3};
362 auto M3xph_ferm_iw = make_gf_from_fourier<0, 1>(M3xph_tau.value(), iw_mesh, iw_mesh_large);
363 auto M3xph_del_iW = make_gf_from_fourier(M3xph_delta.value(), iW_mesh, make_zero_tail(M3xph_delta.value()));
364 M3xph_iw = make_block2_gf(mesh::prod{iW_mesh, iw_mesh}, p.
gf_struct);
369 M3xph_iw.value()(bl1_, bl2_)(iW_, iw_)(i_, j_, k_, l_)
370 << M3xph_ferm_iw(bl1_, bl2_)(iW_ + iw_, -iw_)(i_, j_, k_, l_) + M3xph_del_iW(bl1_, bl2_)(iW_)(i_, j_, k_, l_);
373 if (M_iw_reg && density) {
374 chi2xph_conn_tau_from_M3 = chi2_conn_from_M3<Chan_t::XPH>(M3xph_tau.value(), M3xph_delta.value(), M_iw_reg.value(), G0_shift_iw_reg, M_tau.value(),
375 M_hartree.value(), G0_shift_tau);
376 chi2xph_tau_from_M3 = chi2_from_chi2_conn<Chan_t::XPH>(chi2xph_conn_tau_from_M3.value(), G_iw_reg, density.value());
378 chi2xph_iw_from_M3 = make_gf_from_fourier(chi2xph_tau_from_M3.value(), iw_mesh, make_zero_tail(chi2xph_tau_from_M3.value()));
383 if (M4_iw and M_iw_reg) G2_conn_iw = G2_conn_from_M4(M4_iw.value(), M_iw_reg.value(), G0_shift_iw_reg);
384 if (M4pp_iw and M_iw_reg) G2pp_conn_iw = G2pp_conn_from_M4pp(M4pp_iw.value(), M_iw_reg.value(), G0_shift_iw_reg);
385 if (M4ph_iw and M_iw_reg) G2ph_conn_iw = G2ph_conn_from_M4ph(M4ph_iw.value(), M_iw_reg.value(), G0_shift_iw_reg);
387 if (G2_conn_iw and M_iw_reg) F_iw = F_from_G2c(G2_conn_iw.value(), G_iw_reg);
388 if (G2pp_conn_iw and M_iw_reg) Fpp_iw = Fpp_from_G2pp_conn(G2pp_conn_iw.value(), G_iw_reg);
389 if (G2ph_conn_iw and M_iw_reg) Fph_iw = Fph_from_G2ph_conn(G2ph_conn_iw.value(), G_iw_reg);
391 if (G2_conn_iw and M_iw_reg) G2_iw = G2_from_G2c(G2_conn_iw.value(), G_iw_reg);
392 if (G2pp_conn_iw and M_iw_reg) G2pp_iw = G2pp_from_G2pp_conn(G2pp_conn_iw.value(), G_iw_reg);
393 if (G2ph_conn_iw and M_iw_reg) G2ph_iw = G2ph_from_G2ph_conn(G2ph_conn_iw.value(), G_iw_reg);
396 if (M3pp_iw and M_iw_reg and density) chi3pp_iw = chi3_from_M3<Chan_t::PP>(M3pp_iw.value(), M_iw_reg.value(), G0_shift_iw_reg, density.value(), M_hartree.value());
397 if (M3ph_iw and M_iw_reg and density) chi3ph_iw = chi3_from_M3<Chan_t::PH>(M3ph_iw.value(), M_iw_reg.value(), G0_shift_iw_reg, density.value(), M_hartree.value());
398 if (M3xph_iw and M_iw_reg and density) chi3xph_iw = chi3_from_M3<Chan_t::XPH>(M3xph_iw.value(), M_iw_reg.value(), G0_shift_iw_reg, density.value(), M_hartree.value());
399 if (M3pp_iw_nfft and M_iw_reg and density)
400 chi3pp_iw_nfft = chi3_from_M3<Chan_t::PP>(M3pp_iw_nfft.value(), M_iw_reg.value(), G0_shift_iw_reg, density.value(), M_hartree.value());
401 if (M3ph_iw_nfft and M_iw_reg and density)
402 chi3ph_iw_nfft = chi3_from_M3<Chan_t::PH>(M3ph_iw_nfft.value(), M_iw_reg.value(), G0_shift_iw_reg, density.value(), M_hartree.value());
406 if (chi2pp_tau) chi2pp_iw = make_gf_from_fourier(chi2pp_tau.value(), iw_mesh, make_zero_tail(chi2pp_tau.value()));
407 if (chi2ph_tau) chi2ph_iw = make_gf_from_fourier(chi2ph_tau.value(), iw_mesh, make_zero_tail(chi2ph_tau.value()));
410 if (chiAB_tau) chiAB_iw = make_gf_from_fourier(chiAB_tau.value(), iw_mesh, make_zero_tail(chiAB_tau.value()));
Type of the Monte-Carlo configuration.
g_iw_t G0_iw
Non-interacting Green's function in Matsubara frequencies.
solver_core(constr_params_t const &constr_params_)
Construct a CT-INT solver.
void solve(solve_params_t const &solve_params)
constr_params_t constr_params
Parameters used to construct the solver.
C2PY_IGNORE void prepare_G0_shift_iw(params_t const ¶ms)
Calculate the shifted non-interacting Green's function given .
std::optional< solve_params_t > last_solve_params
Parameters used in the last solve (empty until the solver has been run).
g_iw_t G0_shift_iw
The shifted non-interacting Green's function in Matsubara frequencies.
std::optional< block2_gf< mesh::dlr_imfreq, matrix_valued > > D0_iw
Dynamic density-density interaction in Matsubara frequencies (DLR mesh).
std::optional< gf< mesh::dlr_imfreq, matrix_valued > > Jperp_iw
Dynamic spin-spin interaction in Matsubara frequencies (DLR mesh).
g_tau_t G0_shift_tau
The shifted non-interacting Green's function in imaginary time.
g_iw_t G0_iw_inv
Inverse of the non-interacting Green's function .
Parameters used for constructing the solver class.
double dlr_eps
DLR error tolerance for the single-particle quantities.
int n_tau
Number of imaginary-time points for the single-particle quantities.
int n_blocks() const
Number of blocks of the Green's function.
auto block_names() const
Names of the blocks of the Green's function.
double beta
Inverse temperature .
gf_struct_t gf_struct
Structure of the Green's function (names and sizes of blocks).
bool use_D
Use a dynamic density-density interaction?
double dlr_wmax
DLR bandwidth cutoff for the single-particle quantities.
Container for all (optional) quantities measured and post-processed by the solver.
double accumulation_time
Accumulation time in seconds.
double average_k
Average perturbation order.
g_iw_t Sigma_dyn_iw
Dynamic self-energy in Matsubara frequencies (DLR, decays to zero).
g_iw_t G_iw
Green's function in Matsubara frequencies.
double warmup_time
Warmup time in seconds.
mc_weight_t average_sign
Average Monte-Carlo sign.
double auto_corr_time
Auto-correlation time.
Measurement of the auto-correlation time based on perturbation order and diagonal densities.
Measure of the average perturbation order.
Measure of the average sign.
The move that inserts one or multiple vertices into the configuration.
The move that removes one or multiple vertices from the configuration.
The move that spinflips one or multiple vertices from the configuration.
A struct combining both constr_params_t and solve_params_t.
Parameters passed to the solve method of the solver class.
int n_iw_chi2
Number of positive Matsubara frequencies in .
std::string random_name
Name of the random number generator.
bool measure_density
Measure the density by operator insertion?
int n_iw_M3
Number of positive fermionic Matsubara frequencies in .
bool measure_chiAB_tau
Measure by insertion?
bool measure_M_tau
Measure ?
int max_order
Maximum perturbation order accepted during insertion and removal moves (use -1 for unlimited).
bool measure_chi2ph_tau
Measure by insertion?
int length_cycle
Length of a single QMC cycle.
bool post_process
Perform post-processing?
bool use_auxiliary_spin_flip
Use auxiliary spin-flip insertion (requires )?
int n_iW_M4
Number of positive bosonic Matsubara frequencies in .
bool measure_M_iw
Measure using NFFT?
int max_time
Maximum runtime in seconds, use -1 to set infinite.
bool measure_auto_corr_time
Measure the auto-correlation time?
bool measure_M3xph_tau
Measure ?
int n_s
Number of auxiliary spins.
bool measure_histogram
Measure the perturbation-order distribution?
std::vector< int > insertion_types
Types of insertions to use.
int n_cycles
Number of QMC cycles.
bool measure_chi2pp_tau
Measure by insertion?
bool measure_M3ph_tau
Measure ?
bool measure_M4pp_iw
Measure using NFFT?
int verbosity
Verbosity level.
int n_iW_M3
Number of positive bosonic Matsubara frequencies in .
bool measure_M4_iw
Measure using NFFT?
bool measure_M4ph_iw
Measure using NFFT?
bool measure_M3ph_iw
Measure ?
alpha_t alpha
The tensor used in the determinantal expansion.
bool measure_average_k
Measure the average perturbation order?
many_body_operator h_int
Interacting part of the local Hamiltonian.
bool measure_sign_only
Measure the sign only?
int n_iw_M4
Number of positive fermionic Matsubara frequencies in .
int n_warmup_cycles
Number of cycles for thermalization.
bool measure_M3pp_iw
Measure ?
bool measure_M3pp_tau
Measure ?
bool use_double_insertion
Use double insertion?
int random_seed
Seed for the random number generator.
bool measure_average_sign
Measure the Monte-Carlo sign?
static double beta
Inverse temperature associated with all $\tau$ points.