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
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
58 inline std::vector<std::vector<long>> analyze_degenerate_blocks(block_gf<imfreq, matrix_valued> const &Gimp, double threshold = 1.e-5) {
59 auto find_degenerate = [&](auto const &G) {
60 auto are_matrices_equal = [threshold](auto const &A, auto const &B) {
61 if (A.shape() != B.shape()) return false;
62 return nda::all(nda::map([threshold](auto x) { return x < threshold; })(abs(A - B)));
63 };
64 // convert G to list of matrices at Mesh = 0
65 auto midpt = static_cast<long>(G[0].mesh().size() / 2);
66 auto mats = G | stdv::transform([midpt](auto const &g) { return nda::matrix<dcomplex>{g(midpt)}; }) | tl::to<std::vector>();
67
68 auto uf = detail::union_find(mats.size());
69
70 std::map<long, std::vector<long>> groups_map;
71 for (long i = 0; i < mats.size(); ++i) {
72 for (long j = i + 1; j < mats.size(); ++j) {
73 if (are_matrices_equal(mats[i], mats[j])) uf.unite(i, j);
74 }
75 groups_map[uf.find(i)].emplace_back(i);
76 }
77
78 return groups_map | stdv::values | stdv::filter([](auto const &g) { return g.size() > 1; }) | tl::to<std::vector>();
79 };
80 return find_degenerate(Gimp) | stdv::transform([](auto &x) { return x | stdv::transform([](auto &y) { return y; }) | tl::to<std::vector>(); })
81 | tl::to<std::vector>();
82 }
83
94 inline block_gf<imfreq, matrix_valued> symmetrize_gf(block_gf<imfreq, matrix_valued> const &Gin, std::vector<std::vector<long>> degenerate_blocks) {
95 auto Gsymm = Gin;
96 auto mesh = Gsymm[0].mesh();
97 for (auto degenerate : degenerate_blocks) {
98 auto n_deg = degenerate.size();
99 auto dim = Gin[degenerate[0]].target_shape()[0];
100 auto gtmp = gf{mesh, {dim, dim}};
101 for (auto deg_bl : degenerate) { gtmp += Gin[deg_bl] / n_deg; }
102 for (auto deg_bl : degenerate) { Gsymm[deg_bl] = gtmp; }
103 }
104 return Gsymm;
105 }
106
107} // 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 block GF by analyzing or using the union-find algorithm.