TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
_block_gf_view_common.hpp
Go to the documentation of this file.
1// Copyright (c) 2020-2023 Simons Foundation
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You may obtain a copy of the License at
14// https://www.gnu.org/licenses/gpl-3.0.txt
15//
16// Authors: Michel Ferrero, Olivier Parcollet, Nils Wentzell
17
22
23// This is not a standalone header: it is #included inside the bodies of the block_gf / block_gf_view classes, so it
24// cannot carry its own #include directives. The including files must provide, in addition to the block-gf machinery:
25// - <h5/h5.hpp> (via ../../arrays.hpp): h5::group, h5_write/h5_read, read/write_hdf5_format
26// - ../../utility/exceptions.hpp: TRIQS_RUNTIME_ERROR
27// - ../../utility/macros.hpp: EXPECTS
28// - <itertools/itertools.hpp>: itertools::enumerate, itertools::zip
29// - nda::clef (via ../../arrays.hpp): clef::make_expr_call, clef::make_expr_subscript
30// - <iterator> (std::forward_iterator_tag), <string> (std::string), <type_traits>, <vector> (std::vector)
31
32// common to many classes
33
34// ------------- Accessors -----------------------------
35
40data_t &data() { return _glist; }
41
46data_t const &data() const { return _glist; }
47
52block_names_t const &block_names() const { return _block_names; }
53
61std::vector<int> block_sizes() const {
62 static_assert(g_t::target_t::rank == 2);
63 auto res = std::vector<int>(_glist.size());
64 for (auto [i, g] : itertools::enumerate(_glist)) {
65 EXPECTS(g.target_shape()[0] == g.target_shape()[1]);
66 res[i] = g.target_shape()[0];
67 }
68 return res;
69}
70
78gf_struct_t gf_struct() const {
79 gf_struct_t result;
80 for (auto [blk_name, size] : itertools::zip(block_names(), block_sizes())) result.emplace_back(blk_name, size);
81 return result;
82}
83
88int size1() const
89 requires(Arity == 2)
90{
91 return _glist.size();
92}
93
98int size2() const
99 requires(Arity == 2)
100{
101 return _glist.at(0).size();
102}
103
108int size() const {
109 if constexpr (Arity == 1) {
110 return _glist.size();
111 } else {
112 return size1() * size2();
113 }
114}
115
116private:
117// Assign block by block from a right hand side modeling the block-gf concept, copying its block names.
118// NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward): rhs is read block-wise (operator[]/()), not forwarded
119template <typename RHS> void _assign_impl(RHS &&rhs) {
120
121 if constexpr (Arity == 1) {
122 for (int w = 0; w < size(); ++w) _glist[w] = rhs[w];
123 } else {
124 for (int w = 0; w < size1(); ++w)
125 for (int v = 0; v < size2(); ++v) _glist[w][v] = rhs(w, v);
126 }
127 _block_names = rhs.block_names();
128}
129
130public:
131// ------------- All the call operators without lazy arguments -----------------------------
132
133// First, a simple () returns a view, like for an array...
135const_view_type operator()() const { return *this; }
136
138view_type operator()() { return *this; }
139
145decltype(auto) operator()(int n) const
146 requires(Arity == 1)
147{
148 return _glist[n];
149}
150
157decltype(auto) operator()(int n1, int n2) const
158 requires(Arity == 2)
159{
160 return _glist[n1][n2];
161}
162
169decltype(auto) operator()(int n1, int n2)
170 requires(Arity == 2)
171{
172 return _glist[n1][n2];
173}
174
175// ------------- Call with lazy arguments -----------------------------
176
182template <typename... Args>
183auto operator()(Args &&...args) &
184 requires(nda::clef::is_clef_expression<Args...>)
185{
186 return clef::make_expr_call(*this, std::forward<Args>(args)...);
187}
188
190template <typename... Args>
191auto operator()(Args &&...args) const &
192 requires(nda::clef::is_clef_expression<Args...>)
193{
194 return clef::make_expr_call(*this, std::forward<Args>(args)...);
195}
196
198template <typename... Args>
199auto operator()(Args &&...args) &&
200 requires(nda::clef::is_clef_expression<Args...>)
201{
202 return clef::make_expr_call(std::move(*this), std::forward<Args>(args)...);
203}
204
205// ------------- All the [] operators without lazy arguments -----------------------------
206
212decltype(auto) operator[](int n) const
213 requires(Arity == 1)
214{
215 return _glist[n];
216}
217
223decltype(auto) operator[](int n)
224 requires(Arity == 1)
225{
226 return _glist[n];
227}
228
229// ------------- [] with lazy arguments -----------------------------
230
237template <typename Arg>
238auto operator[](Arg &&arg) const &
239 requires(nda::clef::is_clef_expression<Arg>)
240{
241 return clef::make_expr_subscript(*this, std::forward<Arg>(arg));
242}
243
245template <typename Arg>
246auto operator[](Arg &&arg) &
247 requires(nda::clef::is_clef_expression<Arg>)
248{
249 return clef::make_expr_subscript(*this, std::forward<Arg>(arg));
250}
251
253template <typename Arg>
254auto operator[](Arg &&arg) &&
255 requires(nda::clef::is_clef_expression<Arg>)
256{
257 return clef::make_expr_subscript(std::move(*this), std::forward<Arg>(arg));
258}
259
260//----------------------------- HDF5 -----------------------------
261
266[[nodiscard]] static std::string hdf5_format() {
267 if constexpr (Arity == 1)
268 return "BlockGf";
269 else
270 return "Block2Gf";
271}
272
280friend void h5_write(h5::group fg, std::string const &subgroup_name, this_t const &g) {
281 auto gr = fg.create_group(subgroup_name);
282 write_hdf5_format(gr, g);
283
284 if constexpr (Arity == 1) {
285 h5_write(gr, "block_names", g.block_names());
286 for (int i = 0; i < g.size(); ++i) h5_write(gr, g.block_names()[i], g.data()[i]);
287 } else {
288 h5_write(gr, "block_names1", g.block_names()[0]);
289 h5_write(gr, "block_names2", g.block_names()[1]);
290 for (int i = 0; i < g.size1(); ++i)
291 for (int j = 0; j < g.size2(); ++j) h5_write(gr, g.block_names()[0][i] + "_" + g.block_names()[1][j], g._glist[i][j]);
292 }
293}
294
304friend void h5_read(h5::group fg, std::string const &subgroup_name, this_t &g) {
305 auto gr = fg.open_group(subgroup_name);
306 // Check the attribute or throw
307 auto tag_file = read_hdf5_format(gr);
308 auto tag_expected = this_t::hdf5_format();
309 if (tag_file != tag_expected)
310 TRIQS_RUNTIME_ERROR << "h5_read : mismatch of the Format tag in the h5 group : found " << tag_file << " while I expected " << tag_expected;
311 if constexpr (Arity == 1) {
312
313 auto block_names = h5::h5_read<std::vector<std::string>>(gr, "block_names");
314 int s = block_names.size();
315 g._glist.resize(s);
316 g._block_names = block_names;
317 for (int i = 0; i < s; ++i) h5_read(gr, block_names[i], g._glist[i]);
318 } else {
319 auto block_names1 = h5::h5_read<std::vector<std::string>>(gr, "block_names1");
320 auto block_names2 = h5::h5_read<std::vector<std::string>>(gr, "block_names2");
321 auto block_names = std::vector<std::vector<std::string>>{block_names1, block_names2};
322 int s0 = block_names[0].size();
323 int s1 = block_names[1].size();
324 g._glist.resize(s0);
325 g._block_names = block_names;
326 for (int i = 0; i < s0; ++i) {
327 g._glist[i].resize(s1);
328 for (int j = 0; j < s1; ++j) h5_read(gr, block_names[0][i] + "_" + block_names[1][j], g._glist[i][j]);
329 }
330 }
331}
332
333// ------------------------------- iterator --------------------------------------------------
334
342template <bool is_const> class iterator_impl {
343 std::conditional_t<is_const, const this_t *, this_t *> bgf = NULL;
344 int n;
345
346 public:
347 using iterator_category = std::forward_iterator_tag;
348 using value_type = g_t;
349 using difference_type = std::ptrdiff_t;
350 using pointer = std::conditional_t<is_const, const g_t *, g_t *>;
351 using reference = std::conditional_t<is_const, g_t const &, g_t &>;
352 using block_gf_ref = std::conditional_t<is_const, this_t const &, this_t &>;
353
355 iterator_impl() = default;
356
358 iterator_impl(block_gf_ref _bgf, bool at_end = false) : bgf(&_bgf), n(at_end ? bgf->size() : 0) {}
359
361 iterator_impl(block_gf_ref _bgf, int _n) : bgf(&_bgf), n(_n) {}
362
364 operator iterator_impl<true>() const { return iterator_impl<true>(*bgf, n); }
365
367 reference operator*() {
368 if constexpr (Arity == 1) {
369 return (*bgf)[n];
370 } else {
371 return (*bgf)(n / bgf->size2(), n % bgf->size2());
372 }
373 }
374
376 reference operator*() const {
377 if constexpr (Arity == 1) {
378 return (*bgf)[n];
379 } else {
380 return (*bgf)(n / bgf->size2(), n % bgf->size2());
381 }
382 }
383
385 reference operator->() { return operator*(); }
386
389 ++n;
390 return *this;
391 }
392
395 auto it = *this;
396 ++n;
397 return it;
398 }
399
401 bool operator==(iterator_impl const &other) const { return ((bgf == other.bgf) && (n == other.n)); }
402
404 bool operator!=(iterator_impl const &other) const { return (!operator==(other)); }
405};
406
409
412
413//------------
414
416iterator begin() { return {*this, false}; }
417
419const_iterator begin() const { return {*this, false}; }
420
422iterator end() { return {*this, true}; }
423
425const_iterator end() const { return {*this, true}; }
426
428auto cbegin() { return const_view_type(*this).begin(); }
429
431auto cend() { return const_view_type(*this).end(); }
data_t & data()
Direct access to the blocks.
iterator_impl< false > iterator
Mutable block iterator type.
auto cend()
Get a const iterator past the last block.
friend void h5_read(h5::group fg, std::string const &subgroup_name, this_t &g)
Read a block Green's function from HDF5.
gf_struct_t gf_struct() const
Get the block structure.
int size2() const
Get the number of blocks along the second index (block2_gf only).
block_names_t const & block_names() const
Get the block names.
decltype(auto) operator[](int n) const
Access the n-th block of a one-index block Green's function (const overload).
std::vector< int > block_sizes() const
Get the matrix size of each block.
iterator_impl< true > const_iterator
Const block iterator type.
iterator end()
Get an iterator past the last block.
auto cbegin()
Get a const iterator to the first block.
friend void h5_write(h5::group fg, std::string const &subgroup_name, this_t const &g)
Write a block Green's function to HDF5.
static std::string hdf5_format()
Get the HDF5 format tag of a block Green's function.
const_view_type operator()() const
Make a const view of *this.
iterator begin()
Get an iterator to the first block.
int size1() const
Get the number of blocks along the first index (block2_gf only).
int size() const
Get the total number of blocks.
Forward iterator over the blocks of a block Green's function.
reference operator*()
Dereference to the current block.
iterator_impl(block_gf_ref _bgf, int _n)
Construct an iterator over a block Green's function positioned at block _n.
iterator_impl & operator++()
Pre-increment to the next block.
reference operator*() const
Dereference to the current block (const overload).
iterator_impl()=default
Construct a past-the-end (singular) iterator.
iterator_impl(block_gf_ref _bgf, bool at_end=false)
Construct an iterator over a block Green's function, optionally positioned at the end.
iterator_impl operator++(int)
Post-increment to the next block.
bool operator==(iterator_impl const &other) const
Equality comparison (same block Green's function and same position).
reference operator->()
Member access to the current block.
bool operator!=(iterator_impl const &other) const
Inequality comparison.
many_body_operator_generic< T > n(IndexTypes... indices)
Create a number operator .
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.
constexpr nda::clef::placeholder< 3 > w
Placeholder for the frequency .