Loading [MathJax]/extensions/tex2jax.js
NiHu  2.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
unit_sphere_interpolator.cpp
Go to the documentation of this file.
1 
8 
9 #include <boost/math/special_functions/legendre.hpp>
10 
11 namespace NiHu
12 {
13 namespace fmm
14 {
15 
16 interpolator::interpolator(unit_sphere const &Sfrom, unit_sphere const &Sto)
17  : m_Lfrom(Sfrom.get_P())
18  , m_Lto(Sto.get_P())
19  , m_Phi(cmatrix_t::Zero(m_Lfrom, 2 * m_Lfrom))
20  , m_Q(cmatrix_t::Zero(m_Lto, 2 * m_Lto))
21  , m_res(cvector_t::Zero(m_Lto * 2 * m_Lto, 1))
22 {
23  // plan dft-s
24  cmatrix_t a(m_Lfrom, 2 * m_Lfrom), afft(m_Lfrom, 2 * m_Lfrom);
25  int n[1];
26  n[0] = int(2 * m_Lfrom);
27  this->dft_plan = fftw_plan_many_dft(1, n, int(m_Lfrom),
28  (fftw_complex *)a.data(), nullptr, int(m_Lfrom), 1,
29  (fftw_complex *)afft.data(), nullptr, int(m_Lfrom), 1,
30  FFTW_FORWARD, FFTW_MEASURE);
31 
32  cmatrix_t bfft(m_Lto, 2 * m_Lto), b(m_Lto, 2 * m_Lto);
33  n[0] = int(2 * m_Lto);
34  this->idft_plan = fftw_plan_many_dft(1, n, int(m_Lto),
35  (fftw_complex *)bfft.data(), nullptr, int(m_Lto), 1,
36  (fftw_complex *)b.data(), nullptr, int(m_Lto), 1,
37  FFTW_BACKWARD, FFTW_MEASURE);
38 
39  // compute A matrices
40  int L = int(std::min(m_Lfrom, m_Lto));
41  for (int m = -L; m <= L; ++m)
42  m_A.push_back(Amatrix(L, m, Sto.get_theta(), Sfrom.get_theta(), Sfrom.get_wtheta()));
43 }
44 
45 interpolator::interpolator(interpolator &&other)
46  : m_Lfrom(other.m_Lfrom)
47  , m_Lto(other.m_Lto)
48  , m_A(std::move(other.m_A))
49  , dft_plan(other.dft_plan)
50  , idft_plan(other.idft_plan)
51  , m_Phi(std::move(other.m_Phi))
52  , m_Q(std::move(other.m_Q))
53  , m_res(std::move(other.m_res))
54 {
55  other.dft_plan = nullptr;
56  other.idft_plan = nullptr;
57 }
58 
59 
60 
61 interpolator::cvector_t const &
62 interpolator::interpolate(cvector_t const &other) const
63 {
64  using namespace boost::math::double_constants;
65 
66  size_t L = std::min(m_Lfrom, m_Lto);
67 
68  // dft along phi
70  // cmatrix_t Phi(Lfrom, 2 * Lfrom);
71  fftw_execute_dft(
72  this->dft_plan,
73  (fftw_complex *)other.data(),
74  (fftw_complex *)m_Phi.data());
75  m_Phi *= pi / m_Lfrom;
76 
77  // interpolation columnwise with zero padding/truncation
79  // cmatrix_t Q = cmatrix_t::Zero(Lto, 2 * Lto);
80  for (size_t m = 0; m < L; ++m)
81  m_Q.col(m) = m_A[m + L] * m_Phi.col(m);
82  for (int m = -int(L); m < 0; ++m)
83  m_Q.col(2 * m_Lto + m) = m_A[m + L] * m_Phi.col(2 * m_Lfrom + m);
84 
85  // idft along phi
86  // cvector_t res(Lto * 2 * Lto, 1);
87  fftw_execute_dft(
88  this->idft_plan,
89  (fftw_complex *)m_Q.data(),
90  (fftw_complex *)m_res.data());
91 
92  return m_res;
93 }
94 
95 interpolator const &
96 interpolator::operator=(interpolator const &other)
97 {
98  if (this == &other)
99  return *this;
100 
101  if (dft_plan)
102  fftw_destroy_plan(dft_plan);
103  if (idft_plan)
104  fftw_destroy_plan(idft_plan);
105 
106  if (other.dft_plan == nullptr)
107  {
108  dft_plan = nullptr;
109  idft_plan = nullptr;
110  return *this;
111  }
112 
113  m_Lfrom = other.m_Lfrom;
114  m_Lto = other.m_Lto;
115  m_A = other.m_A;
116  m_Phi = other.m_Phi;
117  m_Q = other.m_Q;
118  m_res = other.m_res;
119 
120  // plan dft-s
121  cmatrix_t a(m_Lfrom, 2 * m_Lfrom), afft(m_Lfrom, 2 * m_Lfrom);
122  int n[1];
123  n[0] = int(2 * m_Lfrom);
124  this->dft_plan = fftw_plan_many_dft(1, n, int(m_Lfrom),
125  (fftw_complex *)a.data(), nullptr, int(m_Lfrom), 1,
126  (fftw_complex *)afft.data(), nullptr, int(m_Lfrom), 1,
127  FFTW_FORWARD, FFTW_MEASURE);
128  cmatrix_t bfft(m_Lto, 2 * m_Lto), b(m_Lto, 2 * m_Lto);
129  n[0] = int(2 * m_Lto);
130  this->idft_plan = fftw_plan_many_dft(1, n, int(m_Lto),
131  (fftw_complex *)bfft.data(), nullptr, int(m_Lto), 1,
132  (fftw_complex *)b.data(), nullptr, int(m_Lto), 1,
133  FFTW_BACKWARD, FFTW_MEASURE);
134 
135  return *this;
136 }
137 
138 interpolator const &
139 interpolator::operator=(interpolator &&other)
140 {
141  if (&other == this)
142  return *this;
143 
144  m_Lfrom = other.m_Lfrom;
145  m_Lto = other.m_Lto;
146  m_A = std::move(other.m_A);
147  dft_plan = other.dft_plan;
148  idft_plan = other.idft_plan;
149  m_Phi = std::move(other.m_Phi);
150  m_Q = std::move(other.m_Q);
151  m_res = std::move(other.m_res);
152 
153  other.dft_plan = nullptr;
154  other.idft_plan = nullptr;
155 
156  return *this;
157 }
158 
159 
160 interpolator::dmatrix_t interpolator::Amatrix(int L, int m,
161  dvector_t const &theta,
162  dvector_t const &xi,
163  dvector_t const &wxi)
164 {
165  using boost::math::legendre_p;
166 
167  dmatrix_t Pi = dmatrix_t::Zero(theta.rows(), Eigen::Index(L + 1));
168  dmatrix_t Pj = dmatrix_t::Zero(xi.rows(), Eigen::Index(L + 1));
169  for (int l = std::abs(m); l <= L; ++l)
170  {
171  for (int i = 0; i < theta.rows(); ++i)
172  Pi(i, l) = legendre_p(l, m, std::cos(theta(i)));
173  for (int j = 0; j < xi.rows(); ++j)
174  Pj(j, l) = legendre_p(l, m, std::cos(xi(j)));
175  }
176  dmatrix_t A = dmatrix_t::Zero(theta.rows(), xi.rows());
177  for (int l = std::abs(m); l <= L; ++l)
178  A += C(l, m) * Pi.col(l) * Pj.col(l).transpose();
179  return A * wxi.asDiagonal();
180 }
181 
182 double interpolator::C(int l, int m)
183 {
184  double constexpr pi = boost::math::constants::pi<double>();
185 
186  double r = (2.0 * l + 1) / (4.0 * pi);
187  if (m > 0)
188  {
189  for (int k = l - m + 1; k <= l + m; ++k)
190  r /= k;
191  }
192  else if (m < 0)
193  {
194  for (int k = l + m + 1; k <= l - m; ++k)
195  r *= k;
196  }
197  return r;
198 }
199 
200 } // end of namespace fmm
201 } // namespace NiHu
NiHu::fmm::interpolator::interpolate
const cvector_t & interpolate(cvector_t const &other) const
Definition: unit_sphere_interpolator.cpp:62
unit_sphere_interpolator.h
Interface of class NiHu::fmm::interpolator.
NiHu::fmm::interpolator
class interpolating over the unit sphere
Definition: unit_sphere_interpolator.h:25
C
Definition: bbfmm_covariance.cpp:47