NiHu  2.0
x2x_precompute.hpp
Go to the documentation of this file.
1 
7 #ifndef NIHU_FMM_X2X_PRECOMPUTE_HPP_INCLUDED
8 #define NIHU_FMM_X2X_PRECOMPUTE_HPP_INCLUDED
9 
10 #include "cluster_tree.hpp"
11 #include "fmm_operator.hpp"
12 #include "lists.hpp"
13 
14 #include "util/eigen_utils.hpp"
15 
16 #ifdef NIHU_FMM_PARALLEL
17 #include <omp.h>
18 #endif
19 
20 #include "Eigen/SparseCore"
21 
22 #include <chrono>
23 #include <type_traits>
24 #include <vector>
25 #include <memory>
26 
27 namespace NiHu
28 {
29 namespace fmm
30 {
31 
38 template <class Result, class ClusterDerived, class FmmTag>
40  : public fmm_operator<FmmTag>
41 {
42 public:
43  typedef ClusterDerived cluster_t;
45  typedef interaction_lists::list_t list_t;
46  typedef Result result_t;
47 
48  typedef typename std::conditional<
49  is_eigen<result_t>::value, typename eigen_std_vector<Result>::type, std::vector<result_t>
50  >::type container_elem_t;
51 
52  typedef typename std::conditional<
53  is_eigen<result_t>::value, typename eigen_std_vector<container_elem_t>::type, std::vector<container_elem_t>
54  >::type container_t;
55 
56  typedef unsigned int index_t;
57  typedef Eigen::SparseMatrix<index_t> indices_t;
58 
59  template <class Operator>
60  x2x_precompute(Operator const &op, list_t const &list)
61  : m_tree(op.get_tree())
62  , m_pindices(new indices_t(m_tree.get_n_clusters(), m_tree.get_n_clusters()))
63  , m_pcontainer(new container_t(m_tree.get_n_levels()))
64  {
65  typedef typename std::decay<Operator>::type operator_t;
66  typedef Eigen::Triplet<index_t> triplet_t;
67  std::vector<triplet_t> triplets, to_compute;
68 
69  std::vector<std::vector<bool> > ready(m_tree.get_n_levels() + 1);
70 
71  auto tstart = std::chrono::steady_clock::now();
72 
73  for (size_t to = 0; to < list.size(); ++to)
74  {
75  for (auto from : list[to])
76  {
77  cluster_t const &cto = m_tree[to];
78  cluster_t const &cfrom = m_tree[from];
79  size_t level = cto.get_level();
80  size_t idx = operator_t::operator_t::unique_idx(cto, cfrom);
81  if (idx >= (*m_pcontainer)[level].size() )
82  {
83  (*m_pcontainer)[level].resize(idx + 1);
84  ready[level].resize(idx + 1, false);
85  }
86  if (!ready[level][idx])
87  {
88  to_compute.push_back(triplet_t(int(to), int(from), idx));
89  ready[level][idx] = true;
90  }
91  triplets.push_back(triplet_t(int(to), int(from), idx));
92  }
93  }
94 
95 #ifdef NIHU_FMM_PARALLEL
96 #pragma omp parallel for schedule(dynamic)
97 #endif
98  for (int i = 0; i < to_compute.size(); ++i)
99  {
100  size_t to = to_compute[i].row();
101  size_t from = to_compute[i].col();
102  size_t idx = to_compute[i].value();
103  size_t level = m_tree[to].get_level();
104  (*m_pcontainer)[level][idx] = op(to, from);
105  }
106 #ifdef NIHU_FMM_PARALLEL
107 #pragma omp barrier
108 #endif
109 
110  m_pindices->setFromTriplets(triplets.begin(), triplets.end());
111  auto tend = std::chrono::steady_clock::now();
112  m_assembly_time = std::chrono::duration_cast<std::chrono::microseconds>(tend - tstart).count();
113  }
114 
115  result_t const &operator()(size_t to, size_t from) const
116  {
117  size_t level = m_tree[to].get_level();
118  size_t idx = m_pindices->coeff(to, from);
119  return (*m_pcontainer)[level][idx];
120  }
121 
122  size_t get_assembly_time() const
123  {
124  return m_assembly_time;
125  }
126 
127 private:
128  cluster_tree_t const &m_tree;
129  std::shared_ptr<indices_t> m_pindices;
130  std::shared_ptr<container_t> m_pcontainer;
131  size_t m_assembly_time;
132 };
133 
134 
135 template <class Operator>
136 auto
137 create_x2x_precompute(Operator const &op, typename interaction_lists::list_t const &list)
138 {
139  typedef typename std::decay<Operator>::type operator_t;
140  return x2x_precompute<
141  typename operator_t::result_t,
142  typename operator_t::cluster_t,
143  typename operator_t::fmm_tag
144  >(op, list);
145 }
146 
147 } // namespace fmm
148 } // namespace NiHu
149 
150 #endif /* NIHU_FMM_X2X_PRECOMPUTE_HPP_INCLUDED */
fmm_operator.hpp
FMM operator types and tags.
NiHu::is_eigen
metafunction determining if its argument is an Eigen expression or not
Definition: eigen_utils.hpp:51
eigen_utils.hpp
Implementation of Eigen related utility classes.
NiHu::fmm::cluster_tree< cluster_t >
NiHu::fmm::x2x_precompute
Precomputation for M2M, M2L, and L2L operators.
Definition: x2x_precompute.hpp:39
cluster_tree.hpp
Implementation of class NiHu::fmm::cluster_tree.
NiHu::fmm::cluster_tree::get_n_levels
size_t get_n_levels() const
return number of levels
Definition: cluster_tree.hpp:253
lists.hpp
Definition of class NiHu::fmm::interaction_lists.
NiHu::fmm::fmm_operator
Operator defining its tag type.
Definition: fmm_operator.hpp:85