TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
gf_expr.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//
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 "./gf.hpp"
28
30#include "../../mesh/imtime.hpp"
34
35#include <cmath>
36#include <optional>
37#include <ostream>
38#include <type_traits>
39#include <utility>
40
41namespace triqs::gfs {
42
47
48 using utility::is_in_ZRC;
49 using utility::remove_rvalue_ref;
50
51 // Implementation helpers for Green's function expression templates.
52 namespace gfs_expr_tools {
53
54 // Placeholder mesh type used for the scalar operands of an expression.
55 using no_mesh_t = void *;
56
57 // Wrapper that lets a scalar participate in a Green's function expression: it exposes a minimal
58 // Green's-function-like interface (fake mesh, operator[]/operator()) that always returns the wrapped scalar.
59 template <typename S> struct scalar_wrap {
60 using mesh_t = void;
61 using target_t = void;
62
63 // The wrapped scalar value.
64 S s;
65
66 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload): scalar_wrap only ever wraps scalars, not gf operands
67 template <typename T> scalar_wrap(T &&x) : s(std::forward<T>(x)) {}
68
69 [[nodiscard]] no_mesh_t mesh() const { return {}; } // Fake for combine_mesh
70
71 template <typename... Keys> S operator[](Keys &&...) const { return s; }
72
73 template <typename... Args> inline S operator()(Args &&...) const { return s; }
74
75 friend std::ostream &operator<<(std::ostream &sout, scalar_wrap const &expr) { return sout << expr.s; }
76 };
77
78 // Combine a mesh with a scalar operand: returns the mesh.
79 template <typename Tag, typename M> M combine_mesh(M const &m, no_mesh_t) { return m; }
80
81 // Combine a scalar operand with a mesh: returns the mesh.
82 template <typename Tag, typename M> M combine_mesh(no_mesh_t, M const &m) { return m; }
83
84 // Combine the meshes of the two operands of a binary expression (they must be equal; throws otherwise).
85 template <typename Tag, typename M> M combine_mesh(M const &l, M const &r) {
86 if (!(l == r))
87 TRIQS_RUNTIME_ERROR << "Mesh mismatch: In Green Function Expression, the mesh of the 2 operands should be equal" << l << " vs " << r;
88 return l;
89 }
90
91 // Combine the meshes for imaginary-time operands, accounting for the statistics of a product/quotient.
92 template <typename Tag, nda::AnyOf<mesh::imtime, mesh::dlr_imtime> M> M combine_mesh(M const &l, M const &r) {
93
94 if constexpr (std::is_same_v<Tag, utility::tags::multiplies> or std::is_same_v<Tag, utility::tags::divides>) {
95 bool eq = (std::abs(l.beta() - r.beta()) < 1.e-15) and (l.size() == r.size());
96 if (!eq) TRIQS_RUNTIME_ERROR << "Mesh mismatch: In Green Function Expression, the mesh of the 2 operands should be equal" << l << " vs " << r;
97
98 // compute the stat of the product, divide.
99 int s = (int(l.statistic()) + int(r.statistic())) % 2;
100 statistic_enum stat = (s == 0 ? Boson : Fermion);
101 if constexpr (std::is_same_v<M, mesh::imtime>)
102 return M{l.beta(), stat, l.size()};
103 else // dlr_imtime
104 return M{l.beta(), stat, l.w_max(), l.eps()};
105 } else {
106 if (!(l == r))
107 TRIQS_RUNTIME_ERROR << "Mesh mismatch: In Green Function Expression, the mesh of the 2 operands should be equal" << l << " vs " << r;
108 return l;
109 }
110 }
111
112 // special case of prod of mesh
113 namespace details {
114 // Component-wise combination of two product meshes (helper for the product-mesh combine_mesh overload).
115 template <typename Tag, typename... M, size_t... Is>
116 mesh::prod<M...> combine_mesh_impl_cp(std::index_sequence<Is...>, mesh::prod<M...> const &l, mesh::prod<M...> const &r) {
117 return {combine_mesh<Tag>(std::get<Is>(l), std::get<Is>(r))...};
118 }
119 } // namespace details
120
121 // Combine two product meshes component by component.
122 template <typename Tag, typename... M> mesh::prod<M...> combine_mesh(mesh::prod<M...> const &l, mesh::prod<M...> const &r) {
123 return details::combine_mesh_impl_cp<Tag>(std::index_sequence_for<M...>{}, l, r);
124 }
125
126 // Functor combining the data shapes of the two operands of a binary expression (shapes must match; a scalar
127 // operand takes the shape of the other operand).
128 struct combine_shape {
129 template <typename L, typename R> auto operator()(L &&l, R &&r) const {
130 auto ls = std::forward<L>(l).data_shape();
131 auto rs = std::forward<R>(r).data_shape();
132 if (!(ls == rs)) TRIQS_RUNTIME_ERROR << "Shape mismatch in Green Function Expression: " << ls << " vs " << rs;
133 return ls;
134 }
135 template <typename S, typename R> decltype(auto) operator()(scalar_wrap<S> const &, R &&r) const { return std::forward<R>(r).data_shape(); }
136 template <typename S, typename L> decltype(auto) operator()(L &&l, scalar_wrap<S> const &) const { return std::forward<L>(l).data_shape(); }
137 };
138
139 // Node type of an expression operand: a scalar_wrap for scalars, else the operand itself.
140 template <typename T>
141 using node_t = std::conditional_t<utility::is_in_ZRC<T>::value, scalar_wrap<std::decay_t<T>>, typename remove_rvalue_ref<T>::type>;
142
143 // Trait combining two (mesh or target) types into one, treating void as "unset" (mismatch yields void).
144 template <typename A, typename B> struct _or_ {
145 using type = void;
146 };
147 template <typename A> struct _or_<A, A> {
148 using type = A;
149 };
150 template <typename A> struct _or_<void, A> {
151 using type = A;
152 };
153 template <typename A> struct _or_<A, void> {
154 using type = A;
155 };
156 template <> struct _or_<void, void> {
157 using type = void;
158 };
159
160 } // namespace gfs_expr_tools
161
172 template <typename Tag, typename L, typename R> struct gf_expr : TRIQS_CONCEPT_TAG_NAME(GreenFunction) {
174 using L_t = std::remove_reference_t<L>;
175
177 using R_t = std::remove_reference_t<R>;
178
180 using mesh_t = typename gfs_expr_tools::_or_<typename L_t::mesh_t, typename R_t::mesh_t>::type;
181
183 using target_t = typename gfs_expr_tools::_or_<typename L_t::target_t, typename R_t::target_t>::type;
184
187
188 static_assert(!std::is_same_v<mesh_t, void>, "Cannot combine two gf expressions with different variables");
189 static_assert(!std::is_same_v<target_t, void>, "Cannot combine two gf expressions with different target");
190
192 L l;
193
195 R r;
196
205 template <typename LL, typename RR> gf_expr(LL &&l_, RR &&r_) : l(std::forward<LL>(l_)), r(std::forward<RR>(r_)) {}
206
207 private:
208 mutable std::optional<mesh_t> _mesh;
209
210 public:
215 auto const &mesh() const {
216 if (not _mesh) _mesh.emplace(gfs_expr_tools::combine_mesh<Tag>(l.mesh(), r.mesh()));
217 return *_mesh;
218 }
219
224 auto data_shape() const { return gfs_expr_tools::combine_shape()(l, r); }
225
233 template <typename... Keys> decltype(auto) operator[](Keys &&...keys) const {
234 return utility::operation<Tag>()(l.operator[](std::forward<Keys>(keys)...), r.operator[](std::forward<Keys>(keys)...)); // Clang Fix
235 }
236
243 template <typename... Args> decltype(auto) operator()(Args &&...args) const {
244 return utility::operation<Tag>()(l(std::forward<Args>(args)...), r(std::forward<Args>(args)...));
245 }
246
248 friend std::ostream &operator<<(std::ostream &sout, gf_expr const &expr) {
249 return sout << "(" << expr.l << " " << utility::operation<Tag>::name << " " << expr.r << ")";
250 }
251 };
252
253 // -------------------------------------------------------------------
258 template <typename L> struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(GreenFunction) {
260 using L_t = std::remove_reference_t<L>;
261
263 using mesh_t = typename L_t::mesh_t;
264
266 using target_t = typename L_t::target_t;
267
270
272 L l;
273
280 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload): only constructs from an operand, not a copy/move source
281 template <typename LL> gf_unary_m_expr(LL &&l_) : l(std::forward<LL>(l_)) {}
282
287 decltype(auto) mesh() const { return l.mesh(); }
288
293 auto data_shape() const { return l.data_shape(); }
294
296 template <typename... Keys> auto operator[](Keys &&...keys) const { return -l.operator[](std::forward<Keys>(keys)...); } // Clang Fix
297
299 template <typename... Args> auto operator()(Args &&...args) const { return -l(std::forward<Args>(args)...); }
300
302 friend std::ostream &operator<<(std::ostream &sout, gf_unary_m_expr const &expr) { return sout << '-' << expr.l; }
303 };
304
309 template <typename T> struct is_gf_expr : std::false_type {};
310
311 // Specialization of triqs::gfs::is_gf_expr for triqs::gfs::gf_expr.
312 template <typename Tag, typename L, typename R> struct is_gf_expr<gf_expr<Tag, L, R>> : std::true_type {};
313
314 // Specialization of triqs::gfs::is_gf_expr for triqs::gfs::gf_unary_m_expr.
315 template <typename L> struct is_gf_expr<gf_unary_m_expr<L>> : std::true_type {};
316
317// -------------------------------------------------------------------
318// Now we can define all the C++ operators ...
319// NOLINTBEGIN(bugprone-macro-parentheses): OP is an operator token and cannot be parenthesized
320// Define a binary arithmetic operator returning a lazy triqs::gfs::gf_expr node.
321#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \
322 template <typename A1, typename A2> \
323 requires(TRAIT1<A1>::value and TRAIT2<A2>::value) \
324 gf_expr<utility::tags::TAG, gfs_expr_tools::node_t<A1>, gfs_expr_tools::node_t<A2>> operator OP(A1 &&a1, A2 &&a2) { \
325 return {std::forward<A1>(a1), std::forward<A2>(a2)}; \
326 }
327 // NOLINTEND(bugprone-macro-parentheses)
328
329 DEFINE_OPERATOR(plus, +, GreenFunction, GreenFunction);
330 DEFINE_OPERATOR(minus, -, GreenFunction, GreenFunction);
331 DEFINE_OPERATOR(multiplies, *, GreenFunction, GreenFunction);
332 DEFINE_OPERATOR(multiplies, *, is_in_ZRC, GreenFunction);
333 DEFINE_OPERATOR(multiplies, *, GreenFunction, is_in_ZRC);
334 DEFINE_OPERATOR(divides, /, GreenFunction, GreenFunction);
335 DEFINE_OPERATOR(divides, /, is_in_ZRC, GreenFunction);
336 DEFINE_OPERATOR(divides, /, GreenFunction, is_in_ZRC);
337#undef DEFINE_OPERATOR
338
339 // the unary is special
341 template <typename A1>
342 requires(GreenFunction<A1>::value)
343 auto operator-(A1 &&a1) {
344 return gf_unary_m_expr<gfs_expr_tools::node_t<A1>>{std::forward<A1>(a1)};
345 }
346
347 // Now the inplace operator. Because of expression template, there are useless for speed
348 // we implement them trivially.
349
350// Define in-place compound-assignment operators for Green's functions in terms of the binary operators.
351#define DEFINE_OPERATOR(OP1, OP2) \
352 template <typename Mesh, typename Target, typename T> void operator OP1(gf_view<Mesh, Target> g, T const &x) { g = g OP2 x; } \
353 template <typename Mesh, typename Target, typename T> void operator OP1(gf<Mesh, Target> &g, T const &x) { g = g OP2 x; }
354
355 DEFINE_OPERATOR(+=, +);
356 DEFINE_OPERATOR(-=, -);
357 DEFINE_OPERATOR(*=, *);
358 DEFINE_OPERATOR(/=, /);
359
360#undef DEFINE_OPERATOR
361
362 // In-place matrix inversion
363
364 // Invert, in place, the target matrix (last two dimensions) at each mesh point of a Green's function data array.
365 template <typename A> void _gf_invert_data_in_place(A &a) {
366 auto mesh_lengths = nda::stdutil::mpop<2>(a.indexmap().lengths());
367 nda::for_each(mesh_lengths, [&a](auto &&...i) { nda::linalg::inv_in_place(make_matrix_view(a(i..., range::all, range::all))); });
368 }
369
370 // Python specific operator and definitions
371
372 // definitions of operators for scalar / matrix with all triqs Gf mesh types
373 // loop over mesh and apply operatations
374
376 template <Mesh M, nda::MemoryMatrix Mat> inline void operator+=(gf_view<M> g, Mat const &mat) {
377 for (auto mp : g.mesh()) g[mp] += mat;
378 }
379
381 template <Mesh M, nda::MemoryMatrix Mat> inline void operator-=(gf_view<M> g, Mat const &mat) {
382 for (auto mp : g.mesh()) g[mp] -= mat;
383 }
384
386 template <Mesh M> inline void operator+=(gf_view<M> g, dcomplex a) { g += make_regular(a * nda::eye<double>(g.target_shape()[0])); }
387
389 template <Mesh M> inline void operator-=(gf_view<M> g, dcomplex a) { g -= make_regular(a * nda::eye<double>(g.target_shape()[0])); }
390
392 template <Mesh M> inline void operator+=(gf_view<M, scalar_valued> g, dcomplex a) { g.data() += a; }
393
395 template <Mesh M> inline void operator-=(gf_view<M, scalar_valued> g, dcomplex a) { g.data() -= a; }
396
398
399} // namespace triqs::gfs
const_view_type operator()() const
Make a const view of *this.
A mutable, non-owning view of a Green's function.
Definition gf_view.hpp:48
std::array< long, Target::rank > target_shape() const
Get the shape of the target.
Definition gf_view.hpp:165
data_t & data() &
Get the data array view.
Definition gf_view.hpp:131
mesh_t const & mesh() const
Get the mesh of the Green's function.
Definition gf_view.hpp:125
The owning Green's function container.
Definition gf.hpp:194
Macros that define a legacy (pre C++20) concept-tag trait pair.
Provides a mesh type for the discrete Lehmann representation in imaginary time.
TRIQS exception hierarchy and related macros.
Building blocks for expression-template and other type traits.
Provides the Green's function class.
statistic_enum
Enum to specify particle statistics.
Definition utils.hpp:163
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.
#define TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept)
Helper macro that produces the name of the tag for TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT.
Provides a mesh type on the imaginary time axis.
Lazy expression node representing a binary operation between two Green's function operands.
Definition gf_expr.hpp:172
typename gfs_expr_tools::_or_< typename L_t::mesh_t, typename R_t::mesh_t >::type mesh_t
Mesh type of the expression, deduced from the two operands.
Definition gf_expr.hpp:180
gf< mesh_t, target_t > regular_t
Regular (owning) type the expression evaluates to.
Definition gf_expr.hpp:186
auto const & mesh() const
Get the mesh of the expression (computed lazily and cached).
Definition gf_expr.hpp:215
std::remove_reference_t< R > R_t
Decayed type of the right operand.
Definition gf_expr.hpp:177
friend std::ostream & operator<<(std::ostream &sout, gf_expr const &expr)
Stream output of the expression.
Definition gf_expr.hpp:248
std::remove_reference_t< L > L_t
Decayed type of the left operand.
Definition gf_expr.hpp:174
L l
Left operand.
Definition gf_expr.hpp:192
R r
Right operand.
Definition gf_expr.hpp:195
auto data_shape() const
Get the data shape of the expression.
Definition gf_expr.hpp:224
gf_expr(LL &&l_, RR &&r_)
Construct from the two operands.
Definition gf_expr.hpp:205
typename gfs_expr_tools::_or_< typename L_t::target_t, typename R_t::target_t >::type target_t
Target type of the expression, deduced from the two operands.
Definition gf_expr.hpp:183
Lazy expression node representing the unary minus of a Green's function operand.
Definition gf_expr.hpp:258
gf< mesh_t, target_t > regular_t
Regular (owning) type the expression evaluates to.
Definition gf_expr.hpp:269
typename L_t::mesh_t mesh_t
Mesh type of the expression.
Definition gf_expr.hpp:263
auto operator[](Keys &&...keys) const
Evaluate the negated expression via subscript.
Definition gf_expr.hpp:296
decltype(auto) mesh() const
Get the mesh of the expression.
Definition gf_expr.hpp:287
std::remove_reference_t< L > L_t
Decayed type of the operand.
Definition gf_expr.hpp:260
typename L_t::target_t target_t
Target type of the expression.
Definition gf_expr.hpp:266
friend std::ostream & operator<<(std::ostream &sout, gf_unary_m_expr const &expr)
Stream output of the expression.
Definition gf_expr.hpp:302
auto data_shape() const
Get the data shape of the expression.
Definition gf_expr.hpp:293
auto operator()(Args &&...1) const
Evaluate the negated expression via call.
Definition gf_expr.hpp:299
gf_unary_m_expr(LL &&l_)
Construct from the operand.
Definition gf_expr.hpp:281
Trait to detect whether a type is a Green's function expression node.
Definition gf_expr.hpp:309
Callable wrapper that evaluates the operation identified by Tag on two operands.