TRIQS/triqs_modest 3.3.0
Brillouin zone summation
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
8
9using namespace triqs::gfs;
10
11namespace triqs::modest {
12
13 namespace detail {
14
16 struct union_find {
17 std::vector<long> parent;
18
19 union_find(long n) { parent = range(n) | tl::to<std::vector<long>>(); };
20
22 long find(long x) {
23 if (parent[x] != x) { parent[x] = find(parent[x]); }
24 return parent[x];
25 }
26
28 void unite(long x, long y) {
29 long px = find(x);
30 long py = find(y);
31 if (px != py) parent[px] = py;
32 }
33 };
34
35 } // namespace detail
36
37 // HL: TODO the dft_tools analyse_degenerate_blocks (or analyse_deg_shells) did the following steps:
38 // 1. Make G(tau) hermitian
39 // 2. diagonalize G(tau = 0)
40 // 3. Compare eigenvalues.
41 // 4. if eigenvalues are the same to epsilon
42 // 5. Rotate all blocks using the eigenvectors which constitute a unitary transformation.
43 // Do we agree with this algorithm and want the same?
44
57 inline std::vector<std::vector<long>> analyze_degenerate_blocks(block_gf<imfreq, matrix_valued> const &Gimp, double threshold = 1.e-5) {
58 auto find_degenerate = [&](auto const &G) {
59 auto are_matrices_equal = [threshold](auto const &A, auto const &B) {
60 if (A.shape() != B.shape()) return false;
61 return nda::all(nda::map([threshold](auto x) { return x < threshold; })(abs(A - B)));
62 };
63 // convert G to list of matrices at Mesh = 0
64 auto midpt = static_cast<long>(G[0].mesh().size() / 2);
65 auto mats = G | stdv::transform([midpt](auto const &g) { return nda::matrix<dcomplex>{g(midpt)}; }) | tl::to<std::vector>();
66
67 auto uf = detail::union_find(mats.size());
68
69 std::map<long, std::vector<long>> groups_map;
70 for (long i = 0; i < mats.size(); ++i) {
71 for (long j = i + 1; j < mats.size(); ++j) {
72 if (are_matrices_equal(mats[i], mats[j])) uf.unite(i, j);
73 }
74 groups_map[uf.find(i)].emplace_back(i);
75 }
76
77 return groups_map | stdv::values | stdv::filter([](auto const &g) { return g.size() > 1; }) | tl::to<std::vector>();
78 };
79 return find_degenerate(Gimp) | stdv::transform([](auto &x) { return x | stdv::transform([](auto &y) { return y; }) | tl::to<std::vector>(); })
80 | tl::to<std::vector>();
81 }
82
93 inline block_gf<imfreq, matrix_valued> symmetrize_gf(block_gf<imfreq, matrix_valued> const &Gin, std::vector<std::vector<long>> degenerate_blocks) {
94 auto Gsymm = Gin;
95 auto mesh = Gsymm[0].mesh();
96 for (auto degenerate : degenerate_blocks) {
97 auto n_deg = degenerate.size();
98 auto dim = Gin[degenerate[0]].target_shape()[0];
99 auto gtmp = gf{mesh, {dim, dim}};
100 for (auto deg_bl : degenerate) { gtmp += Gin[deg_bl] / n_deg; }
101 for (auto deg_bl : degenerate) { Gsymm[deg_bl] = gtmp; }
102 }
103 return Gsymm;
104 }
105
106} // namespace triqs::modest
block_gf< imfreq, matrix_valued > symmetrize_gf(block_gf< imfreq, matrix_valued > const &Gin, std::vector< std::vector< long > > degenerate_blocks)
Symmetrize the blocks of a Green's function given a list of it's degenerate blocks.
std::vector< std::vector< long > > analyze_degenerate_blocks(block_gf< imfreq, matrix_valued > const &Gimp, double threshold=1.e-5)
Find the generate blocks of a BlockGf by analyzing G(τ=0) or G(iω₀) using the union-find algorithm.