NiHu  2.0
leaf_precompute.hpp
Go to the documentation of this file.
1 
7 #ifndef NIHU_LEAF_PRECOMPUTE_HPP_INCLUDED
8 #define NIHU_LEAF_PRECOMPUTE_HPP_INCLUDED
9 
10 #include "cluster_tree.hpp"
11 #include "fmm_operator.hpp"
12 #include "lists.hpp"
13 
14 #include <Eigen/SparseCore>
15 
16 #ifdef NIHU_FMM_PARALLEL
17 #include <omp.h>
18 #endif
19 
20 #include <chrono>
21 #include <memory>
22 #include <type_traits>
23 #include <vector>
24 
25 
26 namespace NiHu
27 {
28 namespace fmm
29 {
30 
31 template <class Result, class FmmTag>
33 
34 
35 template <class Result>
36 class p2x_precompute<Result, p2m_tag>
37  : public fmm_operator<p2m_tag>
38 {
39 public:
40  typedef Result result_t;
41 
42  typedef unsigned int index_t;
43  typedef std::vector<index_t> indices_t;
44  typedef std::vector<result_t> container_t;
45 
46  template <class Operator, class ClusterDerived>
47  p2x_precompute(Operator const &op, cluster_tree<ClusterDerived> const &tree)
48  : m_pcontainer(new container_t(tree.get_leaf_src_indices().size()))
49  , m_psingle_idx(new indices_t(tree.get_n_clusters()))
50  {
51  auto tstart = std::chrono::steady_clock::now();
52  auto const &src_indices = tree.get_leaf_src_indices();
53 #ifdef NIHU_FMM_PARALLEL
54 #pragma omp parallel for
55 #endif
56  for (int i = 0; i < src_indices.size(); ++i)
57  {
58  size_t to = src_indices[i];
59  (*m_pcontainer)[i] = op(to);
60  (*m_psingle_idx)[to] = i;
61  }
62 #ifdef NIHU_FMM_PARALLEL
63 #pragma omp barrier
64 #endif
65  auto tend = std::chrono::steady_clock::now();
66  m_assembly_time = std::chrono::duration_cast<std::chrono::microseconds>(tend - tstart).count();
67  }
68 
69  size_t get_assembly_time() const
70  {
71  return m_assembly_time;
72  }
73 
74  result_t const &operator()(size_t to) const
75  {
76  return (*m_pcontainer)[(*m_psingle_idx)[to]];
77  }
78 
79 private:
80  std::shared_ptr<container_t> m_pcontainer;
81  std::shared_ptr<indices_t> m_psingle_idx;
82  size_t m_assembly_time;
83 };
84 
85 
86 template <class Result>
87 class p2x_precompute<Result, p2l_tag>
88  : public fmm_operator<p2l_tag>
89 {
90 public:
91  typedef Result result_t;
92  typedef interaction_lists::list_t list_t;
93 
94  template <class Operator, class ClusterDerived>
95  p2x_precompute(Operator const &op,
96  cluster_tree<ClusterDerived> const &tree,
97  list_t const &list)
98  : m_double_idx(tree.get_n_clusters(), tree.get_n_clusters())
99  {
100  typedef Eigen::Triplet<size_t, size_t> triplet_t;
101  auto tstart = std::chrono::steady_clock::now();
102  std::vector<triplet_t> triplets;
103  size_t idx = 0;
104  for (size_t to = 0; to < list.size(); ++to)
105  {
106  for (auto from : list[to])
107  {
108  m_container.push_back(op(to, from));
109  triplets.push_back(triplet_t(to, from, idx));
110  ++idx;
111  }
112  }
113  m_double_idx.setFromTriplets(triplets.begin(), triplets.end());
114  auto tend = std::chrono::steady_clock::now();
115  m_assembly_time = std::chrono::duration_cast<std::chrono::microseconds>(tend - tstart).count();
116  }
117 
118  size_t get_assembly_time() const
119  {
120  return m_assembly_time;
121  }
122 
123  result_t const &operator()(size_t to, size_t from) const
124  {
125  return m_container[m_double_idx.coeff(to, from)];
126  }
127 
128 private:
129  std::vector<result_t> m_container;
130  Eigen::SparseMatrix<size_t> m_double_idx;
131  size_t m_assembly_time;
132 };
133 
134 
135 
136 template <class Operator>
137 auto create_p2x_precompute(
138  Operator const &op,
139  cluster_tree<typename std::decay<Operator>::type::cluster_t> const &tree,
140  interaction_lists::list_t const &list)
141 {
142  typedef typename std::decay<Operator>::type operator_t;
143  return p2x_precompute<
144  typename operator_t::result_t,
145  typename operator_t::fmm_tag
146  >(op, tree, list);
147 }
148 
149 template <class Operator>
150 auto create_p2x_precompute(Operator const &op,
151  cluster_tree<typename std::decay<Operator>::type::cluster_t> const &tree)
152 {
153  typedef typename std::decay<Operator>::type operator_t;
154  return p2x_precompute<
155  typename operator_t::result_t,
156  typename operator_t::fmm_tag
157  >(op, tree);
158 }
159 
160 
161 template <class Result, class FmmTag>
163 
164 
165 template <class Result>
166 class x2p_precompute<Result, l2p_tag>
167  : public fmm_operator<l2p_tag>
168 {
169 public:
170  typedef Result result_t;
171 
172  template <class Operator>
173  x2p_precompute(Operator const &op,
174  cluster_tree<typename std::decay<Operator>::type::cluster_t> const &tree)
175  : m_pcontainer(tree.get_leaf_rec_indices().size())
176  , m_single_idx(tree.get_n_clusters())
177  {
178  auto tstart = std::chrono::steady_clock::now();
179  auto const &list = tree.get_leaf_rec_indices();
180 #ifdef NIHU_FMM_PARALLEL
181 #pragma omp parallel for
182 #endif
183  for (int i = 0; i < list.size(); ++i)
184  {
185  size_t to = list[i];
186  m_pcontainer[i] = op(to);
187  m_single_idx[to] = i;
188  }
189 #ifdef NIHU_FMM_PARALLEL
190 #pragma omp barrier
191 #endif
192  auto tend = std::chrono::steady_clock::now();
193  m_assembly_time = std::chrono::duration_cast<std::chrono::microseconds>(tend - tstart).count();
194  }
195 
196  result_t const &operator()(size_t to) const
197  {
198  return m_pcontainer[m_single_idx[to]];
199  }
200 
201  size_t get_assembly_time() const
202  {
203  return m_assembly_time;
204  }
205 
206 private:
207  std::vector<result_t> m_pcontainer;
208  std::vector<size_t> m_single_idx;
209  size_t m_assembly_time;
210 };
211 
212 
213 
214 
215 template <class Result>
216 class x2p_precompute<Result, m2p_tag>
217  : public fmm_operator<m2p_tag>
218 {
219 public:
220  typedef interaction_lists::list_t list_t;
221  typedef Result result_t;
222 
223  typedef unsigned int index_t;
224  typedef Eigen::SparseMatrix<index_t> indices_t;
225  typedef std::vector<result_t> container_t;
226 
227  template <class Operator>
228  x2p_precompute(Operator const &op,
229  cluster_tree<typename std::decay<Operator>::type::cluster_t> const &tree, list_t const &list)
230  : m_pcontainer(new container_t)
231  , m_pdouble_idx(new indices_t(tree.get_n_clusters(), tree.get_n_clusters()))
232  {
233  typedef Eigen::Triplet<size_t, size_t> triplet_t;
234  auto tstart = std::chrono::steady_clock::now();
235  std::vector<triplet_t> triplets;
236  size_t idx = 0;
237  for (size_t to = 0; to < list.size(); ++to)
238  {
239  for (auto from : list[to])
240  {
241  m_pcontainer->push_back(op(to, from));
242  triplets.push_back(triplet_t(to, from, idx));
243  ++idx;
244  }
245  }
246  m_pdouble_idx->setFromTriplets(triplets.begin(), triplets.end());
247  auto tend = std::chrono::steady_clock::now();
248  m_assembly_time = std::chrono::duration_cast<std::chrono::microseconds>(tend - tstart).count();
249  }
250 
251  result_t const &operator()(size_t to, size_t from) const
252  {
253  return (*m_pcontainer)[m_pdouble_idx->coeff(to, from)];
254  }
255 
256  size_t get_assembly_time() const
257  {
258  return m_assembly_time;
259  }
260 
261 private:
262  std::shared_ptr<container_t> m_pcontainer;
263  std::shared_ptr<indices_t> m_pdouble_idx;
264  size_t m_assembly_time;
265 };
266 
267 
268 
269 template <class Operator>
270 auto create_x2p_precompute(
271  Operator const &op,
272  cluster_tree<typename std::decay<Operator>::type::cluster_t> const &tree,
273  interaction_lists::list_t const &list)
274 {
275  typedef typename std::decay<Operator>::type operator_t;
276 
277  return x2p_precompute<
278  typename operator_t::result_t,
279  m2p_tag
280  >(op, tree, list);
281 }
282 
283 template <class Operator>
284 auto create_x2p_precompute(
285  Operator const &op,
286  cluster_tree<typename std::decay<Operator>::type::cluster_t> const &tree)
287 {
288  typedef typename std::decay<Operator>::type operator_t;
289  return x2p_precompute<
290  typename operator_t::result_t,
291  l2p_tag
292  >(op, tree);
293 }
294 
295 
296 } // end of namespace fmm
297 } // namespace NiHu
298 
299 #endif /* NIHU_LEAF_PRECOMPUTE_HPP_INCLUDED */
fmm_operator.hpp
FMM operator types and tags.
NiHu::fmm::op_tags::l2p
Definition: fmm_operator.hpp:26
NiHu::fmm::cluster_tree::get_n_clusters
size_t get_n_clusters() const
return number of clusters
Definition: cluster_tree.hpp:282
NiHu::fmm::op_tags::p2l
Definition: fmm_operator.hpp:25
NiHu::fmm::cluster_tree
Class representing a cluster tree.
Definition: cluster_tree.hpp:33
NiHu::fmm::op_tags::p2m
Definition: fmm_operator.hpp:24
NiHu::fmm::p2x_precompute
Definition: leaf_precompute.hpp:32
cluster_tree.hpp
Implementation of class NiHu::fmm::cluster_tree.
lists.hpp
Definition of class NiHu::fmm::interaction_lists.
NiHu::fmm::fmm_operator
Operator defining its tag type.
Definition: fmm_operator.hpp:85
NiHu::fmm::op_tags::m2p
Definition: fmm_operator.hpp:27
NiHu::fmm::x2p_precompute
Definition: leaf_precompute.hpp:162