NiHu  2.0
helmholtz_2d_wb_level_data.cpp
Go to the documentation of this file.
1 
8 #include <iostream>
9 #include <omp.h>
10 
11 namespace NiHu
12 {
13 namespace fmm
14 {
15 
17  : m_interp_ups(1)
18  , m_interp_dns(1)
19  , m_dft_plan(nullptr)
20  , m_multi_paddeds(1)
21  , m_multi_spectrums(1)
22  , m_idft_plan(nullptr)
23  , m_local_paddeds(1)
24  , m_locals(1)
25 
26 {
27 }
28 
30 {
31  if (m_dft_plan)
32  fftw_destroy_plan(m_dft_plan);
33  if (m_idft_plan)
34  fftw_destroy_plan(m_idft_plan);
35 }
36 
38  : m_high_freq(rhs.m_high_freq)
39  , m_interp_ups(rhs.m_interp_ups)
40  , m_interp_dns(rhs.m_interp_dns)
41  , m_dft_plan(nullptr)
42  , m_multi_paddeds(rhs.m_multi_paddeds)
43  , m_multi_spectrums(rhs.m_multi_spectrums)
44  , m_idft_plan(nullptr)
45  , m_local_paddeds(rhs.m_local_paddeds)
46  , m_locals(rhs.m_locals)
47 {
48  set_expansion_length(rhs.get_expansion_length());
49 }
50 
51 
53 {
54  int expansion_length = int(40.0 + 9.0 * drel);
55  bool is_high = drel > 3.0;
56  set_expansion_length(expansion_length);
57  set_high_freq(is_high);
58 }
59 
61 {
62  m_expansion_length = expansion_length;
63 
64  // destroy dft's if existing
65  if (m_dft_plan)
66  fftw_destroy_plan(m_dft_plan);
67  if (m_idft_plan)
68  fftw_destroy_plan(m_idft_plan);
69 
70  size_t S = 2 * (2 * m_expansion_length) + 1;
71 
72  // replan dft
73  for (auto &a : m_multi_paddeds)
74  a.resize(S, 1);
75  for (auto &a : m_multi_spectrums)
76  a.resize(S, 1);
77  m_dft_plan = fftw_plan_dft_1d(int(S), (fftw_complex *)m_multi_paddeds[0].data(),
78  (fftw_complex *)m_multi_spectrums[0].data(), FFTW_FORWARD, FFTW_MEASURE);
79 
80  // replan idft
81  for (auto &a : m_locals)
82  a.resize(S, 1);
83  for (auto &a : m_local_paddeds)
84  a.resize(S, 1);
85  m_idft_plan = fftw_plan_dft_1d(int(S), (fftw_complex *)m_locals[0].data(),
86  (fftw_complex *)m_local_paddeds[0].data(), FFTW_BACKWARD, FFTW_MEASURE);
87 
88  for (auto &a : m_locals)
89  a.resize(2 * m_expansion_length + 1, 1);
90 
91  for (auto &a : m_multi_paddeds)
92  a.setZero();
93 }
94 
96 {
97  return m_expansion_length;
98 }
99 
101 {
102  size_t M = m_expansion_length;
103  if (is_high_freq())
104  return 2 * (2 * M) + 1;
105  else
106  return 2 * M + 1;
107 }
108 
110 {
111  m_high_freq = hf;
112 }
113 
115 {
116  return m_high_freq;
117 }
118 
121 {
122  auto const idx = omp_get_thread_num();
123 
124  if (multi.rows() != 2 * m_expansion_length + 1)
125  throw std::runtime_error("Invalid multipole size");
126 
127  // pad and shift
128  m_multi_paddeds[idx].tail(m_expansion_length) = multi.head(m_expansion_length);
129  m_multi_paddeds[idx].head(m_expansion_length + 1) = multi.tail(m_expansion_length + 1);
130 
131  // dft
132  fftw_execute_dft(m_dft_plan, (fftw_complex *)m_multi_paddeds[idx].data(),
133  (fftw_complex *)m_multi_spectrums[idx].data());
134 
135  return m_multi_spectrums[idx];
136 }
137 
140 {
141  auto const idx = omp_get_thread_num();
142 
143  if (local_spect.rows() != 2 * (2 * m_expansion_length) + 1)
144  throw std::runtime_error("Invalid local spectrum size");
145 
146  // idft
147  fftw_execute_dft(m_idft_plan, (fftw_complex *)local_spect.data(),
148  (fftw_complex *)m_local_paddeds[idx].data());
149  m_local_paddeds[idx] /= double(2 * (2 * m_expansion_length) + 1);
150 
151  // shift and depad
152  m_locals[idx].head(m_expansion_length) = m_local_paddeds[idx].tail(m_expansion_length);
153  m_locals[idx].tail(1 + m_expansion_length) = m_local_paddeds[idx].head(1 + m_expansion_length);
154 
155  return m_locals[idx];
156 }
157 
159 {
160  m_interp_ups[0] = spectral_interpolate(m_expansion_length, Nfrom);
161  for (size_t i = 1; i < m_interp_ups.size(); ++i)
162  m_interp_ups[i] = m_interp_ups[0];
163 }
164 
167 {
168  auto const idx = omp_get_thread_num();
169  return m_interp_ups[idx].interpolate(multi);
170 }
171 
173 {
174  m_interp_dns[0] = spectral_interpolate(m_expansion_length, Nfrom);
175  for (size_t i = 1; i < m_interp_dns.size(); ++i)
176  m_interp_dns[i] = m_interp_dns[0];
177 }
178 
181 {
182  auto const idx = omp_get_thread_num();
183  return m_interp_dns[idx].interpolate(local);
184 }
185 
186 void helmholtz_2d_wb_level_data::set_num_threads(size_t n)
187 {
188  // resize all thread_private vectors
189  m_interp_dns.resize(n, m_interp_dns[0]);
190  m_interp_ups.resize(n, m_interp_ups[0]);
191  m_multi_paddeds.resize(n, m_multi_paddeds[0]);
192  m_multi_spectrums.resize(n, m_multi_spectrums[0]);
193  m_locals.resize(n, m_locals[0]);
194  m_local_paddeds.resize(n, m_local_paddeds[0]);
195 }
196 
197 } // end of namespace fmm
198 } // namespace NiHu
NiHu::fmm::helmholtz_2d_wb_level_data
class containing the level data of the helmholtz 2d wide band fmm
Definition: helmholtz_2d_wb_level_data.h:24
NiHu::fmm::helmholtz_2d_wb_level_data::set_expansion_length
void set_expansion_length(size_t expansion_length)
set the expansion length of the level
Definition: helmholtz_2d_wb_level_data.cpp:60
NiHu::fmm::helmholtz_2d_wb_level_data::is_high_freq
bool is_high_freq() const
return true if the level is in hgh frequency
Definition: helmholtz_2d_wb_level_data.cpp:114
NiHu::fmm::helmholtz_2d_wb_level_data::helmholtz_2d_wb_level_data
helmholtz_2d_wb_level_data()
constructor
Definition: helmholtz_2d_wb_level_data.cpp:16
NiHu::fmm::helmholtz_2d_wb_level_data::idft
const cvector_t & idft(cvector_t const &local) const
perform inverse dft on this level
Definition: helmholtz_2d_wb_level_data.cpp:139
NiHu::fmm::helmholtz_2d_wb_level_data::cvector_t
Eigen::Matrix< std::complex< double >, Eigen::Dynamic, 1 > cvector_t
complex column vector type
Definition: helmholtz_2d_wb_level_data.h:28
NiHu::fmm::helmholtz_2d_wb_level_data::~helmholtz_2d_wb_level_data
~helmholtz_2d_wb_level_data()
destructor
Definition: helmholtz_2d_wb_level_data.cpp:29
NiHu::fmm::helmholtz_2d_wb_level_data::get_expansion_length
size_t get_expansion_length() const
return the expansion length
Definition: helmholtz_2d_wb_level_data.cpp:95
NiHu::fmm::helmholtz_2d_wb_level_data::get_data_size
size_t get_data_size() const
return the size of the multipole / local data
Definition: helmholtz_2d_wb_level_data.cpp:100
helmholtz_2d_wb_level_data.h
declaration of class helmholtz_2d_wb_level_data
NiHu::fmm::helmholtz_2d_wb_level_data::interp_up
const cvector_t & interp_up(cvector_t const &multi) const
interpolate multipole contribution up to this level
Definition: helmholtz_2d_wb_level_data.cpp:166
NiHu::fmm::helmholtz_2d_wb_level_data::interp_dn
const cvector_t & interp_dn(cvector_t const &local) const
interpolate local data down to this level
Definition: helmholtz_2d_wb_level_data.cpp:180
NiHu::fmm::helmholtz_2d_wb_level_data::init
void init(double drel)
initialize the data for a given frequency
Definition: helmholtz_2d_wb_level_data.cpp:52
NiHu::fmm::helmholtz_2d_wb_level_data::set_high_freq
void set_high_freq(bool hf)
set if the level is in high frequency
Definition: helmholtz_2d_wb_level_data.cpp:109
NiHu::fmm::spectral_interpolate
class performing spectral interpolation
Definition: spectral_interpolate.h:20
NiHu::fmm::helmholtz_2d_wb_level_data::dft
const cvector_t & dft(cvector_t const &multi) const
perform dft on this level
Definition: helmholtz_2d_wb_level_data.cpp:120
NiHu::fmm::helmholtz_2d_wb_level_data::set_interp_up
void set_interp_up(size_t Nfrom)
compute upward interpolating matrix
Definition: helmholtz_2d_wb_level_data.cpp:158
NiHu::fmm::helmholtz_2d_wb_level_data::set_interp_dn
void set_interp_dn(size_t Nfrom)
compute the downward interpolating matrix
Definition: helmholtz_2d_wb_level_data.cpp:172