TRIQS/triqs_modest 3.3.0
Modular Electronic Structure Toolkit
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 <nda/mpi.hpp>
11#include <mpi/mpi.hpp>
12#include <triqs/gfs.hpp>
14#include <triqs/utility/macros.hpp>
15
16namespace triqs::modest {
17
18 // IBZ symmetry operations to obtain observables (equivalent to summing on FBZ).
19
20 // NB: if SOC and time inversion present <T*O> = <K^-1 O K> = <transpose(O)>.
21 // FIXME : OP : document the size of matrices, meaning of permutations.
22 // FIXME OP : rename into ibz_symmetrizer
23 // FIMXE HL : can we generalize to work on any type T that supports matrix multiplication?
24
49
50 //-----------------------------------------------------------------------------------
52 struct op {
53 std::vector<nda::matrix<dcomplex>> mats; // mats[i_alpha]
54 std::vector<long> permutation; // permutation [i_alpha]
55 long time_inv; // FIXME : we should supress/comment this ?
56
58 bool operator==(op const &) const = default;
59
61 C2PY_IGNORE friend void mpi_broadcast(op &x, mpi::communicator c = {}, int root = 0) {
62 mpi::broadcast(x.mats, c, root);
63 mpi::broadcast(x.permutation, c, root);
64 mpi::broadcast(x.time_inv, c, root);
65 }
66 };
68 std::vector<op> ops; // ops[i_sym]
69
71 bool operator==(ibz_symmetry_ops const &) const = default;
72
74 C2PY_IGNORE friend void mpi_broadcast(ibz_symmetry_ops &x, mpi::communicator c = {}, int root = 0) { mpi::broadcast(x.ops, c, root); }
75
76 // printing
77 friend std::ostream &operator<<(std::ostream &out, ibz_symmetry_ops const &ibz);
78
79 //-----------------------------------------------------------------------------------
80 template <typename T> nda::array<T, 2> symmetrize(nda::array<T, 2> const &X) const {
81 auto [n_alpha, n_sigma] = X.shape();
82 nda::array<T, 2> result(n_alpha, n_sigma);
83 for (auto [a, s] : result.indices()) { result(a, s) = nda::zeros<dcomplex>(X(a, s).shape()); }
84 auto n_symm = double(this->ops.size());
85 for (auto const &sym_op : this->ops) {
86 for (auto &&[ialpha, jalpha, mat] : zip(range(n_alpha), sym_op.permutation, sym_op.mats)) {
87 for (auto sigma : range(n_sigma)) {
88 result(jalpha, sigma) += mat * (sym_op.time_inv ? transpose(X(ialpha, sigma)) : X(ialpha, sigma)) * dagger(mat) / n_symm;
89 } // end loop on sigma
90 } // end loop on alpha
91 } // end loop on ops
92 return result;
93 }
94
95 // -------------------------------------------------------------------------------------------
96
97 // FIXME : Pas Gin in the atomic decomposition directly ??
98 // as a block2_gf_view ??
99 // Or array<gf_view, 2> ??
100 template <typename Mesh>
101 block2_gf<Mesh, matrix_valued> symmetrize(block2_gf<Mesh, matrix_valued> const &Gin, auto const &atomic_decomposition) const {
102 // FIXME : copy it , take atom_ivew of it, operate and return it.
103 // 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.
104 auto Gout = make_block2_gf(Gin(0, 0).mesh(), get_struct(Gin));
105 auto n_sigma = Gout.size2();
106 auto n_symm = double(this->ops.size());
107
108 auto range_list =
109 enumerated_sub_slices(atomic_decomposition) | stdv::transform([](auto &&x) { return std::get<1>(x); }) | tl::to<std::vector>();
110
111 for (auto [alpha, R_alpha] : enumerated_sub_slices(atomic_decomposition)) { // loop on alpha
112 for (auto sigma : range(n_sigma)) { // loop on sigma
113 for (auto const &op : this->ops) { // loop on ops
114 auto const &mat = op.mats[alpha];
115 auto R_jalpha = range_list[op.permutation[alpha]];
116 for (auto om : Gin(0, sigma).mesh()) { // loop on mesh
117 auto A = nda::matrix<dcomplex>{Gin(0, sigma)[om](R_alpha, R_alpha)};
118 Gout(0, sigma)[om](R_jalpha, R_jalpha) += mat * (op.time_inv ? transpose(A) : A) * dagger(mat) / n_symm;
119 } // end loop on mesh
120 } // end loop on ops
121 } // end loop on sigma
122 } // end loop on alpha
123 return Gout;
124 }
125 };
126
134 inline ibz_symmetry_ops rotate_local_basis(nda::array<nda::matrix<dcomplex>, 2> const &U, ibz_symmetry_ops const &x) {
135 auto result = x;
136 for (auto &sym_op : result.ops)
137 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);
138 return result;
139 }
140
141} // namespace triqs::modest
#define C2PY_IGNORE
Definition defs.hpp:17
gf_struct2_t get_struct(block2_gf< Mesh, matrix_valued > const &g)
Definition gf_supp.hpp:52
block2_gf< Mesh, matrix_valued > make_block2_gf(Mesh const &mesh, gf_struct2_t const &gf_s)
Definition gf_supp.hpp:41
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)
Irreducible Brillouin Zone (IBZ) symmetry operations to symmetrize observables over the entire Brillo...
friend std::ostream & operator<<(std::ostream &out, ibz_symmetry_ops const &ibz)
Definition printing.cpp:63
bool operator==(ibz_symmetry_ops const &) const =default
Equality comparison operator.
C2PY_IGNORE friend void mpi_broadcast(ibz_symmetry_ops &x, mpi::communicator c={}, int root=0)
MPI broadcast.
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