TRIQS/triqs_modest 3.3.0
Modular Electronic Structure Toolkit
Loading...
Searching...
No Matches
degenerate_blocks.hpp
Go to the documentation of this file.
1// Copyright (c) 2025--present, The Simons Foundation
2// This file is part of TRIQS/modest and is licensed under the terms of GPLv3 or later.
3// SPDX-License-Identifier: GPL-3.0-or-later
4// See LICENSE in the root of this distribution for details.
5
6#pragma once
7#include "utils/defs.hpp"
8
9using namespace triqs::gfs;
10
11namespace triqs::modest {
12
27 template <typename Mesh>
28 std::vector<std::vector<long>> analyze_degenerate_blocks(block_gf<Mesh, matrix_valued> const &Gimp, double threshold = 1.e-5) {
29
30 auto n_mesh = Gimp[0].mesh().size();
31 auto n_blocks = Gimp.size();
32
33 std::vector<std::vector<long>> groups;
34 std::vector<bool> used(n_blocks, false);
35
36 auto are_matrices_equal = [threshold, n_mesh](auto const &A, auto const &B) {
37 if (A.target_shape() != B.target_shape()) return false;
38 long n0 = A.target_shape()[0];
39 for (auto mesh_idx : range(n_mesh)) {
40 auto const &Am = A(mesh_idx);
41 auto const &Bm = B(mesh_idx);
42 for (size_t i = 0; i < n0; ++i) {
43 for (size_t j = 0; j < i + 1; ++j) {
44 if (std::abs(Am(i, j) - Bm(i, j)) > threshold) return false;
45 }
46 }
47 }
48 return true;
49 };
50
51 for (auto i = 0; i < n_blocks; ++i) {
52 if (!used[i]) {
53 std::vector<long> current_group = {i};
54 used[i] = true;
55 for (auto j = i + 1; j < n_blocks; ++j) {
56 if (!used[j] && are_matrices_equal(Gimp[i], Gimp[j])) {
57 current_group.push_back(j);
58 used[j] = true;
59 }
60 }
61 groups.push_back(std::move(current_group));
62 }
63 }
64 return groups;
65 }
66
78 template <typename Mesh> block_gf<Mesh, matrix_valued> symmetrize(block_gf<Mesh, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls) {
79 auto gsymm = g;
80 auto const &mesh = gsymm[0].mesh();
81
82 for (auto const &deg_bl : deg_bls) {
83 auto n_deg = deg_bl.size();
84 auto dim = g[deg_bl[0]].target_shape()[0];
85
86 auto gtmp = gf{mesh, {dim, dim}};
87 for (auto bl : deg_bl) { gtmp += g[bl]; }
88
89 gtmp /= n_deg;
90
91 for (auto bl : deg_bl) { gsymm[bl] = gtmp; }
92 }
93
94 return gsymm;
95 }
96
108 template <typename Mesh> gf<Mesh, matrix_valued> symmetrize(gf<Mesh, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls) {
109 auto gsymm = g;
110 auto const &mesh = gsymm.mesh();
111
112 for (auto const &deg_bl : deg_bls) {
113 auto n_deg = deg_bl.size();
114
115 // symmetrize the blocks on the diagonals first
116 auto gtmp_data = nda::zeros<dcomplex>(mesh.size());
117 for (auto ibl : deg_bl) { gtmp_data += g.data()(r_all, ibl, ibl); }
118 gtmp_data /= n_deg;
119 for (auto ibl : deg_bl) { gsymm.data()(r_all, ibl, ibl) = gtmp_data; }
120
121 // symmetrize the off-diagonal blocks
122 auto gtmp_data_off = nda::zeros<dcomplex>(mesh.size());
123 auto n_off = n_deg * (n_deg - 1);
124 for (auto ibl : deg_bl) {
125 for (auto jbl : deg_bl) {
126 if (ibl != jbl) { gtmp_data_off += g.data()(r_all, ibl, jbl); }
127 }
128 }
129 gtmp_data_off /= n_off;
130 for (auto ibl : deg_bl) {
131 for (auto jbl : deg_bl) {
132 if (ibl != jbl) { gsymm.data()(r_all, ibl, jbl) = gtmp_data_off; }
133 }
134 }
135 }
136 return gsymm;
137 }
138
149 inline std::vector<nda::matrix<dcomplex>> symmetrize(std::vector<nda::matrix<dcomplex>> const &bl_mat, std::vector<std::vector<long>> deg_bls) {
150
151 std::vector<nda::matrix<dcomplex>> bl_mat_symm = bl_mat;
152
153 for (auto const &deg_bl : deg_bls) {
154 auto n_deg = deg_bl.size();
155 auto dim = bl_mat[deg_bl[0]].shape()[0];
156
157 auto bl_mat_tmp = nda::zeros<dcomplex>(dim, dim);
158 for (auto bl : deg_bl) { bl_mat_tmp += bl_mat[bl]; }
159
160 bl_mat_tmp /= static_cast<double>(n_deg);
161
162 for (auto bl : deg_bl) { bl_mat_symm[bl] = bl_mat_tmp; }
163 }
164
165 return bl_mat_symm;
166 }
167
168 template std::vector<std::vector<long>> analyze_degenerate_blocks(block_gf<dlr_imfreq, matrix_valued> const &G, double threshold);
169 template std::vector<std::vector<long>> analyze_degenerate_blocks(block_gf<dlr_imtime, matrix_valued> const &G, double threshold);
170 template std::vector<std::vector<long>> analyze_degenerate_blocks(block_gf<imfreq, matrix_valued> const &G, double threshold);
171 template std::vector<std::vector<long>> analyze_degenerate_blocks(block_gf<imtime, matrix_valued> const &G, double threshold);
172
173 template block_gf<imfreq, matrix_valued> symmetrize(block_gf<imfreq, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls);
174 template block_gf<imtime, matrix_valued> symmetrize(block_gf<imtime, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls);
175 template block_gf<dlr_imfreq, matrix_valued> symmetrize(block_gf<dlr_imfreq, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls);
176 template block_gf<dlr_imtime, matrix_valued> symmetrize(block_gf<dlr_imtime, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls);
177
178 template gf<imfreq, matrix_valued> symmetrize(gf<imfreq, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls);
179 template gf<imtime, matrix_valued> symmetrize(gf<imtime, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls);
180 template gf<dlr_imfreq, matrix_valued> symmetrize(gf<dlr_imfreq, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls);
181 template gf<dlr_imtime, matrix_valued> symmetrize(gf<dlr_imtime, matrix_valued> const &g, std::vector<std::vector<long>> deg_bls);
182} // namespace triqs::modest
block_gf< Mesh, matrix_valued > symmetrize(block_gf< Mesh, matrix_valued > const &g, std::vector< std::vector< long > > deg_bls)
Symmetrize the blocks of a block Green's function given a list of it's degenerate blocks.
std::vector< std::vector< long > > analyze_degenerate_blocks(block_gf< Mesh, matrix_valued > const &Gimp, double threshold=1.e-5)
Find the generate blocks of a block GF by analyzing or using the union-find algorithm.
static constexpr auto r_all
Definition defs.hpp:33