NiHu  2.0
laplace_3d_fmm.cpp
Go to the documentation of this file.
1 
7 #include "laplace_3d_fmm.hpp"
8 #include <boost/math/special_functions/binomial.hpp>
9 
10 namespace NiHu
11 {
12 namespace fmm
13 {
14 
16 {
17  m_expansion_length = L;
18 }
19 
21 {
22  return m_expansion_length;
23 }
24 
25 size_t laplace_3d_cluster::data_size() const
26 {
27  return (m_expansion_length + 1) * (m_expansion_length + 1);
28 }
29 
32 {
33  return multipole_t(data_size(), 1);
34 }
35 
38 {
39  return local_t(data_size(), 1);
40 }
41 
42 Eigen::Index
43 laplace_3d_cluster::linear_index(Eigen::Index n, Eigen::Index m) const
44 {
45  if (n < 0 || m > n || -m > n)
46  throw std::logic_error("Invalid index in hat matrix");
47  return n * n + n + m;
48 }
49 
50 laplace_3d_fmm::m2l::result_t
51 laplace_3d_fmm::m2l::operator()(cluster_t to, cluster_t from) const
52 {
53  using boost::math::binomial_coefficient;
54 
55  result_t res(to.data_size(), from.data_size());
56 
58  x_t x = from.get_bounding_box().get_center() - to.get_bounding_box().get_center();
59  double rho = x.norm();
60  double phi = std::atan2(x(1), x(0));
61  double theta = std::acos(x(2) / rho);
62 
63  std::complex<double> const J(0.0, 1.0);
64 
65  for (size_t j = 0; j <= to.get_expansion_length(); ++j)
66  {
67  for (int k = -int(j); k <= int(j); ++k)
68  {
69  Eigen::Index row = to.linear_index(j, k);
70 
71  for (size_t n = 0; n <= from.get_expansion_length(); ++n)
72  {
73  for (int m = -int(n); m <= int(n); ++m)
74  {
75  Eigen::Index col = from.linear_index(n, m);
76 
77  res(row, col) =
78  std::pow(J, std::abs(k - m) - std::abs(k) - std::abs(m)) *
79  Y(j + n, m - k, theta, phi) *
80  std::pow(-1, n) *
81  std::pow(rho, -int(j + n + 1)) *
82  std::sqrt(binomial_coefficient<double>(unsigned(j + k + n - m), unsigned(j + k))) *
83  std::sqrt(binomial_coefficient<double>(unsigned(n + m + j - k), unsigned(n + m)));
84  }
85  }
86  }
87  }
88 
89  return res;
90 }
91 
92 laplace_3d_fmm::m2m::result_t
93 laplace_3d_fmm::m2m::operator()(cluster_t to, cluster_t from) const
94 {
95  using namespace std::complex_literals;
96  using boost::math::binomial_coefficient;
97  result_t res = result_t::Zero(to.data_size(), from.data_size());
98 
100  x_t x = from.get_bounding_box().get_center() - to.get_bounding_box().get_center();
101 
102 
103  double r = x.norm();
104  double phi = std::atan2(x(1), x(0));
105  double theta = std::acos(x(2) / r);
106 
107  int p = int(to.get_expansion_length());
108 
109  for (int j = 0; j <= p; ++j)
110  {
111  for (int k = -j; k <= +j; ++k)
112  {
113  Eigen::Index row_idx = to.linear_index(j, k);
114 
115  for (int n = 0; n <= j; ++n)
116  {
117  for (int m = -n; m <= +n; ++m)
118  {
119  if (n - m > j - k || m + n > j + k)
120  continue;
121  Eigen::Index col_idx = from.linear_index(j - n, k - m);
122 
123  res(row_idx, col_idx) =
124  std::pow(1i, std::abs(k) - std::abs(m) - std::abs(k - m)) *
125  std::pow(r, n) *
126  Y(n, -m, theta, phi) *
127  std::sqrt(
128  binomial_coefficient<double>(j - k, n - m) *
129  binomial_coefficient<double>(j + k, n + m)
130  );
131  }
132  }
133  }
134  }
135 
136  return res;
137 }
138 
139 laplace_3d_fmm::l2l::result_t
140 laplace_3d_fmm::l2l::operator()(cluster_t to, cluster_t from) const
141 {
142  using namespace std::complex_literals;
143  using boost::math::binomial_coefficient;
144  result_t res = result_t::Zero(to.data_size(), from.data_size());
145 
147  x_t x = from.get_bounding_box().get_center() - to.get_bounding_box().get_center();
148 
149  double r = x.norm();
150  double phi = std::atan2(x(1), x(0));
151  double theta = std::acos(x(2) / r);
152 
153  int p = int(to.get_expansion_length());
154 
155  for (int j = 0; j <= p; ++j)
156  {
157  for (int k = -j; k <= +j; ++k)
158  {
159  Eigen::Index row_idx = to.linear_index(j, k);
160  for (int n = j; n <= p; ++n)
161  {
162  for (int m = -n; m <= +n; ++m)
163  {
164  if (n - m < j - k || n + m < j + k)
165  continue;
166  Eigen::Index col_idx = from.linear_index(n, m);
167  res(row_idx, col_idx) =
168  std::pow(1.i, std::abs(m) - std::abs(m - k) - std::abs(k)) *
169  Y(n - j, m - k, theta, phi) *
170  std::pow(r, n - j) *
171  std::pow(-1, n + j) *
172  std::sqrt(
173  binomial_coefficient<double>(n - m, j - k) *
174  binomial_coefficient<double>(n + m, j + k)
175  );
176  }
177  }
178  }
179  }
180 
181  return res;
182 }
183 
184 laplace_3d_fmm::m2m
186 {
187  return m2m();
188 }
189 
192 {
193  return l2l();
194 }
195 
198 {
199  return m2l();
200 }
201 
202 
203 } // end of namespace fmm
204 } // namespace NiHu
NiHu::fmm::laplace_3d_fmm::m2l
M2L operator of the Laplace 3D FMM.
Definition: laplace_3d_fmm.hpp:400
NiHu::bessel::J
T J(T const &z)
Bessel function J_nu(z)
Definition: math_functions.hpp:223
NiHu::fmm::chebyshev_cluster
Cluster class of the Black Box FMM.
Definition: chebyshev_cluster.hpp:28
NiHu::fmm::laplace_3d_fmm::create_l2l
l2l create_l2l() const
return an instance of the L2L operator
Definition: laplace_3d_fmm.cpp:191
NiHu::fmm::laplace_3d_cluster::local_t
base_t::local_t local_t
the local type
Definition: laplace_3d_fmm.hpp:58
NiHu::fmm::laplace_3d_cluster::get_expansion_length
size_t get_expansion_length() const
get the expansion length
Definition: laplace_3d_fmm.cpp:20
NiHu::fmm::bounding_box< dimension, double >::location_t
Eigen::Matrix< scalar_t, dimension, 1 > location_t
the location type in the bounding box
Definition: bounding_box.hpp:38
NiHu::fmm::laplace_3d_cluster::set_expansion_length
void set_expansion_length(size_t L)
set the expansion length
Definition: laplace_3d_fmm.cpp:15
NiHu::fmm::laplace_3d_fmm::create_m2m
m2m create_m2m() const
return an instance of the M2M operator
Definition: laplace_3d_fmm.cpp:185
NiHu::fmm::laplace_3d_fmm::l2l
L2L operator of the Laplace 3D FMM.
Definition: laplace_3d_fmm.hpp:387
NiHu::fmm::laplace_3d_fmm::m2m
M2M operator of the Laplace 3D FMM.
Definition: laplace_3d_fmm.hpp:374
NiHu::fmm::laplace_3d_cluster::zero_local
local_t zero_local() const
return a cleared local contribution
Definition: laplace_3d_fmm.cpp:37
NiHu::fmm::laplace_3d_cluster::zero_multipole
multipole_t zero_multipole() const
return a cleared multipole contribution
Definition: laplace_3d_fmm.cpp:31
laplace_3d_fmm.hpp
Implementation of the FMM method for the 3D Laplace equation.
NiHu::fmm::laplace_3d_fmm::create_m2l
m2l create_m2l() const
return an instance of the M2L operator
Definition: laplace_3d_fmm.cpp:197
NiHu::bessel::Y
std::complex< double > Y(std::complex< double > const &z)
Bessel function Y_nu(z)
Definition: math_functions.hpp:315
NiHu::fmm::laplace_3d_cluster::multipole_t
base_t::multipole_t multipole_t
the multipole type
Definition: laplace_3d_fmm.hpp:56