NiHu  2.0
black_box_fmm.hpp
Go to the documentation of this file.
1 
7 #ifndef NIHU_BLACK_BOX_FMM_HPP_INCLUDED
8 #define NIHU_BLACK_BOX_FMM_HPP_INCLUDED
9 
10 #include "chebyshev_cluster.hpp"
11 #include "cluster_tree.hpp"
12 #include "fmm_operator.hpp"
13 #include "kron_identity.hpp"
14 #include "m2l_indices.hpp"
15 #include "nd_cheb.hpp"
16 #include "p2p.hpp"
17 #include "fmm_operator.hpp"
18 
21 #include "util/matrix_traits.hpp"
22 
23 #include <cstddef>
24 #include <type_traits>
25 
26 
27 namespace NiHu
28 {
29 namespace fmm
30 {
31 
32 template <class Kernel>
34 {
36  typedef Kernel kernel_00_t;
38  typedef Kernel kernel_ny_t;
40  typedef Kernel kernel_nx_t;
41  static int const nx = 0;
42  static int const ny = 0;
43 };
44 
45 template <class DistanceDependentKernel, int Nx, int Ny>
46 struct kernel_derivative_traits<normal_derivative_kernel<DistanceDependentKernel, Nx, Ny> >
47 {
51  static int const nx = Nx;
52  static int const ny = Ny;
53 };
54 
55 
60 template <class Kernel>
62 {
63 public:
65  typedef Kernel kernel_t;
66 
68 
69  typedef typename derivative_traits_t::kernel_00_t kernel_00_t;
70  typedef typename derivative_traits_t::kernel_nx_t kernel_nx_t;
71  typedef typename derivative_traits_t::kernel_ny_t kernel_ny_t;
72  static int const Nx = derivative_traits_t::nx;
73  static int const Ny = derivative_traits_t::ny;
74 
76  static size_t const space_dimension = kernel_00_t::space_t::dimension;
77 
80 
82  typedef typename scalar<typename kernel_00_t::result_t>::type kernel_scalar_t;
83 
86 
87 
89  class m2m
90  : public fmm_operator<m2m_tag>
91  {
92  public:
94 
95  typedef kron_identity<
96  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>,
98  > result_t;
99 
100  static size_t unique_idx(cluster_t const &to, cluster_t const &from)
101  {
102  return cluster_t::bounding_box_t::dist2idx(
103  from.get_bounding_box().get_center(),
104  to.get_bounding_box().get_center());
105  }
106 
107  result_t operator()(cluster_t const &to, cluster_t const &from) const
108  {
109  return result_t(chebanterp<double, space_dimension>(
110  to.get_chebyshev_order(),
111  to.get_bounding_box(),
112  from.get_chebyshev_nodes()));
113  }
114  };
115 
116 
118  class l2l
119  : public fmm_operator<l2l_tag>
120  {
121  public:
123 
124  typedef kron_identity <
125  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>,
127  > result_t;
128 
129  static size_t unique_idx(cluster_t const &to, cluster_t const &from)
130  {
131  return cluster_t::bounding_box_t::dist2idx(
132  to.get_bounding_box().get_center(),
133  from.get_bounding_box().get_center());
134  }
135 
136  result_t operator()(cluster_t const &to, cluster_t const &from) const
137  {
138  return result_t(chebanterp<double, space_dimension>(
139  from.get_chebyshev_order(),
140  from.get_bounding_box(),
141  to.get_chebyshev_nodes()).transpose());
142  }
143  };
144 
145 
147  class m2l
148  : public fmm_operator<m2l_tag>
149  {
150  public:
152 
153  typedef Eigen::Matrix<kernel_scalar_t, Eigen::Dynamic, Eigen::Dynamic> result_t;
154 
155  m2l(kernel_t const &kernel)
156  : m_kernel_00(kernel)
157  {
158  }
159 
160  static size_t unique_idx(cluster_t const &to, cluster_t const &from)
161  {
162  return m2l_indices<space_dimension>::eval(to.get_bounding_box(), from.get_bounding_box());
163  }
164 
165  result_t operator()(cluster_t const &to, cluster_t const &from) const
166  {
167  size_t N = to.get_chebyshev_nodes().cols();
168  size_t M = from.get_chebyshev_nodes().cols();
169  result_t res(M * field_dimension, N * field_dimension);
170  for (size_t i = 0; i < N; ++i)
171  for (size_t j = 0; j < M; ++j)
172  res.block(i * field_dimension, j * field_dimension, field_dimension, field_dimension) = m_kernel_00(
173  typename kernel_t::space_t::location_t(to.get_chebyshev_nodes().col(i)),
174  typename kernel_t::space_t::location_t(from.get_chebyshev_nodes().col(j)))
175  * Eigen::Matrix<kernel_scalar_t, field_dimension, field_dimension>::Identity();
176  return res;
177  }
178 
179  private:
180  kernel_00_t m_kernel_00;
181  };
182 
183 
185  class p2m
186  : public fmm_operator<p2m_tag>
187  {
188  public:
189  typedef cluster_t test_input_t;
190 
191  typedef typename std::conditional<
192  Ny == 0,
195  >::type trial_input_t;
196 
197  typedef Eigen::Matrix<double, Eigen::Dynamic, field_dimension> result_t;
198 
199  size_t rows(test_input_t const &cluster) const
200  {
201  return cluster.get_data_size();
202  }
203 
204  size_t cols(trial_input_t const &) const
205  {
206  return field_dimension;
207  }
208 
209  result_t operator()(test_input_t const &to, trial_input_t const &from) const
210  {
211  return eval(to, from, std::integral_constant<int, Ny>());
212  }
213 
214  private:
215  result_t eval(test_input_t const &to, trial_input_t const &from, std::integral_constant<int, 0>) const
216  {
217  Eigen::Matrix<double, Eigen::Dynamic, 1> res0 = chebanterp<double, space_dimension>(
218  to.get_chebyshev_order(),
219  to.get_bounding_box(), from.get_x());
220  result_t res(rows(to), cols(from));
221  for (Eigen::Index i = 0; i < res0.rows(); ++i)
222  for (Eigen::Index j = 0; j < res0.cols(); ++j)
224  res0(i, j) * Eigen::Matrix<double, field_dimension, field_dimension>::Identity();
225  return res;
226  }
227 
228  result_t eval(test_input_t const &to, trial_input_t const &from, std::integral_constant<int, 1>) const
229  {
230  Eigen::Matrix<double, Eigen::Dynamic, 1> res0 = chebanterp_dny<double, space_dimension>(
231  to.get_chebyshev_order(),
232  to.get_bounding_box(),
233  from.get_x(),
234  from.get_unit_normal());
235  result_t res(rows(to), cols(from));
236  for (Eigen::Index i = 0; i < res0.rows(); ++i)
237  for (Eigen::Index j = 0; j < res0.cols(); ++j)
239  res0(i, j) * Eigen::Matrix<double, field_dimension, field_dimension>::Identity();
240  return res;
241  }
242  };
243 
244 
246  class l2p
247  : public fmm_operator<l2p_tag>
248  {
249  public:
250  typedef typename std::conditional<
251  Nx == 0,
254  >::type test_input_t;
255 
256  typedef cluster_t trial_input_t;
257 
258  typedef Eigen::Matrix<double, field_dimension, Eigen::Dynamic> result_t;
259 
260  size_t rows(test_input_t const &) const
261  {
262  return field_dimension;
263  }
264 
265  size_t cols(trial_input_t const &cluster) const
266  {
267  return cluster.get_data_size();
268  }
269 
270  result_t operator()(test_input_t const &to, trial_input_t const &from) const
271  {
272  return eval(to, from, std::integral_constant<int, Nx>());
273  }
274 
275  private:
276  result_t eval(test_input_t const &to, trial_input_t const &from, std::integral_constant<int, 0>) const
277  {
278  Eigen::Matrix<double, 1, Eigen::Dynamic> res0 = chebanterp<double, space_dimension>(
279  from.get_chebyshev_order(),
280  from.get_bounding_box(),
281  to.get_x()).transpose();
282 
283  result_t res(rows(to), cols(from));
284  for (Eigen::Index i = 0; i < res0.rows(); ++i)
285  for (Eigen::Index j = 0; j < res0.cols(); ++j)
287  res0(i, j) * Eigen::Matrix<double, field_dimension, field_dimension>::Identity();
288  return res;
289  }
290 
291  result_t eval(test_input_t const &to, trial_input_t const &from, std::integral_constant<int, 1>) const
292  {
293  Eigen::Matrix<double, 1, Eigen::Dynamic> res0 = chebanterp_dny<double, space_dimension>(
294  from.get_chebyshev_order(),
295  from.get_bounding_box(),
296  to.get_x(),
297  to.get_unit_normal()
298  ).transpose();
299 
300  result_t res(rows(to), cols(from));
301  for (Eigen::Index i = 0; i < res0.rows(); ++i)
302  for (Eigen::Index j = 0; j < res0.cols(); ++j)
304  res0(i, j) * Eigen::Matrix<double, field_dimension, field_dimension>::Identity();
305  return res;
306  }
307  };
308 
309 
311  class p2l
312  : public fmm_operator<p2l_tag>
313  {
314  public:
315  typedef cluster_t test_input_t;
316  typedef typename kernel_ny_t::trial_input_t trial_input_t;
317  typedef Eigen::Matrix<kernel_scalar_t, Eigen::Dynamic, field_dimension> result_t;
318 
319  p2l(kernel_t const &kernel)
320  : m_kernel_ny(kernel)
321  {
322  }
323 
324  size_t rows(test_input_t const &cluster) const
325  {
326  return cluster.get_data_size();
327  }
328 
329  size_t cols(trial_input_t const &) const
330  {
331  return field_dimension;
332  }
333 
334  result_t operator()(test_input_t const &to, trial_input_t const &from) const
335  {
336  return eval(to, from, std::integral_constant<int, Ny>());
337  }
338 
339  private:
340  result_t eval(test_input_t const &to, trial_input_t const &from, std::integral_constant<int, 0>) const
341  {
342  size_t n = to.get_chebyshev_nodes().cols();
343  result_t res(rows(to), cols(from));
344  for (size_t i = 0; i < n; ++i)
345  res.block(i * field_dimension, 0, field_dimension, field_dimension) =
346  m_kernel_ny(to.get_chebyshev_nodes().col(i), from.get_x()) *
347  Eigen::Matrix<kernel_scalar_t, field_dimension, field_dimension>::Identity();
348  return res;
349  }
350 
351  result_t eval(test_input_t const &to, trial_input_t const &from, std::integral_constant<int, 1>) const
352  {
353  size_t n = to.get_chebyshev_nodes().cols();
354  result_t res(rows(to), cols(from));
355  for (size_t i = 0; i < n; ++i)
356  res.block(i * field_dimension, 0, field_dimension, field_dimension) =
357  m_kernel_ny(to.get_chebyshev_nodes().col(i), from.get_x(), from.get_unit_normal()) *
358  Eigen::Matrix<kernel_scalar_t, field_dimension, field_dimension>::Identity();
359  return res;
360  }
361 
362  kernel_ny_t m_kernel_ny;
363  };
364 
365 
367  class m2p
368  : public fmm_operator<m2p_tag>
369  {
370  public:
371  typedef cluster_t trial_input_t;
372  typedef typename kernel_t::test_input_t test_input_t;
373  typedef Eigen::Matrix<kernel_scalar_t, field_dimension, Eigen::Dynamic> result_t;
374 
375  m2p(kernel_t const &kernel)
376  : m_kernel_nx(kernel)
377  {
378  }
379 
380  size_t rows(test_input_t const &) const
381  {
382  return field_dimension;
383  }
384 
385  size_t cols(trial_input_t const &cluster) const
386  {
387  return cluster.get_data_size();
388  }
389 
390  result_t operator()(test_input_t const &to, trial_input_t const &from) const
391  {
393  size_t n = from.get_chebyshev_nodes().cols();
394  result_t res(rows(to), cols(from));
395  for (size_t i = 0; i < n; ++i)
396  res.block(0, i * field_dimension, field_dimension, field_dimension) =
397  m_kernel_nx(to.get_x(), from.get_chebyshev_nodes().col(i)) *
398  Eigen::Matrix<kernel_scalar_t, field_dimension, field_dimension>::Identity();
399  return res;
400  }
401 
403 
404  private:
405  kernel_nx_t m_kernel_nx;
406  };
407 
408 
412  black_box_fmm(kernel_t const &kernel)
413  : m_kernel(kernel)
414  {
415  }
416 
417 
421  auto create_p2p() const
422  {
423  return p2p<kernel_t>(m_kernel);
424  }
425 
429  auto create_p2m() const
430  {
431  return p2m();
432  }
433 
437  p2l create_p2l() const
438  {
439  return p2l(m_kernel);
440  }
441 
445  auto create_m2p() const
446  {
447  return m2p(m_kernel);
448  }
449 
453  auto create_l2p() const
454  {
455  return l2p();
456  }
457 
461  m2m create_m2m() const
462  {
463  return m2m();
464  }
465 
469  l2l create_l2l() const
470  {
471  return l2l();
472  }
473 
477  m2l create_m2l() const
478  {
479  return m2l(m_kernel);
480  }
481 
482 private:
483  kernel_t m_kernel;
484 };
485 
486 template <class Kernel>
487 black_box_fmm<Kernel> create_black_box_fmm(Kernel const &kernel)
488 {
489  return black_box_fmm<Kernel>(kernel);
490 }
491 
492 } // end of namespace fmm
493 } // end of namespace NiHu
494 
495 #endif /* NIHU_BLACK_BOX_FMM_HPP_INCLUDED */
NiHu::fmm::black_box_fmm::l2l
the l2l operator of the black box fmm
Definition: black_box_fmm.hpp:118
NiHu::fmm::black_box_fmm::kernel_t
Kernel kernel_t
template parameter as nested type
Definition: black_box_fmm.hpp:65
NiHu::fmm::kernel_derivative_traits::kernel_00_t
Kernel kernel_00_t
Kernel type without normal derivation.
Definition: black_box_fmm.hpp:36
fmm_operator.hpp
FMM operator types and tags.
NiHu::fmm::black_box_fmm::create_p2m
auto create_p2m() const
return the p2m operator instance
Definition: black_box_fmm.hpp:429
NiHu::fmm::black_box_fmm
Black box FMM for a smooth kernel.
Definition: black_box_fmm.hpp:61
NiHu::fmm::black_box_fmm::create_l2p
auto create_l2p() const
return the l2p operator instance
Definition: black_box_fmm.hpp:453
NiHu::fmm::chebyshev_cluster::get_chebyshev_order
size_t get_chebyshev_order() const
return the Chebyshev order
Definition: chebyshev_cluster.hpp:104
kron_identity.hpp
Kronecker product of a matrix by an Identity matrix.
NiHu::fmm::chebyshev_cluster
Cluster class of the Black Box FMM.
Definition: chebyshev_cluster.hpp:28
NiHu::fmm::black_box_fmm::black_box_fmm
black_box_fmm(kernel_t const &kernel)
constructor
Definition: black_box_fmm.hpp:412
NiHu::fmm::black_box_fmm::kernel_scalar_t
scalar< typename kernel_00_t::result_t >::type kernel_scalar_t
the kernel result's scalar type
Definition: black_box_fmm.hpp:82
NiHu::exponential_covariance_kernel
Definition: covariance_kernel.hpp:42
NiHu::location_normal_jacobian_input
a class representing a normal + Jacobian input
Definition: location_normal.hpp:79
NiHu::fmm::black_box_fmm::create_m2p
auto create_m2p() const
return the m2p operator instance
Definition: black_box_fmm.hpp:445
p2p.hpp
P2P operator.
m2l_indices.hpp
Implementation of class template Nihu::fmm::m2l_indices.
nd_cheb.hpp
n-dimensional Chebyshev polynomial
NiHu::fmm::black_box_fmm::create_m2l
m2l create_m2l() const
return the m2l operator instance
Definition: black_box_fmm.hpp:477
NiHu::fmm::black_box_fmm::space_dimension
static const size_t space_dimension
the space's dimension
Definition: black_box_fmm.hpp:76
cluster_tree.hpp
Implementation of class NiHu::fmm::cluster_tree.
NiHu::num_rows
metafunction returning the number of compile time rows
Definition: matrix_traits.hpp:16
NiHu::fmm::kernel_derivative_traits::kernel_ny_t
Kernel kernel_ny_t
Kernel with normal derivative in @i y.
Definition: black_box_fmm.hpp:38
NiHu::fmm::black_box_fmm::p2m
the p2m operator of the black box fmm
Definition: black_box_fmm.hpp:185
normal_derivative_kernel.hpp
Class NiHu::normal_derivative_kernel.
NiHu::fmm::chebyshev_cluster::get_chebyshev_nodes
const cheb_nodes_t & get_chebyshev_nodes() const
return the Chebyshev nodes
Definition: chebyshev_cluster.hpp:97
NiHu::fmm::fmm_operator
Operator defining its tag type.
Definition: fmm_operator.hpp:85
NiHu::fmm::kernel_derivative_traits::kernel_nx_t
Kernel kernel_nx_t
Kernel with normal derivative in @i x.
Definition: black_box_fmm.hpp:40
chebyshev_cluster.hpp
Implementation of class chebyshev_cluster.
NiHu::fmm::kron_identity
Definition: kron_identity.hpp:21
NiHu::fmm::black_box_fmm::create_p2p
auto create_p2p() const
return the p2p operator instance
Definition: black_box_fmm.hpp:421
location_normal.hpp
implementation of location and normal kernel inputs
NiHu::normal_derivative_kernel
Normal derivative of a distance dependent kernel.
Definition: normal_derivative_kernel.hpp:26
NiHu::fmm::black_box_fmm::p2l
the p2l operator of the black box fmm
Definition: black_box_fmm.hpp:311
NiHu::fmm::chebyshev_cluster::get_data_size
size_t get_data_size() const
return the number of elements in the multipole coefficients
Definition: chebyshev_cluster.hpp:76
NiHu::fmm::black_box_fmm::field_dimension
static const size_t field_dimension
the field's dimension
Definition: black_box_fmm.hpp:79
NiHu::fmm::black_box_fmm::m2l
the m2l operator of the black box fmm
Definition: black_box_fmm.hpp:147
NiHu::fmm::m2l_indices
Class assigning indices to M2L distances.
Definition: m2l_indices.hpp:21
NiHu::fmm::black_box_fmm::m2p::operator()
result_t operator()(test_input_t const &to, trial_input_t const &from) const
Definition: black_box_fmm.hpp:390
NiHu::fmm::black_box_fmm::m2p
the m2p operator of the black box fmm
Definition: black_box_fmm.hpp:367
NiHu::fmm::p2p
Definition: p2p.hpp:20
NiHu::fmm::black_box_fmm::m2m
the m2m operator of the black box fmm
Definition: black_box_fmm.hpp:89
NiHu::location_input
a class representing a simple location
Definition: location_normal.hpp:37
matrix_traits.hpp
compile time properties of matrices
NiHu::fmm::kernel_derivative_traits
Definition: black_box_fmm.hpp:33
NiHu::fmm::black_box_fmm::create_l2l
l2l create_l2l() const
return the l2l operator instance
Definition: black_box_fmm.hpp:469
NiHu::fmm::black_box_fmm::cluster_t
chebyshev_cluster< space_dimension, kernel_scalar_t, field_dimension > cluster_t
the cluster type
Definition: black_box_fmm.hpp:85
NiHu::fmm::black_box_fmm::create_p2l
p2l create_p2l() const
return the p2l operator instance
Definition: black_box_fmm.hpp:437
NiHu::fmm::black_box_fmm::l2p
the l2p operator of the black box fmm
Definition: black_box_fmm.hpp:246
NiHu::fmm::black_box_fmm::create_m2m
m2m create_m2m() const
return the m2m operator instance
Definition: black_box_fmm.hpp:461