/******************************************************************************* * * 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 gf { namespace local { namespace details { static constexpr double small = 1.e-10; } 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_{}; 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 void has_view_type_tag; // Idiom : ValueView typedef tail_view view_type; typedef tail non_view_type; typedef arrays::array data_non_view_type; typedef arrays::array_view data_view_type; typedef typename mpl::if_c::type data_type; typedef arrays::array mask_non_view_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; //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]);} size_t shape(int i) const { return _data.shape()[i];} 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, long order_min, mask_type const &om): omin(order_min), mask(om), _data(d) {} // tail_impl(tail_impl const & x): omin(x.omin), mask(x.mask), _data(x._data){} 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 & boost::serialization::make_nvp("omin",omin); ar & boost::serialization::make_nvp("mask",mask); ar & boost::serialization::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) { if (omin > 0) TRIQS_RUNTIME_ERROR<<"lhs has too large omin"; for (size_t n=0; n { 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(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_) { tail t(N1, N2, size_, -1); 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_) { return omega(sh[0],sh[1],size_);} }; template void assign_from_expression(tail_view & t,RHS const & rhs) { t = rhs( tail::omega(t.shape(),t.size())); } 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 (this->_data.is_empty()) rebind(rhs); else { if (rhs.omin < omin) TRIQS_RUNTIME_ERROR<<"rhs has too small omin"; if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2])) TRIQS_RUNTIME_ERROR<<"rhs has different shape"; for (size_t i=0; i tail_view slice_target(tail_impl const & t, tqa::range R1, tqa::range R2) { return tail_view(t.data()(tqa::range(),R1,R2),t.order_min(),t.mask_view()(R1,R2)); } inline tail inverse(tail_view const & t) { // find in t long omin1 = - t.smallest_nonzero(); long omax1 = t.order_max() + 2*omin1; size_t si = omax1-omin1+1; tail t_inv(t.shape(), si, omin1); t_inv(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) { tail res(b); for (long n=res.order_min(); n<=res.order_max(); ++n) res(n)=a*res(n); return res; } template TYPE_ENABLE_IF(tail,mpl::and_, tqa::ImmutableMatrix>) operator* (T1 const & a, T2 const & b) { tail res(a); for (long n=res.order_min(); n<=res.order_max(); ++n) res(n)=res(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) { using arrays::range; if (l.shape() != r.shape()) TRIQS_RUNTIME_ERROR<< "tail addition : shape mismatch"; long omin1 = std::min(l.smallest_nonzero(),r.smallest_nonzero()); long omax1 = std::min(l.order_max(),r.order_max()); size_t si = omax1-omin1+1; tail res(l.shape(), si, omin1); 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) { using arrays::range; if (l.shape() != r.shape()) TRIQS_RUNTIME_ERROR<< "tail substraction : shape mismatch"; long omin1 = std::min(l.smallest_nonzero(),r.smallest_nonzero()); long omax1 = std::min(l.order_max(),r.order_max()); size_t si = omax1-omin1+1; tail res(l.shape(), si, omin1); 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