/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2012-2014 by M. Ferrero, O. Parcollet * * TRIQS is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * TRIQS. If not, see . * ******************************************************************************/ #pragma once #include #include #include #include #include namespace triqs { namespace gfs { using dcomplex = std::complex; using arrays::array; using arrays::array_view; using arrays::matrix_view; using arrays::matrix; using arrays::make_shape; using arrays::range; using arrays::ellipsis; using arrays::mini_vector; class tail; // the value class class tail_view; // the view class class tail_const_view; // the const view class // ---------------------- implementation -------------------------------- enum rvc_enum { Regular, View, ConstView }; template struct __get_rvc; template using get_rvc = typename __get_rvc::type; template struct __get_rvc { using type = T; }; template struct __get_rvc { using type = typename T::view_type; }; template struct __get_rvc { using type = typename T::const_view_type; }; /// A common implementation class. template class tail_impl { public: TRIQS_MPI_IMPLEMENTED_VIA_BOOST; using view_type = tail_view; using const_view_type = tail_view; using regular_type = tail; using data_type = get_rvc>; using mask_type = get_rvc>; using mv_type = matrix_view; using const_mv_type = matrix_view; data_type & data() { return _data; } data_type const & data() const { return _data; } mask_type & mask() { return _mask; } mask_type const & mask() const { return _mask; } int order_min() const { return omin; } int order_max() const { return min_element(_mask); } size_t size() const { return _data.shape()[0]; } int smallest_nonzero() const { int om = omin; while ((om < order_max()) && (max_element(abs(_data(om - omin, ellipsis()))) < 1.e-10)) om++; return om; } using shape_type = mini_vector; shape_type shape() const { return shape_type(_data.shape()[1], _data.shape()[2]); } bool is_decreasing_at_infinity() const { return (smallest_nonzero() >= 1); } protected: int omin = -1; mask_type _mask; data_type _data; tail_impl() = default; tail_impl(int N1, int N2, int size_, int order_min) : omin(order_min), _mask(arrays::make_shape(N1, N2)), _data(make_shape(size_, N1, N2)) { _mask() = order_min + size_ - 1; _data() = 0; } tail_impl(data_type const &d, mask_type const &m, int omin_) : omin(omin_), _mask(m), _data(d) {} template tail_impl(tail_impl const &x) : omin(x.order_min()), _mask(x.mask()), _data(x.data()) {} friend class tail; friend class tail_view; friend class tail_const_view; friend tail compose(tail_const_view x, tail_const_view omega); // operator = for views void operator=(tail_const_view const &rhs); // implemented later public: mv_type operator()(int n) { if (n > order_max()) TRIQS_RUNTIME_ERROR << " n > Max Order. n= " << n << ", Max Order = " << order_max(); if (n < order_min()) TRIQS_RUNTIME_ERROR << " n < Min Order. n= " << n << ", Min Order = " << order_min(); return _data(n - omin, ellipsis()); } const_mv_type operator()(int n) const { if (n > order_max()) TRIQS_RUNTIME_ERROR << " n > Max Order. n= " << n << ", Max Order = " << order_max(); if (n < order_min()) { mv_type::regular_type r(shape()); r() = 0; return r; } return _data(n - omin, ellipsis()); } /// same as (), but if n is too large, then returns 0 instead of raising an exception const_mv_type get_or_zero(int n) const { if ((n > order_max()) || (n < order_min())) { mv_type::regular_type r(shape()); r() = 0; return r; } return _data(n - omin, ellipsis()); } friend std::string get_triqs_hdf5_data_scheme(tail_impl const &g) { return "TailGf"; } /// friend void h5_write(h5::group fg, std::string subgroup_name, tail_impl const &t) { auto gr = fg.create_group(subgroup_name); h5_write(gr, "omin", t.omin); h5_write(gr, "mask", t._mask); h5_write(gr, "data", t._data); } friend void h5_read(h5::group fg, std::string subgroup_name, tail_impl &t) { auto gr = fg.open_group(subgroup_name); h5_read(gr, "omin", t.omin); h5_read(gr, "mask", t._mask); h5_read(gr, "data", t._data); } // BOOST Serialization friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int version) { ar &TRIQS_MAKE_NVP("omin", omin); ar &TRIQS_MAKE_NVP("mask", _mask); ar &TRIQS_MAKE_NVP("data", _data); } }; // ----------------------------- class tail_const_view : public tail_impl { using B = tail_impl; // friend class tail; public: tail_const_view(B::data_type d, B::mask_type m, int order_min) : B(std::move(d), std::move(m), order_min) {} tail_const_view(tail_const_view const &) = default; tail_const_view(tail_const_view &&) = default; tail_const_view(tail_impl const &t) : B(t) {} tail_const_view(tail_impl const &t) : B(t) {} void rebind(tail_const_view const &X); }; // ----------------------------- class tail_view : public tail_impl { using B = tail_impl; // friend class tail; public: tail_view(B::data_type d, B::mask_type m, int order_min) : B(std::move(d), std::move(m), order_min) {} tail_view(tail_view const &) = default; tail_view(tail_view &&) = default; tail_view(tail_impl const &t) : B(t) {} void rebind(tail_view const &X); tail_view &operator=(tail_view const &x) { return B::operator=(tail_const_view(x)), *this; } template tail_view &operator=(tail_impl const &x) { return B::operator=(tail_const_view(x)), *this; } tail_view &operator=(dcomplex); }; // ----------------------------- // the regular class class tail : public tail_impl { using B = tail_impl; // friend class tail_view; public: using shape_type = mini_vector; tail() = default; tail(int N1, int N2, int size_ = 10, int order_min = -1) : B(N1, N2, size_, order_min) {} tail(shape_type const &sh, int size_ = 10, int order_min = -1) : B(sh[0], sh[1], size_, order_min) {} tail(mini_vector) : tail(1, 1) {} tail(B::data_type const &d, B::mask_type const &m, int order_min) : B(d, m, order_min) {} tail(tail const &g) : B(g) {} tail(tail_view const &g) : B(g) {} tail(tail_const_view const &g) : B(g) {} tail(tail &&) = default; tail &operator=(tail const &x) { return B::operator=(tail_const_view(x)), *this; } template tail &operator=(tail_impl const &x) { return B::operator=(tail_const_view(x)), *this; } }; // ---- impl. of = for base class ------------- template void tail_impl::operator=(tail_const_view const &rhs) { if (RVC == Regular) { omin = rhs.order_min(); } else { if ((_data.shape()[1] != rhs.data().shape()[1]) || (_data.shape()[2] != rhs.data().shape()[2]) || (omin != rhs.order_min())) TRIQS_RUNTIME_ERROR << "tails are incompatible"; } _mask = rhs.mask(); _data = rhs.data(); } // ---- Factories ------------- /// The simplest tail corresponding to omega tail tail_omega(int N1, int N2, int size_ = 10, int order_min = -1); /// The simplest tail corresponding to omega, constructed from a shape for convenience tail_view tail_omega(tail::shape_type const &sh, int size_, int order_min); /// The simplest tail corresponding to omega, built from the shape, size, ordermin of t tail_view tail_omega(tail_view t); // ---- IO ------------- std::ostream &operator<<(std::ostream &out, tail_const_view); // ---- ------------- // template void assign_singularity_from_function(tail_view t, RHS const &rhs) { t = rhs(tail_omega(t.shape(), t.size(), t.order_min())); } // ---- Evaluate and compose ------------- /// Evaluate the tail to sum_{n=order_min}^ordermax M_n/omega^n matrix evaluate(tail_const_view t, dcomplex const &omega); tail compose(tail_const_view x, tail_const_view t); // ---- Ops ------------- tail conj(tail_const_view const &t); tail transpose(tail_const_view const &t); /// Slice in orbital space tail_const_view slice_target(tail_const_view const &t, range R1, range R2); tail_view slice_target(tail_view t, range R1, range R2); inline tail_view slice_target(tail &t, range R1, range R2) { return slice_target(tail_view{t}, R1, R2);} inline tail_const_view slice_target(tail const &t, range R1, range R2) { return slice_target(tail_const_view{t}, R1, R2);} tail inverse(tail_const_view const &t); /// ------------------- Arithmetic operations ------------------------------ tail operator+(tail_const_view const &l, tail_const_view const &r); tail operator-(tail_const_view const &l, tail_const_view const &r); // +/- with scalar or matrix. template struct is_scalar_or_matrix : std::integral_constant>::value || utility::is_in_ZRC::value> {}; template std14::enable_if_t::value, tail> operator+(T const &a, tail_const_view const &t) { tail res(t); res(0) += a; return res; } template std14::enable_if_t::value, tail> operator+(tail_const_view const &t, T const &a) { return a + t; } template std14::enable_if_t::value, tail> operator-(T const &a, tail_const_view const &t) { return (-a) + t; } template std14::enable_if_t::value, tail> operator-(tail_const_view const &t, T const &a) { return (-a) + t; } tail operator*(tail_const_view const &l, tail_const_view const &r); tail operator*(matrix const &a, tail_const_view const &b); tail operator*(tail_const_view const &a, matrix const &b); template tail operator*(matrix_view const &a, tail_const_view const &b) { return matrix(a) * b; } template tail operator*(tail_const_view const &a, matrix_view const &b) { return a * matrix(b); } tail operator*(dcomplex a, tail_const_view const &r); inline tail operator*(tail_const_view const &r, dcomplex a) { return a * r; } inline tail operator/(tail_const_view const &a, tail_const_view const &b) { return a * inverse(b); } tail operator/(tail_const_view const &r, dcomplex a); inline tail operator/(dcomplex a, tail_view r) { return a * inverse(r); } // inplace operators #define DEFINE_OPERATOR(OP1, OP2) \ template void operator OP1(tail_view g, T &&x) { g = g OP2 x; } \ template void operator OP1(tail &g, T &&x) { g = g OP2 x; } DEFINE_OPERATOR(+=, +); DEFINE_OPERATOR(-=, -); DEFINE_OPERATOR(*=, *); DEFINE_OPERATOR(/=, / ); #undef DEFINE_OPERATOR } }