7#include "work_data.hpp"
11#include <nda/basic_functions.hpp>
12#include <nda/traits.hpp>
13#include <triqs/gfs/functions/functions2.hpp>
14#include <triqs/operators/util/extractors.hpp>
15#include <triqs/utility/exceptions.hpp>
17#include "spdlog/common.h"
18#include "spdlog/spdlog.h"
19#include <fmt/ostream.h>
21using namespace triqs::operators::utils;
23namespace triqs_ctseg {
26 work_data_t::work_data_t(
params_t const &p, inputs_t
const &inputs, mpi::communicator c) {
29 spdlog::set_pattern(
"%v");
30 spdlog::set_level(spdlog::level::info);
31 if constexpr (print_logs) spdlog::set_level(spdlog::level::debug);
35 gf_struct = p.gf_struct;
39 for (
auto const &[bl_name, bl_size] : gf_struct) { n_color += bl_size; }
42 for (
auto const &color : range(n_color)) {
43 block_number.push_back(find_block_number(color));
44 index_in_block.push_back(find_index_in_block(color));
50 for (
auto const &color : range(n_color)) {
51 spdlog::info(
"Block: {} Index: {} Color: {}", gf_struct[block_number[color]].first, index_in_block[color],
62 mu = nda::zeros<double>(n_color);
63 auto h_loc0 = dict_to_matrix<std::complex<double>>(extract_h_dict(p.h_loc0), p.gf_struct);
65 double max_imag = 0.0;
66 for (
auto const &col : range(n_color)) max_imag = std::max(max_imag, std::abs(h_loc0(col, col).imag()));
67 if (max_imag > p.imag_threshold)
68 TRIQS_RUNTIME_ERROR <<
"Largest imaginary element of the h_loc0 diagonal: " << max_imag
69 <<
", is larger than the set parameter imag_threshold " << p.imag_threshold;
70 for (
auto const &col : range(n_color)) mu(col) = -h_loc0(col, col).real();
74 auto U_full = dict_to_matrix(extract_U_dict2(p.h_int), p.gf_struct);
75 U = nda::matrix<double>{real(U_full)};
77 for (
int a = 0; a < U.extent(0); ++a)
78 ALWAYS_EXPECTS((abs(U(a, a)) < 1.e-15),
"Error. A diagonal element of the interaction matrix is not 0.");
82 spdlog::info(
"\n Interaction matrix: U = {} \n", fmt::streamed(U));
83 spdlog::info(
"Orbital energies: mu - eps = {} \n", fmt::streamed(mu));
87 D0t = gf<imtime>({beta, Boson, p.n_tau_bosonic}, {n_color, n_color});
88 for (
int c1 : range(n_color)) {
89 for (
int c2 : range(n_color)) {
90 D0t.data()(range::all, c1, c2) =
91 inputs.D0t(block_number[c1], block_number[c2]).data()(range::all, index_in_block[c1], index_in_block[c2]);
95 for (
auto t : D0t.mesh()) D0t[t] = 0.5 * make_regular(D0t[t] + transpose(D0t[t]));
98 has_Dt = max_element(abs(D0t.data())) > 1.e-13;
99 has_Jperp = max_element(abs(inputs.Jperpt.data())) > 1.e-13;
103 ALWAYS_EXPECTS((not has_Jperp),
"Error : has_jperp is true and we have {} colors instead of 2", n_color);
107 auto ramp = nda::zeros<double>(p.n_tau_bosonic);
108 for (
auto n : range(p.n_tau_bosonic)) { ramp(n) = n * beta / (p.n_tau_bosonic - 1); }
113 K = gf<imtime>({beta, Boson, p.n_tau_bosonic}, {n_color, n_color});
115 for (
auto c1 : range(n_color)) {
116 for (
auto c2 : range(n_color)) {
117 nda::array<dcomplex, 1> D_data = D0t.data()(range::all, c1, c2);
118 auto first_integral = nda::zeros<dcomplex>(p.n_tau_bosonic);
119 auto second_integral = nda::zeros<dcomplex>(p.n_tau_bosonic);
121 for (
int i = 1; i < D_data.size(); ++i) {
122 first_integral(i) = first_integral(i - 1) + (D_data(i) + D_data(i - 1)) / 2;
123 second_integral(i) = second_integral(i - 1) + (first_integral(i) + first_integral(i - 1)) / 2;
126 first_integral *= beta / (p.n_tau_bosonic - 1);
127 second_integral *= (beta / (p.n_tau_bosonic - 1)) * (beta / (p.n_tau_bosonic - 1));
129 Kprime.data()(range::all, c1, c2) = first_integral - second_integral(p.n_tau_bosonic - 1) / beta;
130 K.data()(range::all, c1, c2) = second_integral - ramp * second_integral(p.n_tau_bosonic - 1) / beta;
132 if (c1 != c2) U(c1, c2) -= real(2 * Kprime.data()(0, c1, c2));
134 mu(c1) += real(Kprime.data()(0, c1, c1));
137 spdlog::info(
"\n Renormalized interaction matrix: U = {} \n", fmt::streamed(U));
138 spdlog::info(
"Renormalized orbital energies: mu - eps = {} \n", fmt::streamed(mu));
144 Jperp = inputs.Jperpt;
148 Kprime_spin = gf<imtime>({beta, Boson, p.n_tau_bosonic}, {n_color, n_color});
150 auto Kprime_J = Jperp;
151 nda::array<dcomplex, 1> J_data = Jperp.data()(range::all, 0, 0);
152 auto first_integral = nda::zeros<dcomplex>(p.n_tau_bosonic);
154 for (
int i = 1; i < J_data.size(); ++i) {
155 first_integral(i) = first_integral(i - 1) + (J_data(i) + J_data(i - 1)) / 2;
158 first_integral *= beta / (p.n_tau_bosonic - 1);
160 Kprime_J.data()(range::all, 0, 0) = first_integral - first_integral((p.n_tau_bosonic - 1) / 2);
162 for (
auto c1 : range(n_color)) {
163 for (
auto c2 : range(n_color)) {
164 Kprime_spin.data()(range::all, c1, c2) = (c1 == c2 ? 1 : -1) * Kprime_J.data()(range::all, 0, 0) / 4;
167 auto Kprime_0 = gf<imtime>({beta, Boson, p.n_tau_bosonic}, {n_color, n_color});
168 Kprime_0 = Kprime - Kprime_spin;
170 if (max_element(abs(Kprime_0.data()(range::all, 0, 0) - Kprime_0.data()(range::all, 0, 1))) > 1.e-13)
177 spdlog::info(
"Dynamical interactions = {}, Jperp interactions = {} \n", has_Dt, has_Jperp);
178 if (p.measure_F_tau and !rot_inv)
179 spdlog::info(
"WARNING: Cannot measure F(tau) because spin-spin interaction is not rotationally invariant.");
184 for (
auto const &bl : range(inputs.Delta.size())) {
185 if (max_element(abs(inputs.Delta[bl].data())) > 1.e-13) has_Delta =
true;
187 if (!is_gf_real(inputs.Delta[bl], 1e-10)) {
189 spdlog::info(
"WARNING: The Delta(tau) block number {} is not real in tau space", bl);
190 spdlog::info(
"WARNING: max(Im[Delta(tau)]) = {}", max_element(abs(imag(inputs.Delta[bl].data()))));
191 spdlog::info(
"WARNING: Disregarding the imaginary component in the calculation.");
196 ALWAYS_EXPECTS(has_Jperp,
"Error : both Jperp(tau) and Delta(tau) are 0: there is nothing to expand.");
197 if (c.rank() == 0) { spdlog::info(
"Delta(tau) is 0, running only spin moves."); }
201 for (
auto const &[s, l] : gf_struct) {
202 if (l > 1) offdiag_Delta =
true;
206 Delta = map([](gf_const_view<imtime> d) {
return real(d); }, inputs.Delta);
207 dets.reserve(Delta.size());
208 for (
auto const &bl : range(Delta.size())) {
210 dets.emplace_back(Delta_block_adaptor{Delta[bl]}, p.det_init_size);
212 dets.back().set_singular_threshold(p.det_singular_threshold);
213 dets.back().set_n_operations_before_check(p.det_n_operations_before_check);
214 dets.back().set_precision_warning(p.det_precision_warning);
215 dets.back().set_precision_error(p.det_precision_error);
219 int work_data_t::block_to_color(
int block,
int idx)
const {
220 std::vector<long> gf_block_size_partial_sum;
222 for (
auto const &[s, l] : gf_struct) {
223 gf_block_size_partial_sum.push_back(acc);
226 return gf_block_size_partial_sum[block] + idx;
229 long work_data_t::find_block_number(
int color)
const {
231 long colors_so_far = 0;
232 for (
auto const &[s, l] : gf_struct) {
234 if (color < colors_so_far) {
return bl; }
237 ALWAYS_EXPECTS((colors_so_far == n_color),
"Error in color-to-block conversion.");
241 long work_data_t::find_index_in_block(
int color)
const {
242 long colors_so_far = 0;
243 for (
auto const &[s, l] : gf_struct) {
245 if (color < colors_so_far) {
return color - (colors_so_far - l); }
247 ALWAYS_EXPECTS((colors_so_far == n_color),
"Error in color-to-block conversion.");
252 double trace_sign(work_data_t
const &wdata) {
254 auto const &dets = wdata.dets;
262 for (
auto bl : range(dets.size())) {
263 auto s = long(dets[bl].size());
264 auto n_colors_in_bl = wdata.gf_struct[bl].second;
265 std::vector<int> number_c_before(n_colors_in_bl, 0);
266 std::vector<int> number_cdag_before(n_colors_in_bl, 0);
271 if ((s * (s - 1) / 2) % 2 == 1) { sign *= -1; }
273 for (
int n = 0; n < s; ++n) {
274 auto c_color = dets[bl].get_y(n).second;
275 int n_higher_colors_before = 0;
276 for (
int k = c_color + 1; k < n_colors_in_bl; k++) { n_higher_colors_before += number_c_before[k]; }
277 if (n_higher_colors_before % 2 == 1) sign *= -1;
278 number_c_before[c_color]++;
281 for (
int n = 0; n < s; ++n) {
282 auto cdag_color = dets[bl].get_x(n).second;
283 int n_higher_colors_before = 0;
284 for (
int k = cdag_color + 1; k < n_colors_in_bl; k++) n_higher_colors_before += number_cdag_before[k];
285 if (n_higher_colors_before % 2 == 1) sign *= -1;
286 number_cdag_before[cdag_color]++;
290 auto nb_ops_per_color = number_c_before;
291 for (
int k = 0; k < n_colors_in_bl; ++k) {
292 for (
int l = k + 1; l < n_colors_in_bl; ++l) { nb_transp += nb_ops_per_color[k] * nb_ops_per_color[l]; }
294 if (nb_transp % 2 == 1) sign *= -1;
300 for (
int k = 0; k < n_colors_in_bl; ++k) {
301 int cdag_to_jump = 0;
302 int idx_c = s - 1, idx_cdag = s - 1;
304 auto color_c = dets[bl].get_y(idx_c).second;
305 auto time_c = dets[bl].get_y(idx_c).first;
307 bool keep_going =
true;
308 while (keep_going and (idx_cdag >= 0)) {
309 auto color_cdag = dets[bl].get_x(idx_cdag).second;
310 auto time_cdag = dets[bl].get_x(idx_cdag).first;
311 keep_going = (color_cdag != k) or (time_cdag > time_c);
314 if (color_cdag == k) cdag_to_jump++;
317 if (cdag_to_jump % 2 == 1) sign *= -1;
328 bool c_in_det(
tau_t const &tau, det_t
const &D) {
329 if (D.size() == 0)
return false;
330 auto det_c_time = [&](
long i) {
return D.get_y(i).first; };
331 long det_index_c = lower_bound(det_c_time, D.size(), tau);
332 return (det_index_c >= D.size()) ? false : (det_c_time(det_index_c) == tau);
335 bool cdag_in_det(
tau_t const &tau, det_t
const &D) {
336 if (D.size() == 0)
return false;
337 auto det_cdag_time = [&](
long i) {
return D.get_x(i).first; };
338 long det_index_cdag = lower_bound(det_cdag_time, D.size(), tau);
339 return (det_index_cdag >= D.size()) ? false : (det_cdag_time(det_index_cdag) == tau);
A struct combining both constr_params_t and solve_params_t.