TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
expr.hpp
Go to the documentation of this file.
1// Copyright (c) 2016-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2016-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2023 Simons Foundation
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You may obtain a copy of the License at
16// https://www.gnu.org/licenses/gpl-3.0.txt
17//
18// Authors: Michel Ferrero, Olivier Parcollet, Nils Wentzell
19
24
25#pragma once
26
27#include "./block_gf_view.hpp"
28
31
32#include <algorithm>
33#include <ostream>
34#include <type_traits>
35#include <utility>
36
37namespace triqs::gfs {
38
43
44 using utility::is_in_ZRC;
46
47 // Implementation helpers for block Green's function expression templates.
48 namespace details_bgfs_expr {
49
50 // Wrapper that lets a scalar participate in a block expression: it exposes a minimal block-Green's-function-like
51 // interface (operator[]/operator()) that always returns the wrapped scalar.
52 template <typename S> struct scalar_wrap {
53 using mesh_t = void;
54 using target_t = void;
55
56 // The wrapped scalar value.
57 S s;
58
59 int size() const { return -1; }
60 int size1() const { return -1; }
61 int size2() const { return -1; }
62
63 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload): scalar_wrap only ever wraps scalars, not block-gf operands
64 template <typename T> scalar_wrap(T &&x) : s(std::forward<T>(x)) {}
65
66 template <typename... Keys> S operator[](Keys &&...) const { return s; }
67
68 template <typename... Args> inline S operator()(Args &&...) const { return s; }
69
70 friend std::ostream &operator<<(std::ostream &sout, scalar_wrap const &expr) { return sout << expr.s; }
71 };
72
73 // Node type of an expression operand: a scalar_wrap for scalars, else the operand itself.
74 template <typename T> using node_t = std::conditional_t<utility::is_in_ZRC<T>::value, scalar_wrap<T>, remove_rvalue_ref_t<T>>;
75
76 // Trait combining two (mesh or target) types into one, treating void as "unset" (mismatch yields void).
77 template <typename A, typename B> struct same_or_void {
78 using type = void;
79 };
80 template <typename A> struct same_or_void<A, A> {
81 using type = A;
82 };
83 template <typename A> struct same_or_void<void, A> {
84 using type = A;
85 };
86 template <typename A> struct same_or_void<A, void> {
87 using type = A;
88 };
89 template <> struct same_or_void<void, void> {
90 using type = void;
91 };
92
93 } // namespace details_bgfs_expr
94
106 template <typename Tag, typename L, typename R> struct bgf_expr : TRIQS_CONCEPT_TAG_NAME(BlockGreenFunction) {
107
109 using L_t = std::decay_t<L>;
110
112 using R_t = std::decay_t<R>;
113
115 using mesh_t = typename details_bgfs_expr::same_or_void<typename L_t::mesh_t, typename R_t::mesh_t>::type;
116
118 using target_t = typename details_bgfs_expr::same_or_void<typename L_t::target_t, typename R_t::target_t>::type;
119
120 static_assert(!std::is_same<mesh_t, void>::value, "Cannot combine two gf expressions with different variables");
121 static_assert(!std::is_same<target_t, void>::value, "Cannot combine two gf expressions with different target");
122 static_assert(((arity_of<L_t> == -1) xor (arity_of<R_t> == -1)) or (arity_of<R_t> == arity_of<L_t> and arity_of<R_t> > 0));
123
125 static constexpr int arity = std::max(arity_of<L_t>, arity_of<R_t>);
126
128 L l;
129
131 R r;
132
141 template <typename LL, typename RR> bgf_expr(LL &&l_, RR &&r_) : l(std::forward<LL>(l_)), r(std::forward<RR>(r_)) {}
142
147 auto size() const { return std::max(l.size(), r.size()); }
148
153 auto size1() const { return std::max(l.size1(), r.size1()); }
154
159 auto size2() const { return std::max(l.size2(), r.size2()); }
160
165 auto block_names() const {
166 if constexpr (std::is_void_v<typename L_t::mesh_t>)
167 return r.block_names();
168 else
169 return l.block_names();
170 }
171
179 template <typename... Keys> decltype(auto) operator[](Keys &&...keys) const {
180 return utility::operation<Tag>()(l.operator[](std::forward<Keys>(keys)...), r.operator[](std::forward<Keys>(keys)...)); // Clang fix
181 }
182
189 template <typename... Args> decltype(auto) operator()(Args &&...args) const {
190 return utility::operation<Tag>()(l(std::forward<Args>(args)...), r(std::forward<Args>(args)...));
191 }
192
194 friend std::ostream &operator<<(std::ostream &sout, bgf_expr const &expr) {
195 return sout << "(" << expr.l << " " << utility::operation<Tag>::name << " " << expr.r << ")";
196 }
197 };
198
199 // -------------------------------------------------------------------
204 template <typename L> struct bgf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(BlockGreenFunction) {
206 using L_t = std::decay_t<L>;
207
209 using mesh_t = typename L_t::mesh_t;
210
212 using target_t = typename L_t::target_t;
213
215 L l;
216
223 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload): only constructs from an operand, not a copy/move source
224 template <typename LL> bgf_unary_m_expr(LL &&l_) : l(std::forward<LL>(l_)) {}
225
230 auto size() const { return l.size(); }
231
236 auto block_names() const { return l.block_names(); }
237
239 template <typename... Keys> auto operator[](Keys &&...keys) const { return -l.operator[](std::forward<Keys>(keys)...); } // Clang fix
240
242 template <typename... Args> auto operator()(Args &&...args) const { return -l(std::forward<Args>(args)...); }
243
245 friend std::ostream &operator<<(std::ostream &sout, bgf_unary_m_expr const &expr) { return sout << '-' << expr.l; }
246 };
247
248// -------------------------------------------------------------------
249// Now we can define all the C++ operators ...
250// NOLINTBEGIN(bugprone-macro-parentheses): OP is an operator token and cannot be parenthesized
251// Define a binary arithmetic operator returning a lazy triqs::gfs::bgf_expr node.
252#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \
253 template <typename A1, typename A2> \
254 std::enable_if_t<TRAIT1<A1>::value && TRAIT2<A2>::value, \
255 bgf_expr<utility::tags::TAG, details_bgfs_expr::node_t<A1>, details_bgfs_expr::node_t<A2>>> \
256 operator OP(A1 &&a1, A2 &&a2) { \
257 return {std::forward<A1>(a1), std::forward<A2>(a2)}; \
258 }
259 // NOLINTEND(bugprone-macro-parentheses)
260
261 DEFINE_OPERATOR(plus, +, BlockGreenFunction, BlockGreenFunction);
262 DEFINE_OPERATOR(minus, -, BlockGreenFunction, BlockGreenFunction);
263 DEFINE_OPERATOR(multiplies, *, BlockGreenFunction, BlockGreenFunction);
264 DEFINE_OPERATOR(multiplies, *, is_in_ZRC, BlockGreenFunction);
265 DEFINE_OPERATOR(multiplies, *, BlockGreenFunction, is_in_ZRC);
266 DEFINE_OPERATOR(divides, /, BlockGreenFunction, BlockGreenFunction);
267 DEFINE_OPERATOR(divides, /, is_in_ZRC, BlockGreenFunction);
268 DEFINE_OPERATOR(divides, /, BlockGreenFunction, is_in_ZRC);
269#undef DEFINE_OPERATOR
270
271 // the unary is special
273 template <typename A1>
274 requires(BlockGreenFunction<A1>::value)
275 auto operator-(A1 &&a1) {
276 return bgf_unary_m_expr<details_bgfs_expr::node_t<A1>>{std::forward<A1>(a1)};
277 }
278
279 // Now the inplace operator. Because of expression template, there are useless for speed
280 // we implement them trivially.
281
282// Define in-place compound-assignment operators for block Green's functions in terms of the binary operators.
283#define DEFINE_OPERATOR(OP1, OP2) \
284 template <typename Mesh, typename Target, typename Layout, int Arity, typename T> \
285 void operator OP1(block_gf_view<Mesh, Target, Layout, Arity> g, T const &x) { \
286 g = g OP2 x; \
287 } \
288 template <typename Mesh, typename Target, typename Layout, int Arity, typename T> \
289 void operator OP1(block_gf<Mesh, Target, Layout, Arity> &g, T const &x) { \
290 g = g OP2 x; \
291 }
292
293 DEFINE_OPERATOR(+=, +);
294 DEFINE_OPERATOR(-=, -);
295 DEFINE_OPERATOR(*=, *);
296 DEFINE_OPERATOR(/=, /);
297
298#undef DEFINE_OPERATOR
299
301
302} // namespace triqs::gfs
int size2() const
Get the number of blocks along the second index (block2_gf only).
const_view_type operator()() const
Make a const view of *this.
int size1() const
Get the number of blocks along the first index (block2_gf only).
int size() const
Get the total number of blocks.
Provides a non-owning view of a block Green's function.
Macros that define a legacy (pre C++20) concept-tag trait pair.
Building blocks for expression-template and other type traits.
constexpr int arity_of
Block arity of a type: T::arity if present, -1 otherwise.
Definition block_gf.hpp:138
#define TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept)
Helper macro that produces the name of the tag for TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT.
typename remove_rvalue_ref< T >::type remove_rvalue_ref_t
Alias for the nested type in remove_rvalue_ref.
std::decay_t< R > R_t
Decayed type of the right operand.
Definition expr.hpp:112
R r
Right operand.
Definition expr.hpp:131
typename details_bgfs_expr::same_or_void< typename L_t::target_t, typename R_t::target_t >::type target_t
Target type of the expression, deduced from the two operands.
Definition expr.hpp:118
auto size1() const
Get the number of blocks along the first dimension (for a block2 expression).
Definition expr.hpp:153
auto block_names() const
Get the block names of the expression.
Definition expr.hpp:165
typename details_bgfs_expr::same_or_void< typename L_t::mesh_t, typename R_t::mesh_t >::type mesh_t
Mesh type of the expression, deduced from the two operands.
Definition expr.hpp:115
bgf_expr(LL &&l_, RR &&r_)
Construct from the two operands.
Definition expr.hpp:141
friend std::ostream & operator<<(std::ostream &sout, bgf_expr const &expr)
Stream output of the expression.
Definition expr.hpp:194
std::decay_t< L > L_t
Decayed type of the left operand.
Definition expr.hpp:109
static constexpr int arity
Block arity of the expression (1 for triqs::gfs::block_gf, 2 for triqs::gfs::block2_gf).
Definition expr.hpp:125
L l
Left operand.
Definition expr.hpp:128
auto size() const
Get the number of blocks of the expression.
Definition expr.hpp:147
auto size2() const
Get the number of blocks along the second dimension (for a block2 expression).
Definition expr.hpp:159
Lazy expression node representing the unary minus of a block Green's function operand.
Definition expr.hpp:204
auto operator[](Keys &&...keys) const
Evaluate the negated expression via subscript.
Definition expr.hpp:239
bgf_unary_m_expr(LL &&l_)
Construct from the operand.
Definition expr.hpp:224
auto size() const
Get the number of blocks of the expression.
Definition expr.hpp:230
auto operator()(Args &&...1) const
Evaluate the negated expression via call.
Definition expr.hpp:242
friend std::ostream & operator<<(std::ostream &sout, bgf_unary_m_expr const &expr)
Stream output of the expression.
Definition expr.hpp:245
std::decay_t< L > L_t
Decayed type of the operand.
Definition expr.hpp:206
auto block_names() const
Get the block names of the expression.
Definition expr.hpp:236
typename L_t::mesh_t mesh_t
Mesh type of the expression.
Definition expr.hpp:209
typename L_t::target_t target_t
Target type of the expression.
Definition expr.hpp:212
Trait identifying types that lie in .
Callable wrapper that evaluates the operation identified by Tag on two operands.