TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
gf_sym_grp.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2013-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2023 Simons Foundation
4// Copyright (c) 2023 Hugo U.R. Strand
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You may obtain a copy of the License at
17// https://www.gnu.org/licenses/gpl-3.0.txt
18//
19// Authors: Dominik Kiese, Nils Wentzell
20
25
26#pragma once
27
28#include "./gf/gf.hpp"
29
30#include <nda/sym_grp.hpp>
31
32#include <array>
33#include <cstddef>
34#include <functional>
35#include <tuple>
36#include <utility>
37#include <vector>
38
39namespace triqs::gfs {
40
45
56 template <typename F, typename G, typename mesh_index_t = typename G::mesh_t::index_t>
58 requires(F f, mesh_index_t const &mesh_index) {
59 requires(G::target_rank == 0);
60 { f(mesh_index) } -> std::same_as<std::tuple<mesh_index_t, nda::operation>>;
61 };
62
74 template <typename F, typename G, typename mesh_index_t = typename G::mesh_t::index_t,
75 typename target_index_t = std::array<long, static_cast<std::size_t>(G::target_rank)>>
77 requires(F f, mesh_index_t const &mesh_index, target_index_t const &target_index) {
78 requires(G::target_rank > 0);
79 { f(mesh_index, target_index) } -> std::same_as<std::tuple<mesh_index_t, target_index_t, nda::operation>>;
80 };
81
91 template <typename F, typename G, typename mesh_index_t = typename G::mesh_t::index_t>
93 requires(F f, mesh_index_t const &mesh_index) {
94 requires(G::target_rank == 0);
95 { f(mesh_index) } -> std::same_as<typename G::scalar_t>;
96 };
97
109 template <typename F, typename G, typename mesh_index_t = typename G::mesh_t::index_t,
110 typename target_index_t = std::array<long, static_cast<std::size_t>(G::target_rank)>>
112 requires(F f, mesh_index_t const &mesh_index, target_index_t const &target_index) {
113 requires(G::target_rank > 0);
114 { f(mesh_index, target_index) } -> std::same_as<typename G::scalar_t>;
115 };
116
117 // make tuple from array
118 template <typename A> auto to_tuple(A const &arr) {
119 constexpr auto fetch = [](auto const &...xs) { return std::tuple{xs...}; };
120 return std::apply(fetch, arr);
121 }
122
123 // make tuple from array using index_sequence
124 template <std::size_t R, typename A> auto to_tuple(A const &arr) {
125 return [&]<std::size_t... Is>(std::index_sequence<Is...>) { return std::tuple{arr[Is]...}; }(std::make_index_sequence<R>{});
126 }
127
128 // make array from tuple
129 template <typename tpl_t> auto to_array(tpl_t const &tpl) {
130 constexpr auto fetch = [](auto const &...xs) { return std::array{xs...}; };
131 return std::apply(fetch, tpl);
132 }
133
145 template <typename F, typename G>
147 class sym_grp {
148
149 private:
150 // data aliases
151 using data_t = typename G::data_t;
152 using value_t = typename G::scalar_t;
153 using data_index_t = std::array<long, static_cast<std::size_t>(nda::get_rank<data_t>)>;
154 using data_sym_func_t = std::function<std::tuple<data_index_t, nda::operation>(data_index_t const &)>;
155 using data_init_func_t = std::function<value_t(data_index_t const &)>;
156
157 // mesh aliases
158 using mesh_index_t = typename G::mesh_t::index_t;
159 static constexpr auto mesh_rank = n_variables<typename G::mesh_t>;
160
161 // target aliases
162 static constexpr size_t target_rank = G::target_rank;
163 using target_index_t = std::array<long, static_cast<std::size_t>(target_rank)>;
164
165 // members
166 nda::sym_grp<data_sym_func_t, data_t> data_sym_grp; // symmetry group instance for the data array
167
168 // convert from gf to nda symmetry
169 data_sym_func_t to_data_symmetry(F const &f, G const &g) const {
170
171 auto fp = [f, m = g.mesh()](data_index_t const &x) -> std::tuple<data_index_t, nda::operation> {
172 // init new data index and residual operation
173 data_index_t xp;
174
175 if constexpr (target_rank == 0) { // scalar valued gfs
176
177 if constexpr (mesh_rank == 1) {
178 auto [new_mesh_index, op] = f(m.to_index(x[0]));
179 xp[0] = m.to_data_index(new_mesh_index);
180 return {xp, op};
181
182 } else { // product mesh
183 auto [new_mesh_index, op] = f(m.to_index(to_tuple(x)));
184 xp = to_array(m.to_data_index(new_mesh_index));
185 return {xp, op};
186 }
187
188 } else { // tensor valued gfs
189
190 // convert data index to target index
191 target_index_t target_index;
192 for (auto i : range(target_rank)) target_index[i] = x[i + mesh_rank];
193
194 if constexpr (mesh_rank == 1) {
195 // evaluate symmetry
196 auto [new_mesh_index, new_target_index, op] = f(m.to_index(x[0]), target_index);
197
198 // convert mesh index + target index back to data index
199 xp[0] = m.to_data_index(new_mesh_index);
200 for (auto i : range(target_rank)) xp[i + mesh_rank] = new_target_index[i];
201
202 return {xp, op};
203
204 } else { // product mesh
205 // evaluate symmetry
206 auto [new_mesh_index, new_target_index, op] = f(m.to_index(to_tuple<mesh_rank>(x)), target_index);
207
208 // convert mesh index + target index back to data index
209 auto new_mesh_arr = to_array(m.to_data_index(new_mesh_index));
210 for (auto i : range(mesh_rank)) xp[i] = new_mesh_arr[i];
211 for (auto i : range(target_rank)) xp[i + mesh_rank] = new_target_index[i];
212
213 return {xp, op};
214 }
215 }
216 };
217
218 return fp;
219 };
220
221 // convert from list of gf symmetries to list of nda symmetries
222 std::vector<data_sym_func_t> to_data_symmetry_list(G const &g, std::vector<F> const &sym_list) const {
223 std::vector<data_sym_func_t> data_sym_list;
224 for (auto f : sym_list) data_sym_list.push_back(to_data_symmetry(f, g));
225 return data_sym_list;
226 }
227
228 // convert from gf to nda init function
229 template <typename H> data_init_func_t to_data_init_func(G const &g, H const &h) const {
230
231 auto hp = [h, m = g.mesh()](data_index_t const &x) {
232 if constexpr (target_rank == 0) { // scalar valued gfs
233
234 if constexpr (mesh_rank == 1) {
235 return h(m.to_index(x[0]));
236
237 } else { // product mesh
238 return h(m.to_index(to_tuple(x)));
239 }
240
241 } else { // tensor valued gfs
242
243 target_index_t target_index;
244 for (auto i : range(target_rank)) target_index[i] = x[i + mesh_rank];
245
246 if constexpr (mesh_rank == 1) {
247 return h(m.to_index(x[0]), target_index);
248
249 } else { // product mesh
250 return h(m.to_index(to_tuple<mesh_rank>(x)), target_index);
251 }
252 }
253 };
254
255 return hp;
256 }
257
258 public:
264 [[nodiscard]] nda::sym_grp<data_sym_func_t, data_t> const &get_data_sym_grp() const { return data_sym_grp; }
265
271 [[nodiscard]] long num_classes() const { return data_sym_grp.num_classes(); }
272
279 [[nodiscard]] std::vector<value_t> get_representative_data(G const &g) const { return data_sym_grp.get_representative_data(g.data()); }
280
288 template <typename V> void init_from_representative_data(G &g, V const &vec) const { data_sym_grp.init_from_representative_data(g.data(), vec); }
289
293 sym_grp() = default;
294
302 sym_grp(G const &g, std::vector<F> const &sym_list, long const max_length = 0)
303 : data_sym_grp{g.data(), to_data_symmetry_list(g, sym_list), max_length} {};
304
316 template <typename H>
317 void init(G &g, H const &h, bool parallel = false) const
318 requires(ScalarGfInitFunc<H, G> || TensorGfInitFunc<H, G>)
319 {
320 data_sym_grp.init(g.data(), to_data_init_func(g, h), parallel);
321 }
322
332 std::tuple<double, mesh_index_t, target_index_t> symmetrize(G &g) const {
333 auto const &[max_diff, max_index] = data_sym_grp.symmetrize(g.data());
334 auto const m = g.mesh();
335
336 if constexpr (target_rank == 0) { // scalar valued gfs
337
338 if constexpr (mesh_rank == 1) {
339 return {max_diff, m.to_index(max_index[0]), {}};
340
341 } else { // product mesh
342 return {max_diff, m.to_index(to_tuple(max_index)), {}};
343 }
344
345 } else { // tensor valued gfs
346
347 // convert data index to target index
348 target_index_t target_index;
349 for (auto i : range(target_rank)) target_index[i] = max_index[i + mesh_rank];
350
351 if constexpr (mesh_rank == 1) {
352 return {max_diff, m.to_index(max_index[0]), target_index};
353
354 } else { // product mesh
355 return {max_diff, m.to_index(to_tuple<mesh_rank>(max_index)), target_index};
356 }
357 }
358 }
359 };
360
362
363} // namespace triqs::gfs
data_t & data()
Direct access to the blocks.
long num_classes() const
Accessor for the number of symmetry classes.
void init(G &g, H const &h, bool parallel=false) const
Initialize a Green's function using an init function.
sym_grp(G const &g, std::vector< F > const &sym_list, long const max_length=0)
Construct the symmetry group of a Green's function from a list of symmetries.
nda::sym_grp< data_sym_func_t, data_t > const & get_data_sym_grp() const
Accessor for the symmetry group of the data array.
sym_grp()=default
Default constructor.
void init_from_representative_data(G &g, V const &vec) const
Initialize a Green's function from its representative data using the symmetries.
std::tuple< double, mesh_index_t, target_index_t > symmetrize(G &g) const
Symmetrize a Green's function in place.
std::vector< value_t > get_representative_data(G const &g) const
Reduce a Green's function to its representative data using the symmetries.
Initializer-function concept for scalar-valued Green's functions.
Symmetry concept for scalar-valued Green's functions.
Initializer-function concept for tensor-valued Green's functions.
Symmetry concept for tensor-valued Green's functions.
static constexpr int n_variables
Constexpr variable that holds the number of meshes in a triqs::mesh::Mesh type ( for non-product mes...
Definition utils.hpp:154
Provides the Green's function class.
constexpr bool is_gf_v
Trait to check whether a type models the Green's function concept.
Definition gf.hpp:101