/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2012 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 . * ******************************************************************************/ #ifndef TRIQS_GF_LOCAL_TAIL_H #define TRIQS_GF_LOCAL_TAIL_H #include #include #include #include namespace triqs { namespace gfs { namespace local { namespace details { static constexpr double small = 1.e-10; } using arrays::matrix_view; using arrays::matrix; namespace tqa= triqs::arrays; //namespace tql= triqs::clef; namespace mpl= boost::mpl; typedef std::complex dcomplex; class tail; // the value class class tail_view; // the view class template struct LocalTail : mpl::false_{}; // a boolean trait to identify the objects modelling the concept LocalTail template<> struct LocalTail : mpl::true_{}; template<> struct LocalTail: mpl::true_{}; // a trait to find the scalar of the algebra i.e. the true scalar and the matrix ... template struct is_scalar_or_element : mpl::or_< tqa::ImmutableMatrix, utility::is_in_ZRC > {}; // ---------------------- implementation -------------------------------- /// A common implementation class. Idiom: ValueView template class tail_impl { public: typedef tail_view view_type; typedef tail regular_type; typedef arrays::array data_regular_type; typedef arrays::array_view data_view_type; typedef typename mpl::if_c::type data_type; typedef arrays::array mask_regular_type; typedef arrays::array_view mask_view_type; typedef typename mpl::if_c::type mask_type; typedef arrays::matrix_view mv_type; typedef arrays::matrix_view const_mv_type; data_view_type data() { return _data;} const data_view_type data() const { return _data;} mask_view_type mask_view() { return mask;} const mask_view_type mask_view() const { return mask;} long order_min() const {return omin;} long order_max() const {return min_element(mask);} size_t size() const {return _data.shape()[0];} long smallest_nonzero() const { long om = omin; while ((om < this->order_max()) && (max_element(abs(_data(om-omin,tqa::range(),tqa::range()))) < details::small)) om++; return om; } typedef tqa::mini_vector shape_type; shape_type shape() const { return shape_type(_data.shape()[1], _data.shape()[2]);} bool is_decreasing_at_infinity() const { return (smallest_nonzero() >=1);} protected: long omin; mask_type mask; data_type _data; // All constructors tail_impl(): omin(0), mask(), _data() {} // all arrays of zero size (empty) tail_impl(size_t N1, size_t N2, size_t size_, long order_min): omin(order_min), mask(tqa::make_shape(N1,N2)), _data(tqa::make_shape(size_,N1,N2)) { mask() = order_min+size_-1; _data() = 0; } tail_impl(data_type const &d, mask_type const &m, long omin_) : omin(omin_), mask(m), _data(d) {} tail_impl(tail_impl const & x): omin(x.omin), mask(x.mask), _data(x._data) {} tail_impl(tail_impl const &) = default; tail_impl(tail_impl &&) = default; friend class tail_impl; public: mv_type operator() (int n) { if (n>this->order_max()) TRIQS_RUNTIME_ERROR<<" n > Max Order. n= "< Max Order. n= "< 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); } friend std::ostream & operator << (std::ostream & out, tail_impl const & x) { out <<"tail/tail_view: min/smallest/max = "<< x.order_min() << " " << x.smallest_nonzero() << " "<< x.order_max(); for (long u = x.order_min(); u <= x.order_max(); ++u) out <<"\n ... Order "< const & x) { _data() = 0.0; mv_type(_data(-omin, tqa::range(), tqa::range())) = x; mask() = omin+size()-1; return *this; } using B::operator(); // import all previously defined operator() for overloading friend std::ostream & triqs_nvl_formal_print(std::ostream & out, tail_view const & x) { return out<<"tail_view"; } }; // ----------------------------- // the regular class class tail: public tail_impl { typedef tail_impl B; friend class tail_view; public: tail():B() {} typedef tqa::mini_vector shape_type; tail(size_t N1, size_t N2, size_t size_=10, long order_min=-1): B(N1,N2,size_,order_min) {} tail(shape_type const & sh, size_t size_=10, long order_min=-1): B(sh[0],sh[1],size_,order_min) {} tail(B::data_type const &d, B::mask_type const &m, long order_min): B(d, m, order_min) {} tail(tail const & g): B(g) {} tail(tail_view const & g): B(g) {} tail(tail &&) = default; // operator = for values tail & operator = (tail_view const & rhs) { omin = rhs.omin; mask = rhs.mask; _data = rhs._data; return *this; } tail & operator = (tail const & rhs) { omin = rhs.omin; mask = rhs.mask; _data = rhs._data; return *this; } using B::operator(); /// The simplest tail corresponding to omega static tail_view omega(size_t N1, size_t N2, size_t size_, long order_min) { tail t(N1, N2, size_, order_min); t(-1) = 1; return t; } /// The simplest tail corresponding to omega, constructed from a shape for convenience static tail_view omega(tail::shape_type const & sh, size_t size_, long order_min) { return omega(sh[0],sh[1],size_,order_min); } }; template void assign_from_expression(tail_view t,RHS const & rhs) { t = rhs( tail::omega(t.shape(),t.size(),t.order_min()) ); } inline void tail_view::rebind(tail const &X) { omin = X.omin; mask.rebind(X.mask); _data.rebind(X._data); } inline tail_view & tail_view::operator = (const tail & rhs) { if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2]) || (omin != rhs.omin)) TRIQS_RUNTIME_ERROR<<"tails are incompatible"; mask = rhs.mask; _data = rhs._data; return *this; } inline tail conj(tail_view t) { return {conj(t.data()), t.mask_view(),t.order_min()};} /// Slice in orbital space //template tail_view slice_target(tail_impl const & t, tqa::range R1, tqa::range R2) { inline tail_view slice_target(tail_view t, tqa::range R1, tqa::range R2) { return tail_view(t.data()(tqa::range(),R1,R2), t.mask_view()(R1,R2), t.order_min()); } inline tail inverse(tail_view const & t) { long omin1 = - t.smallest_nonzero(); long omax1 = std::min(t.order_max() + 2*omin1, t.order_min()+long(t.size())-1); size_t si = omax1-omin1+1; tail res(t.shape(), t.size(), t.order_min()); res.mask_view() = omax1; res(omin1) = inverse(t(-omin1)); for (size_t n=1; n= a.n_min and n-p <=b.n_max and n-p >= b.n_min // hence p <= min ( a.n_max, n-b.n_min ) and p >= max ( a.n_min, n- b.n_max) const long pmin = std::max(l.smallest_nonzero(), n - r.order_max() ); const long pmax = std::min(l.order_max(), n - r.smallest_nonzero() ); for (long p = pmin; p <= pmax; ++p) { res(n) += l(p) * r(n-p);} } return res; } template TYPE_ENABLE_IF(tail, mpl::and_, LocalTail>) operator*(T1 const &a, T2 const &b) { return mult_impl(a, b); } template TYPE_ENABLE_IF(tail, mpl::and_, LocalTail>) operator*(T1 const &a, T2 const &b) { auto res = tail{first_dim(a), b.shape()[1], b.size(), b.order_min()}; for (int n = res.order_min(); n <= res.order_max(); ++n) res(n) = a * b(n); return res; } template TYPE_ENABLE_IF(tail, mpl::and_, tqa::ImmutableMatrix>) operator*(T1 const &a, T2 const &b) { auto res = tail{a.shape()[0], second_dim(b), a.size(), a.order_min()}; for (int n = res.order_min(); n <= res.order_max(); ++n) res(n) = a(n) * b; return res; } inline tail operator * (dcomplex a, tail_view const & r) { tail res(r); res.data()*=a; return res;} inline tail operator * (tail_view const & r, dcomplex a) { return a*r; } template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) operator/ (T1 const & a, T2 const & b) { return a * inverse(b); } inline tail operator / (tail_view const & r, dcomplex a) { tail res(r); res.data() /=a; return res;} inline tail operator / (dcomplex a, tail_view const & r) { return a * inverse(r); } template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) operator + (T1 const & l, T2 const& r) { if (l.shape() != r.shape() || l.order_min() != r.order_min() || (l.size() != r.size())) TRIQS_RUNTIME_ERROR<< "tail addition: shape mismatch"; tail res(l.shape(), l.size(), l.order_min()); res.mask_view() = std::min(l.order_max(), r.order_max()); for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) + r(i); return res; } template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) operator - (T1 const & l, T2 const& r) { if (l.shape() != r.shape() || l.order_min() != r.order_min() || (l.size() != r.size())) TRIQS_RUNTIME_ERROR<< "tail addition: shape mismatch"; tail res(l.shape(), l.size(), l.order_min()); res.mask_view() = std::min(l.order_max(), r.order_max()); for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) - r(i); return res; } template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) operator + (T1 const & a, T2 const & t) { tail res(t); res(0) += a; return res; } template TYPE_ENABLE_IF(tail,mpl::and_, is_scalar_or_element>) operator + (T1 const & t, T2 const & a) { return a+t;} template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) operator - (T1 const & a, T2 const & t) { return (-a) + t;} template TYPE_ENABLE_IF(tail,mpl::and_, is_scalar_or_element>) operator - (T1 const & t, T2 const & a) { return (-a) + t;} }}} #endif