ALPSCore reference
tail_base.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 
7 #ifndef ALPSCORE_GF_TAIL_BASE_H
8 #define ALPSCORE_GF_TAIL_BASE_H
9 
10 #include <alps/gf/gf_base.hpp>
11 
12 namespace alps {
13  namespace gf {
14  static const int TAIL_NOT_SET=-1;
15 
16  // forward declarations
17  namespace detail {
18  template<typename HEADGF, typename TAILGF>
19  class gf_tail_base;
20 
21 #ifdef ALPS_HAVE_MPI
22  template <typename TAILT>
23  void broadcast_tail(const alps::mpi::communicator& comm,
24  int& min_order, int& max_order,
25  std::vector<TAILT>& tails,
26  const TAILT& tail_init,
27  int root)
28  {
30  broadcast(comm, min_order, root);
31  broadcast(comm, max_order, root);
32 
33  if (min_order==TAIL_NOT_SET) return;
34  if (comm.rank()!=root) {
35  tails.resize(max_order+1, tail_init);
36  }
37  for (int i=min_order; i<=max_order; ++i) {
38  tails[i].broadcast(comm,root);
39  }
40  }
41 #endif
42  }
43  template<typename HEADGF, typename TAILGF>
44  using gf_tail = detail::gf_tail_base<HEADGF, TAILGF>;
45  // TODO: think how to implement tailed GF view
46 // template<typename VTYPE, typename ...Meshes>
47 // using gf_tail_view = detail::gf_tail_base<VTYPE, detail::tensor_view<VTYPE, sizeof...(Meshes)>, Meshes...>;
48 
49  namespace detail {
58  template<typename HEADGF, typename TAILGF>
59  class gf_tail_base : public HEADGF {
60  // parent class method using
61  using HEADGF::meshes;
62  public:
63  // types definition
65  using Storage = typename HEADGF::storage_type;
67  using VTYPE = typename HEADGF::value_type;
68  using mesh_tuple = typename HEADGF::mesh_types;
70  typedef HEADGF gf_type;
72  typedef TAILGF tail_type;
74  typedef gf_tail_base< HEADGF, TAILGF > gf_type_with_tail;
75  private:
76  // fields definition
77  std::vector<tail_type> tails_;
78  int min_tail_order_;
79  int max_tail_order_;
80 
81  public:
82 
84  gf_tail_base() : gf_type(), min_tail_order_(TAIL_NOT_SET), max_tail_order_(TAIL_NOT_SET) {}
86  gf_tail_base(const gf_type& gf): gf_type(gf), min_tail_order_(TAIL_NOT_SET), max_tail_order_(TAIL_NOT_SET)
87  { }
89  gf_tail_base(const gf_type_with_tail& gft): gf_type(gft), tails_(gft.tails_),
90  min_tail_order_(gft.min_tail_order_),
91  max_tail_order_(gft.max_tail_order_)
92  { }
93 
95  int min_tail_order() const { return min_tail_order_; }
97  int max_tail_order() const { return max_tail_order_; }
98 
100  const tail_type& tail(int order) const{
101  if (order<min_tail_order_ || order > max_tail_order_)
102  throw std::runtime_error("tails are known between min and max order, your order is outside.");
103  return tails_[order];
104  }
105 
107  const std::vector<tail_type>& tail() const{
108  return tails_;
109  }
110 
120  bool operator==(const gf_type_with_tail &rhs) const {
121  bool tail_eq = (min_tail_order_ == rhs.min_tail_order_) && (max_tail_order_ == rhs.max_tail_order_);
122  if(tail_eq && min_tail_order_!=TAIL_NOT_SET) {
123  for (int i = min_tail_order_; i <= max_tail_order_; ++i) {
124  tail_eq &= (tails_[i] == rhs.tails_[i]);
125  }
126  }
127  return tail_eq && HEADGF::operator==(rhs);
128  }
129 
130  template<typename RHS_GF>
131  bool operator!=(const RHS_GF &rhs) const {
132  return !(this->operator==(rhs));
133  }
134 
141  gf_type_with_tail& set_tail(int order, const tail_type &tail){
142  static_assert(std::is_same<typename tail_type::mesh_types,
143  decltype(tuple_tail < 1, std::tuple_size<typename HEADGF::mesh_types>::value >(HEADGF::meshes())) >::value, "Incorrect tail mesh types" );
144 
145  int tail_size=tails_.size();
146  if(order>=tail_size){
147  tails_.resize(order+1, tail_type (tuple_tail < 1, std::tuple_size<typename HEADGF::mesh_types>::value >(meshes())));
148  for(int i=tail_size;i<=order;++i) tails_[i].initialize();
149  }
150  tails_[order]=tail;
151 
152  //set minimum and maximum known coefficients if needed
153  if(min_tail_order_==TAIL_NOT_SET || min_tail_order_>order) min_tail_order_=order;
154  if(max_tail_order_==TAIL_NOT_SET || max_tail_order_<=order) max_tail_order_=order;
155  return *this;
156  }
157 
159  void save(alps::hdf5::archive& ar, const std::string& path) const
160  {
161  gf_type::save(ar,path);
162  ar[path+"/tail/descriptor"]="INFINITY_TAIL";
163  ar[path+"/tail/min_tail_order"]=min_tail_order_;
164  ar[path+"/tail/max_tail_order"]=max_tail_order_;
165  if(min_tail_order_==TAIL_NOT_SET) return;
166  for (int i=min_tail_order_; i<=max_tail_order_; ++i) {
167  ar[path+"/tail/"+std::to_string(i)] << tails_[i].data();
168  }
169  }
170 
172  void load(alps::hdf5::archive& ar, const std::string& path)
173  {
174  gf_type::load(ar,path);
175  std::string descr; ar[path+"/tail/descriptor"] >> descr;
176  if (descr!="INFINITY_TAIL") throw std::runtime_error("Wrong tail format '"+descr+"', expected INFINITY_TAIL");
177 
178  // FIXME!FIXME! Rewrite using clone-swap for exception safety.
179  ar[path+"/tail/min_tail_order"] >> min_tail_order_;
180  ar[path+"/tail/max_tail_order"] >> max_tail_order_;
181 
182  tails_.clear();
183  if(min_tail_order_==TAIL_NOT_SET) return;
184 
185  if(min_tail_order_>0) tails_.resize(min_tail_order_, tail_type (tuple_tail < 1, std::tuple_size<typename HEADGF::mesh_types>::value >(meshes())));
186 
187  for (int i=min_tail_order_; i<=max_tail_order_; ++i) {
188  typename tail_type::storage_type buffer;
189  ar[path+"/tail/"+std::to_string(i)] >> buffer;
190  tails_.push_back(tail_type(buffer, tuple_tail < 1, std::tuple_size<typename HEADGF::mesh_types>::value >(meshes())));
191  }
192  }
193 
195  void save(alps::hdf5::archive& ar) const
196  {
197  save(ar, ar.get_context());
198  }
199 
201  void load(alps::hdf5::archive& ar)
202  {
203  load(ar, ar.get_context());
204  }
205 
206 #ifdef ALPS_HAVE_MPI
207  void broadcast(const alps::mpi::communicator& comm, int root)
209  {
210  // FIXME: use clone-swap?
211  gf_type::broadcast(comm,root);
212  detail::broadcast_tail(comm,
213  min_tail_order_, max_tail_order_,
214  tails_, tail_type(tuple_tail < 1, std::tuple_size<typename HEADGF::mesh_types>::value >(meshes())),
215  root);
216  }
217 #endif
218  };
219  }
220  }
221 }
222 
223 #endif //ALPSCORE_GF_TAIL_BASE_H
void load(archive &ar, std::string const &path, T &value, std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
Definition: archive.hpp:309
void broadcast(C const &c, P &p, int r=0)
Definition: api.hpp:56
bool operator==(const dictionary &lhs, const dictionary &rhs)
Definition: dictionary.hpp:96
auto tuple_tail(T &t) -> DECLTYPE(tuple_tail_< Trim >(t, make_index_sequence< Count-Trim >()))
Encapsulation of an MPI communicator and some communicator-related operations.
Definition: mpi.hpp:111
detail::gf_tail_base< HEADGF, TAILGF > gf_tail
Definition: tail_base.hpp:44
static const int TAIL_NOT_SET
Special tail order meaning the tail is not set.
Definition: tail_base.hpp:14
std::string get_context() const
Definition: archive.cpp:144
int rank() const
Returns process rank in this communicator.
Definition: mpi.hpp:156
void broadcast(const communicator &comm, T *vals, std::size_t count, int root)
Broadcasts array vals of a primitive type T, length count on communicator comm with root root ...
Definition: mpi.hpp:270
bool operator!=(const dictionary &lhs, const dictionary &rhs)
Definition: dictionary.hpp:100
void save(archive &ar, std::string const &path, T const &value, std::vector< std::size_t >=std::vector< std::size_t >(), std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
Definition: archive.hpp:292