8 #include <boost/math/special_functions/binomial.hpp>
17 m_expansion_length = L;
22 return m_expansion_length;
25 size_t laplace_3d_cluster::data_size()
const
27 return (m_expansion_length + 1) * (m_expansion_length + 1);
43 laplace_3d_cluster::linear_index(Eigen::Index n, Eigen::Index m)
const
45 if (n < 0 || m > n || -m > n)
46 throw std::logic_error(
"Invalid index in hat matrix");
50 laplace_3d_fmm::m2l::result_t
53 using boost::math::binomial_coefficient;
55 result_t res(to.data_size(), from.data_size());
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);
63 std::complex<double>
const J(0.0, 1.0);
65 for (
size_t j = 0; j <= to.get_expansion_length(); ++j)
67 for (
int k = -
int(j); k <= int(j); ++k)
69 Eigen::Index row = to.linear_index(j, k);
71 for (
size_t n = 0; n <= from.get_expansion_length(); ++n)
73 for (
int m = -
int(n); m <= int(n); ++m)
75 Eigen::Index col = from.linear_index(n, m);
78 std::pow(
J, std::abs(k - m) - std::abs(k) - std::abs(m)) *
79 Y(j + n, m - k, theta, phi) *
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)));
92 laplace_3d_fmm::m2m::result_t
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());
100 x_t x = from.get_bounding_box().get_center() - to.get_bounding_box().get_center();
104 double phi = std::atan2(x(1), x(0));
105 double theta = std::acos(x(2) / r);
107 int p = int(to.get_expansion_length());
109 for (
int j = 0; j <= p; ++j)
111 for (
int k = -j; k <= +j; ++k)
113 Eigen::Index row_idx = to.linear_index(j, k);
115 for (
int n = 0; n <= j; ++n)
117 for (
int m = -n; m <= +n; ++m)
119 if (n - m > j - k || m + n > j + k)
121 Eigen::Index col_idx = from.linear_index(j - n, k - m);
123 res(row_idx, col_idx) =
124 std::pow(1i, std::abs(k) - std::abs(m) - std::abs(k - m)) *
126 Y(n, -m, theta, phi) *
128 binomial_coefficient<double>(j - k, n - m) *
129 binomial_coefficient<double>(j + k, n + m)
139 laplace_3d_fmm::l2l::result_t
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());
147 x_t x = from.get_bounding_box().get_center() - to.get_bounding_box().get_center();
150 double phi = std::atan2(x(1), x(0));
151 double theta = std::acos(x(2) / r);
153 int p = int(to.get_expansion_length());
155 for (
int j = 0; j <= p; ++j)
157 for (
int k = -j; k <= +j; ++k)
159 Eigen::Index row_idx = to.linear_index(j, k);
160 for (
int n = j; n <= p; ++n)
162 for (
int m = -n; m <= +n; ++m)
164 if (n - m < j - k || n + m < j + k)
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) *
171 std::pow(-1, n + j) *
173 binomial_coefficient<double>(n - m, j - k) *
174 binomial_coefficient<double>(n + m, j + k)