TRIQS/triqs_modest 3.3.0
Brillouin zone summation
Loading...
Searching...
No Matches
ibz_symmetry_ops.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#include "utils/gf_supp.hpp"
9#include <nda/nda.hpp>
10#include <triqs/gfs.hpp>
12
13namespace triqs::modest {
14
15 // IBZ symmetry operations to obtain observables (equivalent to summing on FBZ).
16
17 // NB: if SOC and time inversion present <T*O> = <K^-1 O K> = <transpose(O)>.
18 // FIXME : OP : document the size of matrices, meaning of permutations.
19 // FIXME OP : rename into ibz_symmetrizer
20 // FIMXE HL : can we generalize to work on any type T that supports matrix multiplication?
27
28 //-----------------------------------------------------------------------------------
30 struct op {
31 std::vector<nda::matrix<dcomplex>> mats; // mats[i_alpha]
32 std::vector<long> permutation; // permutation [i_alpha]
33 long time_inv; // FIXME : we should supress/comment this ?
34 };
36 std::vector<op> ops; // ops[i_sym]
37
38 // printing
39 friend std::ostream &operator<<(std::ostream &out, ibz_symmetry_ops const &ibz);
40
41 //-----------------------------------------------------------------------------------
42 template <typename T> nda::array<T, 2> symmetrize(nda::array<T, 2> const &X) const {
43 auto [n_alpha, n_sigma] = X.shape();
44 nda::array<T, 2> result(n_alpha, n_sigma);
45 for (auto [a, s] : result.indices()) { result(a, s) = nda::zeros<dcomplex>(X(a, s).shape()); }
46 auto n_symm = double(this->ops.size());
47 for (auto const &sym_op : this->ops) {
48 for (auto &&[ialpha, jalpha, mat] : zip(range(n_alpha), sym_op.permutation, sym_op.mats)) {
49 for (auto sigma : range(n_sigma)) {
50 result(jalpha, sigma) += mat * (sym_op.time_inv ? transpose(X(ialpha, sigma)) : X(ialpha, sigma)) * dagger(mat) / n_symm;
51 } // end loop on sigma
52 } // end loop on alpha
53 } // end loop on ops
54 return result;
55 }
56
57 // -------------------------------------------------------------------------------------------
58
59 // FIXME : Pas Gin in the atomic decomposition directly ??
60 // as a block2_gf_view ??
61 // Or array<gf_view, 2> ??
62 template <typename Mesh>
63 block2_gf<Mesh, matrix_valued> symmetrize(block2_gf<Mesh, matrix_valued> const &Gin, auto const &atomic_decomposition) const {
64 // FIXME : copy it , take atom_ivew of it, operate and return it.
65 // FIXME : are we sure all Gin have the same mesh ? We use this internally and we have a check at E.embed that the meshes are the same. We could add this here.
66 auto Gout = make_block2_gf(Gin(0, 0).mesh(), get_struct(Gin));
67 auto n_sigma = Gout.size2();
68 auto n_symm = double(this->ops.size());
69
70 auto range_list =
71 enumerated_sub_slices(atomic_decomposition) | stdv::transform([](auto &&x) { return std::get<1>(x); }) | tl::to<std::vector>();
72
73 for (auto [alpha, R_alpha] : enumerated_sub_slices(atomic_decomposition)) { // loop on alpha
74 for (auto sigma : range(n_sigma)) { // loop on sigma
75 for (auto const &op : this->ops) { // loop on ops
76 auto const &mat = op.mats[alpha];
77 auto R_jalpha = range_list[op.permutation[alpha]];
78 for (auto om : Gin(0, sigma).mesh()) { // loop on mesh
79 auto A = nda::matrix<dcomplex>{Gin(0, sigma)[om](R_alpha, R_alpha)};
80 Gout(0, sigma)[om](R_jalpha, R_jalpha) += mat * (op.time_inv ? transpose(A) : A) * dagger(mat) / n_symm;
81 } // end loop on mesh
82 } // end loop on ops
83 } // end loop on sigma
84 } // end loop on alpha
85 return Gout;
86 }
87 };
88
96 inline ibz_symmetry_ops rotate_local_basis(nda::array<nda::matrix<dcomplex>, 2> const &U, ibz_symmetry_ops const &x) {
97 auto result = x;
98 for (auto &sym_op : result.ops)
99 for (auto &&[a, b] : zip(range(U.extent(0)), sym_op.permutation)) sym_op.mats[a] = dagger(U(b, 0)) * sym_op.mats[a] * U(a, 0);
100 return result;
101 }
102
103} // namespace triqs::modest
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
Definition gf_supp.hpp:41
gf_struct_t get_struct(block_gf< Mesh > const &g)
Definition gf_supp.hpp:51
one_body_elements_on_grid rotate_local_basis(nda::array< nda::matrix< dcomplex >, 2 > const &U, one_body_elements_on_grid const &x)
Rotates the local basis of the downfolding projector.
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
friend std::ostream & operator<<(std::ostream &out, ibz_symmetry_ops const &ibz)
Definition printing.cpp:63
block2_gf< Mesh, matrix_valued > symmetrize(block2_gf< Mesh, matrix_valued > const &Gin, auto const &atomic_decomposition) const
nda::array< T, 2 > symmetrize(nda::array< T, 2 > const &X) const