48 using utility::is_in_ZRC;
49 using utility::remove_rvalue_ref;
52 namespace gfs_expr_tools {
55 using no_mesh_t =
void *;
59 template <
typename S>
struct scalar_wrap {
61 using target_t = void;
67 template <
typename T> scalar_wrap(T &&x) : s(std::forward<T>(x)) {}
69 [[nodiscard]] no_mesh_t mesh()
const {
return {}; }
71 template <
typename... Keys> S operator[](Keys &&...)
const {
return s; }
73 template <
typename... Args>
inline S
operator()(Args &&...)
const {
return s; }
75 friend std::ostream &operator<<(std::ostream &sout, scalar_wrap
const &expr) {
return sout << expr.s; }
79 template <
typename Tag,
typename M> M combine_mesh(M
const &m, no_mesh_t) {
return m; }
82 template <
typename Tag,
typename M> M combine_mesh(no_mesh_t, M
const &m) {
return m; }
85 template <
typename Tag,
typename M> M combine_mesh(M
const &l, M
const &r) {
87 TRIQS_RUNTIME_ERROR <<
"Mesh mismatch: In Green Function Expression, the mesh of the 2 operands should be equal" << l <<
" vs " << r;
92 template <
typename Tag, nda::AnyOf<mesh::imtime, mesh::dlr_imtime> M> M combine_mesh(M
const &l, M
const &r) {
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;
99 int s = (int(l.statistic()) + int(r.statistic())) % 2;
101 if constexpr (std::is_same_v<M, mesh::imtime>)
102 return M{l.beta(), stat, l.size()};
104 return M{l.beta(), stat, l.w_max(), l.eps()};
107 TRIQS_RUNTIME_ERROR <<
"Mesh mismatch: In Green Function Expression, the mesh of the 2 operands should be equal" << l <<
" vs " << r;
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))...};
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);
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;
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(); }
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>;
144 template <
typename A,
typename B>
struct _or_ {
147 template <
typename A>
struct _or_<A, A> {
150 template <
typename A>
struct _or_<void, A> {
153 template <
typename A>
struct _or_<A, void> {
156 template <>
struct _or_<void, void> {
174 using L_t = std::remove_reference_t<L>;
177 using R_t = std::remove_reference_t<R>;
180 using mesh_t =
typename gfs_expr_tools::_or_<typename L_t::mesh_t, typename R_t::mesh_t>::type;
183 using target_t =
typename gfs_expr_tools::_or_<typename L_t::target_t, typename R_t::target_t>::type;
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");
205 template <
typename LL,
typename RR>
gf_expr(LL &&l_, RR &&r_) :
l(std::forward<LL>(l_)),
r(std::forward<RR>(r_)) {}
208 mutable std::optional<mesh_t> _mesh;
216 if (not _mesh) _mesh.emplace(gfs_expr_tools::combine_mesh<Tag>(
l.mesh(),
r.mesh()));
224 auto data_shape()
const {
return gfs_expr_tools::combine_shape()(
l,
r); }
233 template <
typename... Keys>
decltype(
auto)
operator[](Keys &&...keys)
const {
243 template <
typename... Args>
decltype(
auto)
operator()(Args &&...args)
const {
260 using L_t = std::remove_reference_t<L>;
287 decltype(
auto)
mesh()
const {
return l.mesh(); }
296 template <
typename... Keys>
auto operator[](Keys &&...keys)
const {
return -
l.operator[](std::forward<Keys>(keys)...); }
299 template <
typename... Args>
auto operator()(Args &&...args)
const {
return -
l(std::forward<Args>(args)...); }
309 template <
typename T>
struct is_gf_expr : std::false_type {};
312 template <
typename Tag,
typename L,
typename R>
struct is_gf_expr<
gf_expr<Tag, L, R>> : std::true_type {};
315 template <
typename L>
struct is_gf_expr<gf_unary_m_expr<L>> : std::true_type {};
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)}; \
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
341 template <
typename A1>
342 requires(GreenFunction<A1>::value)
343 auto operator-(A1 &&a1) {
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; }
355 DEFINE_OPERATOR(+=, +);
356 DEFINE_OPERATOR(-=, -);
357 DEFINE_OPERATOR(*=, *);
358 DEFINE_OPERATOR(/=, /);
360#undef DEFINE_OPERATOR
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))); });
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;
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;
386 template <Mesh M>
inline void operator+=(
gf_view<M> g, dcomplex a) { g += make_regular(a * nda::eye<double>(g.
target_shape()[0])); }
389 template <Mesh M>
inline void operator-=(
gf_view<M> g, dcomplex a) { g -= make_regular(a * nda::eye<double>(g.
target_shape()[0])); }
const_view_type operator()() const
Make a const view of *this.
A mutable, non-owning view of a Green's function.
std::array< long, Target::rank > target_shape() const
Get the shape of the target.
data_t & data() &
Get the data array view.
mesh_t const & mesh() const
Get the mesh of the Green's function.
The owning Green's function container.
Provides a mesh type for the discrete Lehmann representation in imaginary time.
TRIQS exception hierarchy and related macros.
Provides the Green's function class.
statistic_enum
Enum to specify particle statistics.
#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.
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.
gf< mesh_t, target_t > regular_t
Regular (owning) type the expression evaluates to.
auto const & mesh() const
Get the mesh of the expression (computed lazily and cached).
std::remove_reference_t< R > R_t
Decayed type of the right operand.
friend std::ostream & operator<<(std::ostream &sout, gf_expr const &expr)
Stream output of the expression.
std::remove_reference_t< L > L_t
Decayed type of the left operand.
auto data_shape() const
Get the data shape of the expression.
gf_expr(LL &&l_, RR &&r_)
Construct from the two operands.
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.
Lazy expression node representing the unary minus of a Green's function operand.
gf< mesh_t, target_t > regular_t
Regular (owning) type the expression evaluates to.
typename L_t::mesh_t mesh_t
Mesh type of the expression.
auto operator[](Keys &&...keys) const
Evaluate the negated expression via subscript.
decltype(auto) mesh() const
Get the mesh of the expression.
std::remove_reference_t< L > L_t
Decayed type of the operand.
typename L_t::target_t target_t
Target type of the expression.
friend std::ostream & operator<<(std::ostream &sout, gf_unary_m_expr const &expr)
Stream output of the expression.
auto data_shape() const
Get the data shape of the expression.
auto operator()(Args &&...1) const
Evaluate the negated expression via call.
gf_unary_m_expr(LL &&l_)
Construct from the operand.
Trait to detect whether a type is a Green's function expression node.
Callable wrapper that evaluates the operation identified by Tag on two operands.