NiHu  2.0
fmm_matrix.hpp
Go to the documentation of this file.
1 
7 #ifndef FMM_MATRIX_HPP_INCLUDED
8 #define FMM_MATRIX_HPP_INCLUDED
9 
10 #include "cluster_tree.hpp"
12 #include "fmm_timer.h"
13 #include "lists.hpp"
14 #include "util/matrix_traits.hpp"
15 
16 #include <mex.h>
17 
18 
19 #ifdef NIHU_MEX_DEBUG
20 #define mexForcedPrintf(text) { \
21  mxArray *new_number; \
22  mxArray *str = mxCreateString( (text) ); \
23  mexCallMATLAB(1,&new_number,1,&str,"input"); \
24  double out = mxGetScalar(new_number); \
25  (void)out; \
26  mxDestroyArray(new_number); \
27  mxDestroyArray(str); \
28  }
29 #else
30 #define mexForcedPrintf(text) std::cout << text
31 #endif
32 
33 
34 #ifdef NIHU_FMM_PARALLEL
35 #include <omp.h>
36 #endif
37 
38 #include <algorithm>
39 #include <vector>
40 
41 //#define NIHU_DEBUGGING
42 
43 #ifdef NIHU_DEBUGGING
44 #include <iostream>
45 #endif
46 
47 namespace NiHu
48 {
49 namespace fmm
50 {
51 
64 template <
65  class P2P,
66  class P2M, class P2L, class M2P, class L2P,
67  class M2M, class L2L, class M2L
68 >
70 {
71 public:
72  typedef typename std::decay<P2P>::type p2p_t;
73  typedef typename std::decay<P2M>::type p2m_t;
74  typedef typename std::decay<P2L>::type p2l_t;
75  typedef typename std::decay<M2P>::type m2p_t;
76  typedef typename std::decay<L2P>::type l2p_t;
77  typedef typename std::decay<M2M>::type m2m_t;
78  typedef typename std::decay<L2L>::type l2l_t;
79  typedef typename std::decay<M2L>::type m2l_t;
80 
81  typedef typename m2l_t::cluster_t cluster_t;
82  typedef typename cluster_t::multipole_t multipole_t;
83  typedef typename cluster_t::local_t local_t;
84 
85  typedef typename p2p_t::sparse_t sparse_t;
86  typedef typename scalar<sparse_t>::type scalar_t;
87  typedef Eigen::Matrix<scalar_t, Eigen::Dynamic, 1> excitation_t;
88  typedef Eigen::Matrix<scalar_t, Eigen::Dynamic, 1> response_t;
89 
91 
93  static size_t const num_dof_per_src = p2p_t::num_dof_per_src;
95  static size_t const num_dof_per_rec = p2p_t::num_dof_per_rec;
96 
109  P2M &&p2m, P2L &&p2l, M2P &&m2p, L2P &&l2p,
110  M2M &&m2m, L2L &&l2l, M2L &&m2l,
111  cluster_tree_t const &tree,
112  interaction_lists const &lists)
113  : m_p2p(std::forward<P2P>(p2p))
114  , m_p2m(std::forward<P2M>(p2m))
115  , m_p2l(std::forward<P2L>(p2l))
116  , m_m2p(std::forward<M2P>(m2p))
117  , m_l2p(std::forward<L2P>(l2p))
118  , m_m2m(std::forward<M2M>(m2m))
119  , m_l2l(std::forward<L2L>(l2l))
120  , m_m2l(std::forward<M2L>(m2l))
121  , m_tree(tree)
122  , m_lists(lists)
123  , m_timer(tree.get_n_levels())
124  , m_rhs_segments(tree.get_n_clusters())
125  , m_lhs_segments(tree.get_n_clusters())
126  , m_cut_ratio(2.0)
127  {
128 
129  mexForcedPrintf("fmm_matrix constructor\n");
130 
131  for (auto c : m_tree.get_leaf_src_indices())
132  {
133  cluster_t const &clus = m_tree[c];
134  m_rhs_segments[c].resize(clus.get_n_src_nodes() * num_dof_per_src);
135  }
136  for (auto c : m_tree.get_leaf_rec_indices())
137  {
138  cluster_t const &clus = m_tree[c];
139  m_lhs_segments[c].resize(clus.get_n_rec_nodes() * num_dof_per_rec);
140  }
141  }
142 
147  void set_cut_ratio(double cut_ratio)
148  {
149  m_cut_ratio = cut_ratio;
150  }
151 
156  double get_cut_ratio() const
157  {
158  return m_cut_ratio;
159  }
160 
163  size_t get_dfs_cut_level() const
164  {
165  size_t cut_level = std::min<size_t>(2, m_tree.get_n_levels() - 1);
166 
167 #ifdef NIHU_FMM_PARALLEL
168  int max_num_threads = omp_get_max_threads();
169  size_t cut_num_clusters = max_num_threads * m_cut_ratio;
170  while (cut_level < m_tree.get_n_levels() - 1)
171  {
172  size_t num_clusters = m_tree.level_end(cut_level) - m_tree.level_begin(cut_level);
173  if (num_clusters > cut_num_clusters)
174  break;
175  ++cut_level;
176  }
177 #endif
178 
179  return cut_level;
180  }
181 
184  size_t rows() const
185  {
186  return m_p2p.get_sparse_matrix().rows();
187  }
188 
191  size_t cols() const
192  {
193  return m_p2p.get_sparse_matrix().cols();
194  }
195 
200  template <class RhsDerived>
201  void reorder_excitation(Eigen::MatrixBase<RhsDerived> const &rhs)
202  {
203  for (auto c : m_tree.get_leaf_src_indices())
204  {
205  cluster_t const &clus = m_tree[c];
206  for (size_t i = 0; i < clus.get_n_src_nodes(); ++i)
207  {
208  size_t ii = clus.get_src_node_idx()[i];
209  m_rhs_segments[c].segment(i * num_dof_per_src, num_dof_per_src) =
210  rhs.segment(ii * num_dof_per_src, num_dof_per_src);
211  }
212  }
213  }
214 
220  void upward_pass_dfs_rec(std::vector<multipole_t> &multipoles, size_t root)
221  {
222  for (auto c : m_tree[root].get_children())
223  {
224  if (m_tree[c].is_source())
225  {
226  upward_pass_dfs_rec(multipoles, c);
227  multipoles[root] += m_m2m(root, c) * multipoles[c];
228  }
229  }
230  }
231 
238  void downward_pass_dfs_rec(std::vector<local_t> &locals,
239  std::vector<multipole_t> const &multipoles, size_t to)
240  {
241  if (!m_tree[to].is_receiver())
242  return;
243 
244  for (auto from : m_lists.get_list(interaction_lists::M2L)[to])
245  locals[to] += m_m2l(to, from) * multipoles[from];
246 
247  for (auto from : m_lists.get_list(interaction_lists::L2L)[to])
248  locals[to] += m_l2l(to, from) * locals[from];
249 
250  for (auto c : m_tree[to].get_children())
251  downward_pass_dfs_rec(locals, multipoles, c);
252  }
253 
256  void upward_pass_dfs(std::vector<multipole_t> &multipoles)
257  {
258  // determine cut level
259  size_t cut_level = get_dfs_cut_level();
260 
261  // dfs upward passes below cut level
262  int a = int(m_tree.level_begin(cut_level));
263  int b = int(m_tree.level_end(cut_level));
264 
265 #ifdef NIHU_FMM_PARALLEL
266 #pragma omp parallel for
267 #endif
268  for (int to = a; to < b; ++to)
269  upward_pass_dfs_rec(multipoles, to);
270 #ifdef NIHU_FMM_PARALLEL
271 #pragma omp barrier
272 #endif
273 
274  // bfs upward pass above cut level
275  upward_pass_bfs(multipoles, cut_level - 1);
276  }
277 
278  void downward_pass_dfs(std::vector<local_t> &locals,
279  std::vector<multipole_t> const &multipoles)
280  {
281  // determine cut level
282  size_t cut_level = get_dfs_cut_level();
283 
284  // bfs downward pass above cut level
285  size_t max_to_level = cut_level - 1;
286  downward_pass_bfs(locals, multipoles, max_to_level);
287 
288  // dfs downward pass below cut level
289  size_t a = m_tree.level_begin(cut_level);
290  size_t b = m_tree.level_end(cut_level);
291 
292 #ifdef NIHU_FMM_PARALLEL
293 #pragma omp parallel for
294 #endif
295  for (int to = int(a); to < int(b); ++to)
296  downward_pass_dfs_rec(locals, multipoles, to);
297  }
298 
299  void upward_pass_bfs(std::vector<multipole_t> &multipoles)
300  {
301  upward_pass_bfs(multipoles, m_tree.get_n_levels() - 2);
302  }
303 
304  void upward_pass_bfs(std::vector<multipole_t> &multipoles, size_t lowest_to_level)
305  {
306  // compute upward pass
307  for (size_t iLevel = lowest_to_level; iLevel >= 2; --iLevel)
308  {
309  m_timer.tic();
310 #ifdef NIHU_FMM_PARALLEL
311 #pragma omp parallel for
312 #endif
313  for (int to = int(m_tree.level_begin(iLevel)); to < int(m_tree.level_end(iLevel)); ++to)
314  {
315  for (auto from : m_tree[to].get_children())
316  {
317  if (!m_tree[from].is_source())
318  continue;
319  multipoles[to] += m_m2m(to, from) * multipoles[from];
320  }
321  }
322 #ifdef NIHU_FMM_PARALLEL
323 #pragma omp barrier
324 #endif
325  m_timer.toc(iLevel, fmm_timer::M2M);
326  }
327  }
328 
329  void downward_pass_bfs(std::vector<local_t> &locals,
330  std::vector<multipole_t> const &multipoles)
331  {
332  size_t max_to_level = m_tree.get_n_levels() - 1;
333  downward_pass_bfs(locals, multipoles, max_to_level);
334  }
335 
336  void downward_pass_bfs(std::vector<local_t> &locals,
337  std::vector<multipole_t> const &multipoles,
338  size_t max_to_level)
339  {
340  for (unsigned iLevel = 2; iLevel <= max_to_level; ++iLevel)
341  {
342  size_t a = m_tree.level_begin(iLevel);
343  size_t b = m_tree.level_end(iLevel);
344 
345  m_timer.tic();
346 #ifdef NIHU_FMM_PARALLEL
347 #pragma omp parallel for
348 #endif
349  for (int to = int(a); to < int(b); ++to)
350  for (size_t from : m_lists.get_list(interaction_lists::M2L)[to])
351  locals[to] += m_m2l(to, from) * multipoles[from];
352 #ifdef NIHU_FMM_PARALLEL
353 #pragma omp barrier
354 #endif
355  m_timer.toc(iLevel, fmm_timer::M2L);
356 
357  // no L2L needed at highest level
358  if (iLevel == 2)
359  continue;
360 
361  m_timer.tic();
362 #ifdef NIHU_FMM_PARALLEL
363 #pragma omp parallel for
364 #endif
365  for (int to = int(a); to < int(b); ++to)
366  {
367  if (!m_tree[to].is_receiver())
368  continue;
369  size_t from = m_tree[to].get_parent();
370  locals[to] += m_l2l(to, from) * locals[from];
371  }
372 #ifdef NIHU_FMM_PARALLEL
373 #pragma omp barrier
374 #endif
375  m_timer.toc(iLevel, fmm_timer::L2L);
376 
377  }
378  }
379 
380 
385  template <class Derived>
386  void reorder_response(Eigen::MatrixBase<Derived> &lhs) const
387  {
388  for (auto c : m_tree.get_leaf_rec_indices())
389  {
390  cluster_t const &clus = m_tree[c];
391  for (size_t i = 0; i < clus.get_n_rec_nodes(); ++i)
392  {
393  size_t ii = clus.get_rec_node_idx()[i];
394  lhs.segment(ii * num_dof_per_rec, num_dof_per_rec)
395  += m_lhs_segments[c].segment(i * num_dof_per_rec, num_dof_per_rec);
396  }
397  }
398  }
399 
403  template <class ExcType>
404  response_t operator *(ExcType const &rhs)
405  {
406 #ifdef NIHU_DEBUGGING
407  std::cout << "starting operator * " << std::endl;
408 #endif
409 
410  // compute P2P interactions
411  m_timer.tic();
412 #ifdef NIHU_DEBUGGING
413  std::cout << "Computing P2P " << std::endl;
414 #endif
415 
416 // response_t lhs = m_p2p.get_sparse_matrix() * rhs;
417  response_t lhs = m_p2p * rhs;
418 
419 #ifdef NIHU_DEBUGGING
420  std::cout << "Finished P2P " << std::endl;
421 #endif
422 
423  m_timer.toc(0, fmm_timer::P2P);
424 
425 #ifdef NIHU_DEBUGGING
426  std::cout << "Instantiating local & multipole " << std::endl;
427 #endif
428  // instantiate locals and multipoles
429  size_t n_clusters = m_tree.get_n_clusters();
430  std::vector<multipole_t> multipoles(n_clusters);
431  std::vector<local_t> locals(n_clusters);
432  for (size_t c = 0; c < n_clusters; ++c)
433  {
434  if (m_tree[c].get_level() < 2)
435  continue;
436  if (m_tree[c].is_source())
437  multipoles[c] = m_tree[c].zero_multipole();
438  if (m_tree[c].is_receiver())
439  locals[c] = m_tree[c].zero_local();
440  }
441 #ifdef NIHU_DEBUGGING
442  std::cout << "Instantiating local & multipole ready " << std::endl;
443 #endif
444 
445 #ifdef NIHU_DEBUGGING
446  std::cout << "Reordering excitation " << std::endl;
447 #endif
448 
449  // read reordered excitation into cluster data
450  reorder_excitation(rhs);
451 #ifdef NIHU_DEBUGGING
452  std::cout << "Reorder ready " << std::endl;
453 #endif
454 
455 
456 #ifdef NIHU_DEBUGGING
457  std::cout << "Computing P2L " << std::endl;
458 #endif
459 
460  // compute P2L interactions
461  m_timer.tic();
462  auto const &P2Llist = m_lists.get_list(interaction_lists::P2L);
463  for (auto to : m_tree.get_leaf_rec_indices())
464  for (auto from : P2Llist[to])
465  locals[to] += m_p2l(to, from) * m_rhs_segments[from];
466  m_timer.toc(0, fmm_timer::P2L);
467 
468 #ifdef NIHU_DEBUGGING
469  std::cout << "Computing P2L ready " << std::endl;
470 #endif
471 
472 #ifdef NIHU_DEBUGGING
473  std::cout << "Computing P2M " << std::endl;
474 #endif
475 
476  // compute P2M interactions
477  m_timer.tic();
478 
479 
480  auto const &src_idx = m_tree.get_leaf_src_indices();
481 #ifdef NIHU_FMM_PARALLEL
482 #pragma omp parallel for
483 #endif
484  for (int i = 0; i < int(src_idx.size()); ++i)
485  {
486  size_t to = src_idx[i];
487  multipoles[to] += m_p2m(to) * m_rhs_segments[to];
488  }
489 #ifdef NIHU_FMM_PARALLEL
490 #pragma omp barrier
491 #endif
492  m_timer.toc(0, fmm_timer::P2M);
493 #ifdef NIHU_DEBUGGING
494  std::cout << "Computing P2M ready " << std::endl;
495 #endif
496 
497 
498 #if defined NIHU_FMM_TRAVERSE_BFS
499 
500 #ifdef NIHU_DEBUGGING
501  std::cout << "Starting upward pass BFS " << std::endl;
502 #endif
503 
504  upward_pass_bfs(multipoles);
505 #ifdef NIHU_DEBUGGING
506  std::cout << "Upward pass BFS ready" << std::endl;
507 #endif
508 
509 #ifdef NIHU_DEBUGGING
510  std::cout << "Starting downward pass BFS " << std::endl;
511 #endif
512 
513  downward_pass_bfs(locals, multipoles);
514 #ifdef NIHU_DEBUGGING
515  std::cout << "Downward pass BFS ready" << std::endl;
516 #endif
517 
518 #elif defined NIHU_FMM_TRAVERSE_DFS
519  upward_pass_dfs(multipoles);
520  downward_pass_dfs(locals, multipoles);
521 #else
522 # error You need to explicitly define NIHU_FMM_TRAVERSE_BFS or NIHU_FMM_TRAVERSE_DFS tree traversing algorithm
523 #endif
524 
525  // compute L2P interactions
526 #ifdef NIHU_DEBUGGING
527  std::cout << "Computing L2P " << std::endl;
528 #endif
529 
530 
531  m_timer.tic();
532  auto const &rec_idx = m_tree.get_leaf_rec_indices();
533 #ifdef NIHU_FMM_PARALLEL
534 #pragma omp parallel for
535 #endif
536  for (int i = 0; i < int(rec_idx.size()); ++i)
537  {
538  size_t to = rec_idx[i];
539  m_lhs_segments[to] = m_l2p(to) * locals[to];
540  }
541 #ifdef NIHU_FMM_PARALLEL
542 #pragma omp barrier
543 #endif
544  m_timer.toc(0, fmm_timer::L2P);
545 #ifdef NIHU_DEBUGGING
546  std::cout << "Computing L2P ready" << std::endl;
547 #endif
548 
549  // compute M2P interactions
550 #ifdef NIHU_DEBUGGING
551  std::cout << "Computing M2P " << std::endl;
552 #endif
553 
554  m_timer.tic();
555  for (auto to : m_tree.get_leaf_rec_indices())
556  for (auto from : m_lists.get_list(interaction_lists::M2P)[to])
557  m_lhs_segments[to] += m_m2p(to, from) * multipoles[from];
558  m_timer.toc(0, fmm_timer::M2P);
559 #ifdef NIHU_DEBUGGING
560  std::cout << "Computing M2P ready" << std::endl;
561 #endif
562 
563  // distribute reordered response
564 #ifdef NIHU_DEBUGGING
565  std::cout << "Reordering response" << std::endl;
566 #endif
567 
568  reorder_response(lhs);
569 #ifdef NIHU_DEBUGGING
570  std::cout << "Reordering response ready " << std::endl;
571 #endif
572 
573  return lhs;
574  }
575 
576  fmm_timer const &get_timer() const
577  {
578  return m_timer;
579  }
580 
581  fmm_timer &get_timer()
582  {
583  return m_timer;
584  }
585 
588  Eigen::Matrix<scalar_t, Eigen::Dynamic, 1> get_diagonal() const
589  {
590  return m_p2p.get_sparse_matrix().diagonal();
591  }
592 
593 private:
594  P2P m_p2p;
595  P2M m_p2m;
596  P2L m_p2l;
597  M2P m_m2p;
598  L2P m_l2p;
599  M2M m_m2m;
600  L2L m_l2l;
601  M2L m_m2l;
602  cluster_tree_t const &m_tree;
603  interaction_lists const &m_lists;
604  fmm_timer m_timer;
605  std::vector<excitation_t> m_rhs_segments;
606  std::vector<response_t> m_lhs_segments;
607 
608  double m_cut_ratio;
609 };
610 
611 
623 template <class P2P, class P2M, class P2L, class M2P, class L2P,
624  class M2M, class L2L, class M2L, class Cluster>
625  fmm_matrix<P2P, P2M, P2L, M2P, L2P, M2M, L2L, M2L>
627  P2P &&p2p,
628  P2M &&p2m, P2L &&p2l, M2P &&m2p, L2P &&l2p,
629  M2M &&m2m, L2L &&l2l, M2L &&m2l,
630  cluster_tree<Cluster> const &tree,
631  interaction_lists const &lists
632  )
633 {
634  mexForcedPrintf("create_fmm_matrix from separate\n");
635 
637  std::forward<P2P>(p2p),
638  std::forward<P2M>(p2m),
639  std::forward<P2L>(p2l),
640  std::forward<M2P>(m2p),
641  std::forward<L2P>(l2p),
642  std::forward<M2M>(m2m),
643  std::forward<L2L>(l2l),
644  std::forward<M2L>(m2l),
645  tree,
646  lists);
647 }
648 
649 
650 
659 template <class Cluster, class ...CollOps>
661  fmm_operator_collection<CollOps...> const &collection,
662  cluster_tree<Cluster> const &tree,
663  interaction_lists const &lists
664  )
665 {
666  mexForcedPrintf("create_fmm_matrix from collection\n");
667 
668  return create_fmm_matrix(
669  collection.get(p2p_tag()),
670  collection.get(p2m_tag()),
671  collection.get(p2l_tag()),
672  collection.get(m2p_tag()),
673  collection.get(l2p_tag()),
674  collection.get(m2m_tag()),
675  collection.get(l2l_tag()),
676  collection.get(m2l_tag()),
677  tree,
678  lists);
679 }
680 
681 } // end of namespace fmm
682 } // end of namespace NiHu
683 
684 #endif /* FMM_MATRIX_HPP_INCLUDED */
NiHu::fmm::fmm_timer
class to store fmm timing data
Definition: fmm_timer.h:22
NiHu::fmm::op_tags::m2l
Definition: fmm_operator.hpp:22
NiHu::fmm::fmm_timer::M2L
@ M2L
index of M2L operation
Definition: fmm_timer.h:33
NiHu::fmm::fmm_timer::P2M
@ P2M
index of P2M operation
Definition: fmm_timer.h:35
NiHu::fmm::fmm_matrix::fmm_matrix
fmm_matrix(P2P &&p2p, P2M &&p2m, P2L &&p2l, M2P &&m2p, L2P &&l2p, M2M &&m2m, L2L &&l2l, M2L &&m2l, cluster_tree_t const &tree, interaction_lists const &lists)
constructor from operator instances
Definition: fmm_matrix.hpp:108
NiHu::fmm::op_tags::l2p
Definition: fmm_operator.hpp:26
NiHu::fmm::fmm_timer::L2L
@ L2L
index of L2L operation
Definition: fmm_timer.h:31
NiHu::fmm::cluster_tree::get_n_clusters
size_t get_n_clusters() const
return number of clusters
Definition: cluster_tree.hpp:282
NiHu::fmm::fmm_timer::M2M
@ M2M
index of M2M operation
Definition: fmm_timer.h:29
NiHu::fmm::fmm_matrix::num_dof_per_src
static const size_t num_dof_per_src
number of DOF for a source node in the mesh
Definition: fmm_matrix.hpp:93
NiHu::fmm::fmm_timer::P2L
@ P2L
index of P2L operation
Definition: fmm_timer.h:37
NiHu::fmm::fmm_matrix::upward_pass_dfs
void upward_pass_dfs(std::vector< multipole_t > &multipoles)
depth first search upward pass
Definition: fmm_matrix.hpp:256
NiHu::fmm::fmm_matrix::set_cut_ratio
void set_cut_ratio(double cut_ratio)
set the cut ratio
Definition: fmm_matrix.hpp:147
NiHu::fmm::fmm_timer::P2P
@ P2P
index of P2P operation
Definition: fmm_timer.h:43
NiHu::fmm::op_tags::p2l
Definition: fmm_operator.hpp:25
NiHu::fmm::op_tags::l2l
Definition: fmm_operator.hpp:21
NiHu::fmm::fmm_matrix::get_dfs_cut_level
size_t get_dfs_cut_level() const
determine cut level between bfs and dfs traverse sections
Definition: fmm_matrix.hpp:163
NiHu::fmm::fmm_matrix::num_dof_per_rec
static const size_t num_dof_per_rec
number of DOF for a receiver node in the mesh
Definition: fmm_matrix.hpp:95
NiHu::fmm::fmm_timer::toc
void toc(size_t level, int type)
stop timer at a given level and operation type
Definition: fmm_timer.h:79
NiHu::fmm::fmm_timer::M2P
@ M2P
index of M2P operation
Definition: fmm_timer.h:41
NiHu::fmm::interaction_lists::get_list
const list_t & get_list(size_t idx) const
return a selected list
Definition: lists.hpp:61
NiHu::fmm::fmm_matrix
Matrix representation of the FMM method.
Definition: fmm_matrix.hpp:69
NiHu::fmm::cluster_tree< cluster_t >
NiHu::fmm::op_tags::p2m
Definition: fmm_operator.hpp:24
NiHu::fmm::fmm_matrix::reorder_excitation
void reorder_excitation(Eigen::MatrixBase< RhsDerived > const &rhs)
cluster-continuous reordering of the excitation data
Definition: fmm_matrix.hpp:201
NiHu::fmm::op_tags::m2m
Definition: fmm_operator.hpp:20
cluster_tree.hpp
Implementation of class NiHu::fmm::cluster_tree.
NiHu::fmm::fmm_operator_collection::get
auto get(FmmTag tag) const
Retrieve operator from the collection.
Definition: fmm_operator_collection.hpp:96
NiHu::fmm::cluster_tree::get_n_levels
size_t get_n_levels() const
return number of levels
Definition: cluster_tree.hpp:253
NiHu::fmm::fmm_matrix::get_diagonal
Eigen::Matrix< scalar_t, Eigen::Dynamic, 1 > get_diagonal() const
return the diagonal of the matrix ins a single column vector
Definition: fmm_matrix.hpp:588
NiHu::fmm::chebyshev_cluster::multipole_t
base_t::multipole_t multipole_t
the multipole type
Definition: chebyshev_cluster.hpp:59
NiHu::fmm::chebyshev_cluster::local_t
base_t::local_t local_t
the local type
Definition: chebyshev_cluster.hpp:61
lists.hpp
Definition of class NiHu::fmm::interaction_lists.
NiHu::fmm::fmm_timer::L2P
@ L2P
index of L2P operation
Definition: fmm_timer.h:39
NiHu::fmm::cluster_tree::level_begin
size_t level_begin(size_t idx) const
Begin iterator to idx-th level clusters.
Definition: cluster_tree.hpp:264
NiHu::fmm::create_fmm_matrix
fmm_matrix< P2P, P2M, P2L, M2P, L2P, M2M, L2L, M2L > create_fmm_matrix(P2P &&p2p, P2M &&p2m, P2L &&p2l, M2P &&m2p, L2P &&l2p, M2M &&m2m, L2L &&l2l, M2L &&m2l, cluster_tree< Cluster > const &tree, interaction_lists const &lists)
factory function to create an fmm_matrix object
Definition: fmm_matrix.hpp:626
NiHu::fmm::cluster_tree::level_end
size_t level_end(size_t idx) const
End iterator to idx-th level clusters.
Definition: cluster_tree.hpp:274
fmm_operator_collection.hpp
Implementation of NiHu::fmm::fmm_operator_collection.
NiHu::fmm::op_tags::p2p
Definition: fmm_operator.hpp:29
NiHu::fmm::fmm_matrix::operator*
response_t operator*(ExcType const &rhs)
matrix vector multiplication
Definition: fmm_matrix.hpp:404
NiHu::fmm::fmm_matrix::rows
size_t rows() const
return number of rows of the matrix
Definition: fmm_matrix.hpp:184
NiHu::fmm::fmm_matrix::downward_pass_dfs_rec
void downward_pass_dfs_rec(std::vector< local_t > &locals, std::vector< multipole_t > const &multipoles, size_t to)
recursive depth first search single thread downward pass
Definition: fmm_matrix.hpp:238
NiHu::fmm::fmm_timer::tic
timer_t::time_point_t tic(void)
start timer
Definition: fmm_timer.h:69
fmm_timer.h
Interface of the class NiHu::fmm::fmm_timer.
NiHu::fmm::fmm_matrix::cols
size_t cols() const
return number of columns of the matrix
Definition: fmm_matrix.hpp:191
NiHu::fmm::fmm_matrix::reorder_response
void reorder_response(Eigen::MatrixBase< Derived > &lhs) const
cluster-continuous inverse-reordering of the response data
Definition: fmm_matrix.hpp:386
NiHu::fmm::fmm_matrix::get_cut_ratio
double get_cut_ratio() const
return the cut ratio
Definition: fmm_matrix.hpp:156
NiHu::fmm::p2p
Definition: p2p.hpp:20
NiHu::fmm::interaction_lists
class storing the different interaction lists of a tree
Definition: lists.hpp:22
matrix_traits.hpp
compile time properties of matrices
NiHu::fmm::op_tags::m2p
Definition: fmm_operator.hpp:27
NiHu::fmm::fmm_operator_collection
Class representing a collection of FMM operators.
Definition: fmm_operator_collection.hpp:22
NiHu::fmm::fmm_matrix::upward_pass_dfs_rec
void upward_pass_dfs_rec(std::vector< multipole_t > &multipoles, size_t root)
recursive depth first search single thread upward pass
Definition: fmm_matrix.hpp:220