ALPSCore reference
weight_holder.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 #pragma once
8 
9 #include <alps/config.hpp>
10 
13 
14 #include <alps/hdf5/archive.hpp>
17 
18 #include <boost/utility.hpp>
19 #include <memory>
20 
21 #include <stdexcept>
22 #include <type_traits>
23 
24 namespace alps {
25  namespace accumulators {
26  // this should be called namespace tag { template<typename T> struct weight_holder; }
27  // but gcc <= 4.4 has lookup error, so name it different
28  template<typename T> struct weight_holder_tag;
29 
30  namespace impl {
31 
32  template<typename T, typename W, typename B> struct Accumulator<T, weight_holder_tag<W>, B> : public B {
33 
34  public:
35  typedef W weight_type;
36  typedef Result<T, weight_holder_tag<W>, typename B::result_type> result_type;
37 
38  // TODO: add external weight!
39 
40  Accumulator(): B(), m_owner(true), m_weight(new ::alps::accumulators::derived_accumulator_wrapper<W>(W())) {}
41 
42  Accumulator(Accumulator const & arg): B(arg), m_owner(arg.m_owner), m_weight(arg.m_weight) {}
43 
44  template<typename ArgumentPack> Accumulator(ArgumentPack const & args, typename std::enable_if<!is_accumulator<ArgumentPack>::value, int>::type = 0)
45  : B(args), m_owner(true), m_weight(new ::alps::accumulators::derived_accumulator_wrapper<W>(W()))
46  {}
47 
48  base_wrapper<T> const * weight() const {
49  // TODO: make library for scalar type
50  return m_weight.get();
51  }
52 
53  void operator()(T const & val) {
54  // TODO: throw if weight is owned ...
55  B::operator()(val);
56  }
57 
58  template<typename X> typename std::enable_if<std::conditional<
59  std::is_scalar<typename value_type<weight_type>::type>::value
60  , typename std::is_convertible<X, typename value_type<weight_type>::type>::type
61  , typename std::is_same<X, typename value_type<weight_type>::type>::type
62  >::value>::type operator()(T const & val, X const & weight) {
63  // TODO: how do we make sure, weight is updated only once?
64  B::operator()(val);
65  (m_weight->template extract<W>())(weight);
66  }
67 
68  template<typename X> typename std::enable_if<!std::conditional<
69  std::is_scalar<typename value_type<weight_type>::type>::value
70  , typename std::is_convertible<X, typename value_type<weight_type>::type>::type
71  , typename std::is_same<X, typename value_type<weight_type>::type>::type
72  >::value>::type operator()(T const & /*val*/, X const & /*weight*/) {
73  throw std::runtime_error("Invalid type for binary call operator" + ALPS_STACKTRACE);
74  }
75 
76  template<typename S> void print(S & os, bool terse=false) const {
77  B::print(os, terse);
78  os << ", weight: ";
79  m_weight->print(os, terse);
80  }
81 
82  void save(hdf5::archive & ar) const {
83  B::save(ar);
84  ar["weight/value"] = *weight();
85  }
86 
87  void load(hdf5::archive & ar) { // TODO: make archive const
88  B::load(ar);
89  ar["weight/value"] >> *m_weight;
90  }
91 
92  static std::size_t rank() { return B::rank() + 1; }
93  static bool can_load(hdf5::archive & ar) { // TODO: make archive const
95 
96  ar.set_context("weight/value");
97  bool is = weight_type::can_load(ar);
98  ar.set_context("../..");
99 
100  return is && B::can_load(ar);
101  }
102 
103  void reset() {
104  B::reset();
105  m_weight->reset();
106  }
107 
109  template <typename A>
110  void merge(const A& /*rhs*/)
111  {
112  throw std::logic_error("Merging weight_holder accumulators is not yet implemented"
113  +ALPS_STACKTRACE);
114  }
115 
116 #ifdef ALPS_HAVE_MPI
117  void collective_merge(
118  alps::mpi::communicator const & comm
119  , int root
120  ) {
121  B::collective_merge(comm, root);
122  m_weight->collective_merge(comm, root);
123  }
124 
125  void collective_merge(
126  alps::mpi::communicator const & comm
127  , int root
128  ) const {
129  B::collective_merge(comm, root);
130  m_weight->collective_merge(comm, root);
131  }
132 #endif
133 
134  bool owns_weight() const {
135  return m_owner;
136  }
137 
138  private:
139  bool m_owner;
140  std::shared_ptr< ::alps::accumulators::base_wrapper<typename value_type<weight_type>::type> > m_weight;
141  };
142 
143  template<typename T, typename W, typename B> class Result<T, weight_holder_tag<W>, B> : public B {
144 
145  public:
146  typedef W weight_type;
147  typedef typename detail::make_scalar_result_type<impl::Result,T,weight_holder_tag<W>,B>::type scalar_result_type;
148 
150  : B()
151  , m_owner(true)
152  , m_weight(new ::alps::accumulators::derived_result_wrapper<W>(W()))
153  {}
154 
155  template<typename A> Result(A const & acc)
156  : B(acc)
157  , m_owner(acc.owns_weight())
158  // TODO: implement shared weight
159  , m_weight(acc.weight()->result())
160  {}
161 
163  return m_weight.get();
164  }
165 
166  template<typename S> void print(S & os, bool terse=false) const {
167  B::print(os, terse);
168  os << ", weight: ";
169  m_weight->print(os, terse);
170  }
171 
172  void save(hdf5::archive & ar) const {
173  B::save(ar);
174  ar["weight/value"] = *weight();
175  }
176 
177  void load(hdf5::archive & ar) {
178  B::load(ar);
179  ar["weight/value"] >> *m_weight;
180  }
181 
182  static std::size_t rank() { return B::rank() + 1; }
183  static bool can_load(hdf5::archive & ar) { // TODO: make archive const
185 
186  ar.set_context("weight/value");
187  bool is = weight_type::can_load(ar);
188  ar.set_context("../..");
189 
190  return is && B::can_load(ar);
191  }
192 
193  protected:
194  bool m_owner;
195  std::shared_ptr< ::alps::accumulators::base_wrapper<typename value_type<weight_type>::type> > m_weight;
196  };
197 
198  }
199  }
200 }
std::enable_if<!std::conditional< std::is_scalar< typename value_type< weight_type >::type >::value, typename std::is_convertible< X, typename value_type< weight_type >::type >::type, typename std::is_same< X, typename value_type< weight_type >::type >::type >::value >::type operator()(T const &, X const &)
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
std::vector< std::size_t > get_extent(T const &value)
Definition: archive.hpp:280
Encapsulation of an MPI communicator and some communicator-related operations.
Definition: mpi.hpp:111
Result< T, weight_holder_tag< W >, typename B::result_type > result_type
detail::make_scalar_result_type< impl::Result, T, weight_holder_tag< W >, B >::type scalar_result_type
std::shared_ptr< ::alps::accumulators::base_wrapper< typename value_type< weight_type >::type > > m_weight
void set_context(std::string const &context)
Definition: archive.cpp:148
void reset(accumulator_wrapper &arg)
Accumulator(ArgumentPack const &args, typename std::enable_if<!is_accumulator< ArgumentPack >::value, int >::type=0)
std::ostream & print(std::ostream &s, const dict_value &dv, bool terse)
Definition: dict_value.cpp:186
#define ALPS_STACKTRACE
Definition: stacktrace.hpp:37
base_wrapper< typename value_type< weight_type >::type > const * weight() const
traits< Acc >::result_type result(const Acc &acc)
Definition: util.hpp:53
std::enable_if< std::conditional< std::is_scalar< typename value_type< weight_type >::type >::value, typename std::is_convertible< X, typename value_type< weight_type >::type >::type, typename std::is_same< X, typename value_type< weight_type >::type >::type >::value >::type operator()(T const &val, X const &weight)
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
base_wrapper< typename value_type< T >::type > const * weight(T const &arg)
Definition: weight.hpp:53