7 #ifndef NIHU_P2P_PRECOMPUTE_HPP_INCLUDED
8 #define NIHU_P2P_PRECOMPUTE_HPP_INCLUDED
17 #include <Eigen/SparseCore>
19 #ifdef NIHU_FMM_PARALLEL
25 #include <type_traits>
43 template <
class Operator,
class ClusterDerived,
bool isLocal>
44 class sparse_index_computer;
47 template <
class Operator,
class ClusterDerived>
48 class sparse_index_computer<Operator, ClusterDerived, false>
50 typedef typename std::decay<Operator>::type operator_t;
51 typedef unsigned int index_t;
52 typedef std::vector<std::pair<index_t, index_t> > indices_t;
54 typedef cluster_tree<cluster_t> tree_t;
58 static indices_t eval(tree_t
const &tree,
59 interaction_lists::list_t
const &p2p_list)
65 for (
unsigned to = 0; to < p2p_list.size(); ++to)
66 for (
auto from : p2p_list[to])
67 s += tree[to].get_rec_node_idx().size() *
68 tree[from].get_src_node_idx().size();
72 for (
unsigned to = 0; to < p2p_list.size(); ++to)
73 for (
auto from : p2p_list[to])
74 for (
auto i : tree[to].get_rec_node_idx())
75 for (
auto j : tree[from].get_src_node_idx())
76 indices.push_back(std::make_pair(i, j));
83 template <
class Operator,
class ClusterDerived>
84 class sparse_index_computer<Operator, ClusterDerived, true>
86 typedef typename std::decay<Operator>::type operator_t;
87 typedef std::vector<std::pair<unsigned int, unsigned int> > indices_t;
89 typedef cluster_tree<cluster_t> tree_t;
92 static indices_t eval(tree_t
const &tree,
93 interaction_lists::list_t
const &p2p_list)
99 for (
unsigned to = 0; to < p2p_list.size(); ++to)
100 if (std::find(p2p_list[to].begin(), p2p_list[to].end(), to) != p2p_list[to].end())
101 s += tree[to].get_rec_node_idx().size();
105 for (
unsigned to = 0; to < p2p_list.size(); ++to)
106 if (std::find(p2p_list[to].begin(), p2p_list[to].end(), to) != p2p_list[to].end())
107 for (
auto i : tree[to].get_rec_node_idx())
108 indices.push_back(std::make_pair(i, i));
120 template <
class Operator,
class ClusterDerived,
bool isResultEigen = is_eigen<
121 typename std::decay<Operator>::type::result_t>::value>
122 class sparse_computer;
126 template <
class Operator,
class ClusterDerived>
127 class sparse_computer<Operator, ClusterDerived, true>
129 typedef typename std::decay<Operator>::type operator_t;
130 typedef typename operator_t::result_t result_t;
131 typedef typename scalar<result_t>::type scalar_t;
132 static size_t const rows = num_rows<result_t>::value;
133 static size_t const cols = num_cols<result_t>::value;
134 typedef std::ptrdiff_t storage_index_t;
135 typedef Eigen::SparseMatrix<scalar_t, Eigen::RowMajor, storage_index_t> sparse_t;
137 typedef cluster_tree<cluster_t> tree_t;
139 static bool const is_local = is_local_operator<operator_t>::value;
140 typedef sparse_index_computer<Operator, ClusterDerived, is_local> index_computer_t;
154 static sparse_t *eval(Operator &&op, tree_t
const &tree, interaction_lists::list_t
const &list,
size_t &assembly_time)
156 auto tstart = std::chrono::steady_clock::now();
158 auto indices = index_computer_t::eval(tree, list);
159 size_t s = indices.size();
161 sparse_t *pmat =
new sparse_t(rows * tree.get_n_rec_nodes(), cols * tree.get_n_src_nodes());
162 Eigen::Matrix<unsigned, Eigen::Dynamic, 1> num_nonzeros_per_row(pmat->rows(),1);
163 num_nonzeros_per_row.setZero();
165 for (
size_t isrcrec = 0; isrcrec < s; ++isrcrec)
167 auto i = indices[isrcrec].first;
168 for (
int ii = 0; ii < rows; ++ii)
169 num_nonzeros_per_row(i * rows + ii) += cols;
171 pmat->reserve(num_nonzeros_per_row);
173 #ifdef NIHU_FMM_PARALLEL
176 for (
int isrcrec = 0; isrcrec < s; ++isrcrec)
178 auto i = indices[isrcrec].first;
179 auto j = indices[isrcrec].second;
180 result_t opmat = op(i, j);
181 for (
size_t ii = 0; ii < rows; ++ii)
182 for (
size_t jj = 0; jj < cols; ++jj)
183 pmat->insert(i * rows + ii, j * cols + jj) = opmat(ii, jj);
185 #ifdef NIHU_FMM_PARALLEL
188 pmat->makeCompressed();
190 auto tend = std::chrono::steady_clock::now();
191 assembly_time = std::chrono::duration_cast<std::chrono::microseconds>(tend - tstart).count();
198 template <
class Operator,
class ClusterDerived>
199 class sparse_computer<Operator, ClusterDerived, false>
201 typedef typename std::decay<Operator>::type operator_t;
202 typedef typename operator_t::result_t result_t;
203 using scalar_t =
typename scalar<result_t>::type;
204 typedef std::ptrdiff_t storage_index_t;
205 typedef Eigen::SparseMatrix<scalar_t, Eigen::RowMajor, storage_index_t> sparse_t;
207 typedef cluster_tree<cluster_t> tree_t;
209 static bool const is_local = is_local_operator<operator_t>::value;
210 typedef sparse_index_computer<Operator, ClusterDerived, is_local> index_computer_t;
214 static sparse_t *eval(
217 interaction_lists::list_t
const &list,
218 size_t &assembly_time)
220 auto tstart = std::chrono::steady_clock::now();
223 auto indices = index_computer_t::eval(tree, list);
224 size_t s = indices.size();
226 sparse_t *pmat =
new sparse_t(tree.get_n_rec_nodes(), tree.get_n_src_nodes());
227 Eigen::Matrix<unsigned, Eigen::Dynamic, 1> num_nonzeros_per_row(pmat->rows(),1);
228 num_nonzeros_per_row.setZero();
230 for (
size_t isrcrec = 0; isrcrec < s; ++isrcrec)
231 num_nonzeros_per_row(indices[isrcrec].first)++;
232 pmat->reserve(num_nonzeros_per_row);
234 #ifdef NIHU_FMM_PARALLEL
237 for (
int isrcrec = 0; isrcrec < s; ++isrcrec)
239 size_t i = indices[isrcrec].first;
240 size_t j = indices[isrcrec].second;
241 pmat->insert(i, j) = op(i, j);
243 #ifdef NIHU_FMM_PARALLEL
246 pmat->makeCompressed();
248 auto tend = std::chrono::steady_clock::now();
249 assembly_time = std::chrono::duration_cast<std::chrono::microseconds>(tend - tstart).count();
264 template <
class Scalar,
size_t NumDofPerSrc,
size_t NumDofPerRec>
271 typedef Scalar scalar_t;
274 typedef Eigen::SparseMatrix<scalar_t, Eigen::RowMajor, std::ptrdiff_t> sparse_t;
275 typedef Eigen::Matrix<scalar_t, Eigen::Dynamic, 1> response_t;
277 static size_t const num_dof_per_src = NumDofPerSrc;
278 static size_t const num_dof_per_rec = NumDofPerRec;
286 template <
class Operator,
class ClusterDerived>
288 : m_pmat(internal::sparse_computer<Operator, ClusterDerived>::eval(std::forward<Operator>(op), tree, list, m_assembly_time))
307 return m_assembly_time;
319 return *m_pmat * rhs;
324 std::shared_ptr<sparse_t> m_pmat;
326 size_t m_assembly_time;
338 template <
class Operator,
class ClusterDerived>
341 interaction_lists::list_t
const &list)
343 typedef typename std::decay<Operator>::type operator_t;
345 typename scalar<typename operator_t::result_t>::type,
346 operator_t::num_dof_per_src,
347 operator_t::num_dof_per_rec
348 >(std::forward<Operator>(op), tree, list);