TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
_gf_view_common.hpp
Go to the documentation of this file.
1// Copyright (c) 2019-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 gf / gf_view / gf_const_view classes, so it
24// cannot carry its own #include directives. The including files must provide, in addition to the 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_WITH_MESSAGE
28// - <numeric> (std::accumulate), <ostream> (std::ostream), <string> (std::string), <tuple> (std::tuple, std::apply)
29
30// common to many classes
31
32// ------------- All the call operators arguments -----------------------------
33
45#if __cpp_explicit_this_parameter >= 202110L
46template <typename Self, typename... Args> decltype(auto) operator()(this Self &&self, Args &&...args) {
47#else
48template <typename Self, typename... Args> static decltype(auto) call_impl(Self &&self, Args &&...args) {
49#endif
50 if constexpr (sizeof...(Args) == 0) {
51 if constexpr (std::is_const_v<std::remove_reference_t<Self>>)
52 return const_view_type{std::forward<Self>(self)};
53 else
54 return view_type{std::forward<Self>(self)};
55 } else {
56 static_assert((sizeof...(Args) == n_variables<mesh_t>), "Incorrect number of arguments");
57 if constexpr ((... or clef::is_any_lazy<Args>)) // any argument is lazy ?
58 return clef::make_expr_call(std::forward<Self>(self), std::forward<Args>(args)...);
59 else
60 return gf_evaluator<mesh_t>{}(std::forward<Self>(self), std::forward<Args>(args)...);
61 }
62}
63#if __cpp_explicit_this_parameter < 202110L
65template <typename... Args> decltype(auto) operator()(Args &&...args) const & { return call_impl(*this, std::forward<Args>(args)...); }
67template <typename... Args> decltype(auto) operator()(Args &&...args) & { return call_impl(*this, std::forward<Args>(args)...); }
69template <typename... Args> decltype(auto) operator()(Args &&...args) && { return call_impl(std::move(*this), std::forward<Args>(args)...); }
70#endif
71
72// ------------- [] operator -----------------------------
73
75#ifdef NDA_ENFORCE_BOUNDCHECK
76static constexpr bool has_no_boundcheck = false;
77#else
78static constexpr bool has_no_boundcheck = true;
79#endif
80
91template <typename... T>
92decltype(auto) operator[](std::tuple<T...> const &tu) const noexcept(has_no_boundcheck)
93 requires(sizeof...(T) == arity)
94{
95 return std::apply([this](auto &...x) -> decltype(auto) { return this->operator[](x...); }, tu);
96}
97
99template <typename... T>
100decltype(auto) operator[](std::tuple<T...> const &tu) noexcept(has_no_boundcheck)
101 requires(sizeof...(T) == arity)
102{
103 return std::apply([this](auto &...x) -> decltype(auto) { return this->operator[](x...); }, tu);
104}
105
106private:
107// local helper functions for the _subscript_impl below
108template <Mesh MT, typename X> static auto call_to_data_index(MT const &m, X const &x) {
109 if constexpr (std::is_same_v<X, all_t>)
110 return all_t{};
111 else if constexpr (std::is_same_v<X, typename MT::mesh_point_t>) {
112 static_assert(std::is_same_v<X, typename MT::mesh_point_t>, "Incompatible mesh_point type passed to a gf via [] operator.");
113 EXPECTS_WITH_MESSAGE(m.mesh_hash() == x.mesh_hash(),
114 "Passing to a gf a mesh point of incompatible mesh (but correct type), e.g. different beta, or other parameter.");
115 return x.data_index();
116 } else
117 return m.to_data_index(x);
118}
119
120// ------------------------------------------
121// General implementation for any set of arguments.
122// https://godbolt.org/z/sbqYv3oeE
123template <typename Self, typename... Arg>
124static decltype(auto) _subscript_impl(Self &&self, Arg &&...arg)
125 requires(sizeof...(Arg) == arity)
126{
127 if constexpr ((clef::is_any_lazy<Arg> or ... or false))
128 return clef::make_expr_subscript(std::forward<Self>(self), std::forward<Arg>(arg)...);
129 else {
130 // Count the number of all_t
131 static constexpr auto mesh_filter = std::array<int, sizeof...(Arg)>{std::is_same_v<range::all_t, std::decay_t<Arg>>...};
132 static constexpr auto n_all = std::accumulate(begin(mesh_filter), end(mesh_filter), 0);
133
134 decltype(auto) new_data = [&self,
135 &arg...]<size_t... Is>(std::index_sequence<Is...>) -> decltype(auto) { // the trailing ->decltype(auto) is crucial
136 return data_t::template call<(target_t::is_matrix and n_all == 0 ? 'M' : 'A'), false>(
137 std::forward<Self>(self)._data, this_t::call_to_data_index(get_mesh<Is>(self), std::forward<Arg>(arg))..., ellipsis{});
138 }(std::make_index_sequence<arity>{}); //keep arity here. we could authorize to pass additional integers for direct access here ??
139
140 if constexpr (n_all == 0)
141 return new_data;
142 else {
143 // mesh is a tuple of meshes
144 auto new_mesh = detail::filter_mesh<detail::compute_position<n_all>(mesh_filter)>(self.mesh());
145 using self_t = std::remove_reference_t<Self>;
146 if constexpr (self_t::is_const or std::is_const_v<self_t>)
147 return gf_const_view<decltype(new_mesh), typename self_t::target_t>{std::move(new_mesh), new_data};
148 else
149 return gf_view<decltype(new_mesh), typename self_t::target_t>{std::move(new_mesh), new_data};
150 }
151 }
152}
153
154public:
155// ------------------------------------------
156
168template <typename... Arg>
169decltype(auto) operator[](Arg &&...arg) const & noexcept(has_no_boundcheck)
170 requires(sizeof...(Arg) == arity)
171{
172 return _subscript_impl(*this, std::forward<Arg>(arg)...);
173}
174
176template <typename... Arg>
177decltype(auto) operator[](Arg &&...arg) & noexcept(has_no_boundcheck)
178 requires(sizeof...(Arg) == arity)
179{
180 return _subscript_impl(*this, std::forward<Arg>(arg)...);
181}
182
184template <typename... Arg>
185decltype(auto) operator[](Arg &&...arg) && noexcept(has_no_boundcheck)
186 requires(sizeof...(Arg) == arity)
187{
188 return _subscript_impl(std::move(*this), std::forward<Arg>(arg)...);
189}
190
197decltype(auto) operator[](typename mesh_t::index_t const &index) noexcept(has_no_boundcheck)
198 requires(arity == 1)
199{
200 return this_t::operator[]<typename mesh_t::index_t const &>(index);
201}
202
203//----------------------------- HDF5 -----------------------------
204
209[[nodiscard]] static std::string hdf5_format() { return "Gf"; }
210
211// Grants the HDF5 read/write traits class access to the private members.
212friend struct gf_h5_rw<M, Target>;
213
221friend void h5_write(h5::group fg, std::string const &subgroup_name, this_t const &g) {
222 auto gr = fg.create_group(subgroup_name);
223 write_hdf5_format(gr, g);
224 gf_h5_rw<M, Target>::write(gr, g);
225}
226
236friend void h5_read(h5::group fg, std::string const &subgroup_name, this_t &g) {
237 auto gr = fg.open_group(subgroup_name);
238 auto tag_file = read_hdf5_format(gr);
239 if (!(tag_file[0] == 'G' and tag_file[1] == 'f'))
240 TRIQS_RUNTIME_ERROR << "h5_read : For a Green function, the type tag should be Gf (or Gfxxxx for old archive) "
241 << " while I found " << tag_file;
242 gf_h5_rw<M, Target>::read(gr, g);
243}
244
245//----------------------------- print -----------------------------
246
252friend std::ostream &operator<<(std::ostream &out, this_t const &) { return out << "this_t"; }
iterator end()
Get an iterator past the last block.
iterator begin()
Get an iterator to the first block.
friend std::ostream & operator<<(std::ostream &out, this_t const &)
Write a Green's function to an output stream.
friend void h5_read(h5::group fg, std::string const &subgroup_name, this_t &g)
Read a Green's function from HDF5.
static constexpr bool has_no_boundcheck
Whether bound checking of the data array is disabled (controlled by NDA_ENFORCE_BOUNDCHECK).
friend void h5_write(h5::group fg, std::string const &subgroup_name, this_t const &g)
Write a Green's function to HDF5.
static std::string hdf5_format()
Get the HDF5 format tag of a Green's function.
static decltype(auto) call_impl(Self &&self, Args &&...1)
Evaluate the Green's function at the given arguments.
decltype(auto) operator[](std::tuple< T... > const &tu) const noexcept(has_no_boundcheck)
Access the Green's function at a mesh point/index passed as a tuple (const overload).
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.