Bridge++  Ver. 2.0.2
fft_3d_parallel1d.cpp
Go to the documentation of this file.
1 
13 #ifdef USE_FFTWLIB
14 #ifdef USE_MPI
15 
16 #include "fft_3d_parallel1d.h"
17 #include "Field/index_lex.h"
20 
21 #ifdef USE_OPENMP
23 #endif
24 
25 
26 const std::string FFT_3d_parallel1d::class_name = "FFT_3d_parallel1d";
27 
28 #ifdef USE_FACTORY_AUTOREGISTER
29 namespace {
30  bool init = FFT_3d_parallel1d::register_factory();
31 }
32 #endif
33 
34 //====================================================================
35 FFT_3d_parallel1d::FFT_3d_parallel1d()
36  : m_vl(CommonParameters::Vlevel())
37  , m_ndim(0)
38  , m_vol(0)
39  , m_nv(0)
40  , m_buf_in(NULL)
41  , m_buf_out(NULL)
42  , m_plan_fw(NULL)
43  , m_plan_bw(NULL)
44  , m_direction(UNDEF)
45 {
46  if (check_ok()) {
47  initialize();
48  }
49 }
50 
51 
52 //====================================================================
53 FFT_3d_parallel1d::FFT_3d_parallel1d(const Parameters& params)
54  : m_vl(CommonParameters::Vlevel())
55  , m_ndim(0)
56  , m_vol(0)
57  , m_nv(0)
58  , m_buf_in(NULL)
59  , m_buf_out(NULL)
60  , m_plan_fw(NULL)
61  , m_plan_bw(NULL)
62  , m_direction(UNDEF)
63 {
64  if (check_ok()) {
65  initialize();
66  }
67  set_parameters(params);
68 }
69 
70 
71 //====================================================================
72 FFT_3d_parallel1d::~FFT_3d_parallel1d()
73 {
74  finalize();
75 }
76 
77 
78 //====================================================================
79 void FFT_3d_parallel1d::set_parameters(const Parameters& params)
80 {
81  std::string vlevel;
82  if (!params.fetch_string("verbose_level", vlevel)) {
83  m_vl = vout.set_verbose_level(vlevel);
84  }
85 
86  std::string direction;
87  if (!params.fetch_string("FFT_direction", direction)) {
88  set_parameters(direction);
89  }
90 }
91 
92 
93 //====================================================================
94 void FFT_3d_parallel1d::get_parameters(Parameters& params) const
95 {
96  if (m_direction == FORWARD) {
97  params.set_string("FFT_direction", "Forward");
98  } else if (m_direction == BACKWARD) {
99  params.set_string("FFT_direction", "Backward");
100  } else {
101  params.set_string("FFT_direction", "None");
102  }
103 
104  params.set_string("verbose_level", vout.get_verbose_level(m_vl));
105 }
106 
107 
108 //====================================================================
109 void FFT_3d_parallel1d::set_parameters(const std::string& direction)
110 {
111  if (direction == "Forward") {
112  m_direction = FORWARD;
113  } else if (direction == "Backward") {
114  m_direction = BACKWARD;
115  } else {
116  m_direction = UNDEF;
117 
118  vout.crucial(m_vl, "Error at %s: unsupported FFT direction \"%s\"\n", class_name.c_str(), direction.c_str());
119  exit(EXIT_FAILURE);
120  }
121 }
122 
123 
124 //====================================================================
125 bool FFT_3d_parallel1d::check_ok()
126 {
127  int npe_xy = Communicator::npe(0) * Communicator::npe(1);
128 
129  if (npe_xy > 1) {
130  vout.crucial(m_vl, "%s: incompatible with xy parallelization.\n", class_name.c_str());
131  exit(EXIT_FAILURE);
132  }
133 
134  return true;
135 }
136 
137 
138 //====================================================================
139 void FFT_3d_parallel1d::initialize()
140 {
141 #ifdef USE_OPENMP
142  int thread_ok = fftw_init_threads();
143 
144  if (thread_ok) {
145  fftw_plan_with_nthreads(ThreadManager::get_num_threads());
146  }
147 #endif
148 
149  fftw_mpi_init();
150 
151  // split communicator along t-axis to form 3dim subspaces
152  int ipe_x = Communicator::ipe(0);
153  int ipe_y = Communicator::ipe(1);
154  int ipe_z = Communicator::ipe(2);
155  int ipe_t = Communicator::ipe(3);
156 
157  int npe_x = Communicator::npe(0);
158  int npe_y = Communicator::npe(1);
159  int npe_z = Communicator::npe(2);
160  int npe_t = Communicator::npe(3);
161 
162  int local_rank = ipe_x + npe_x * (ipe_y + npe_y * ipe_z);
163 
164  MPI_Comm_split(Communicator_impl::world(), ipe_t, local_rank, &m_comm);
165 }
166 
167 
168 //====================================================================
169 void FFT_3d_parallel1d::initialize_plan(const Field& src)
170 {
171  int local_vol =
173 
174  if ((m_nv == src.nin() / 2) && (m_vol == local_vol)) {
175  vout.general(m_vl, "%s: plan recycled.\n", class_name.c_str());
176  return;
177  } else {
178  vout.general(m_vl, "%s: create plan.\n", class_name.c_str());
179  }
180 
181  // first, clear pre-existing plan, if any.
182  clear_plan();
183 
184  // assume 3dimensional
185  m_ndim = 3;
186  // row-major fortran order
187  m_nsize[0] = CommonParameters::Lz();
188  m_nsize[1] = CommonParameters::Ly();
189  m_nsize[2] = CommonParameters::Lx();
190 
191  // local volume size
192  m_vol = local_vol;
193 
194  // number of complex elements. run nin at a time.
195  m_nv = src.nin() / 2;
196 
197  // local size
198  ptrdiff_t local_n0, local_0_start;
199 
200  ptrdiff_t psize = fftw_mpi_local_size_many(m_ndim, m_nsize, m_nv,
201  FFTW_MPI_DEFAULT_BLOCK, m_comm,
202  &local_n0, &local_0_start);
203 
204  int nz = CommonParameters::Nz();
205  int ipe_z = Communicator::ipe(2);
206 
207  if ((local_n0 != nz) || (local_0_start != nz * ipe_z)) {
208  vout.crucial(m_vl, "%s: data distribution plan not matched.\n", class_name.c_str());
209  exit(EXIT_FAILURE);
210  }
211 
212  m_buf_in = fftw_alloc_complex(psize);
213  m_buf_out = fftw_alloc_complex(psize);
214 
215  if ((!m_buf_in) || (!m_buf_out)) {
216  vout.crucial(m_vl, "%s: memory allocation failed.\n", class_name.c_str());
217  exit(EXIT_FAILURE);
218  }
219 
220  m_plan_fw = fftw_mpi_plan_many_dft(m_ndim, m_nsize, m_nv,
221  FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,
222  m_buf_in, m_buf_out,
223  m_comm,
224  FFTW_FORWARD,
225  FFTW_ESTIMATE);
226 
227  m_plan_bw = fftw_mpi_plan_many_dft(m_ndim, m_nsize, m_nv,
228  FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,
229  m_buf_in, m_buf_out,
230  m_comm,
231  FFTW_BACKWARD,
232  FFTW_ESTIMATE);
233 
234  if ((!m_plan_fw) || (!m_plan_bw)) {
235  vout.crucial(m_vl, "%s: create plan failed.\n", class_name.c_str());
236  exit(EXIT_FAILURE);
237  }
238 }
239 
240 
241 //====================================================================
242 void FFT_3d_parallel1d::clear_plan()
243 {
244  if (m_buf_in) fftw_free(m_buf_in);
245  if (m_buf_out) fftw_free(m_buf_out);
246 
247  if (m_plan_fw) fftw_destroy_plan(m_plan_fw);
248  if (m_plan_bw) fftw_destroy_plan(m_plan_bw);
249 }
250 
251 
252 //====================================================================
253 void FFT_3d_parallel1d::finalize()
254 {
255  clear_plan();
256 
257  MPI_Comm_free(&m_comm);
258 }
259 
260 
261 //====================================================================
262 void FFT_3d_parallel1d::fft(Field& dst, const Field& src, enum Direction dir)
263 {
264  if (not ((dir == FORWARD) || (dir == BACKWARD))) {
265  vout.crucial(m_vl, "%s: unsupported direction. %d\n", class_name.c_str(), dir);
266  exit(EXIT_FAILURE);
267  }
268 
269  initialize_plan(src);
270 
271  int nex = src.nex();
272  int nt = CommonParameters::Nt();
273 
274  Index_lex index;
275 
276  size_t count = m_nv * m_vol; // count in complex numbers
277 
278  for (int iex = 0; iex < nex; ++iex) {
279  for (int it = 0; it < nt; ++it) {
280  memcpy(m_buf_in, src.ptr(0, index.site(0, 0, 0, it), iex), sizeof(double) * count * 2);
281 
282  if (dir == FORWARD) {
283  fftw_execute(m_plan_fw);
284  } else if (dir == BACKWARD) {
285  fftw_execute(m_plan_bw);
286  } else {
287  vout.crucial(m_vl, "%s: unsupported direction. %d\n", class_name.c_str(), dir);
288  exit(EXIT_FAILURE);
289  }
290 
291  memcpy(dst.ptr(0, index.site(0, 0, 0, it), iex), m_buf_out, sizeof(double) * count * 2);
292  }
293  }
294 
295  if (dir == BACKWARD) {
296  size_t global_vol = CommonParameters::Lvol() / CommonParameters::Lt();
297  scal(dst, 1.0 / global_vol);
298  }
299 }
300 
301 
302 //====================================================================
303 void FFT_3d_parallel1d::fft(Field& dst, const Field& src)
304 {
305  return fft(dst, src, m_direction);
306 }
307 
308 
309 //====================================================================
310 void FFT_3d_parallel1d::fft(Field& field)
311 {
312  vout.crucial(m_vl, "Error at %s: fft on-the-fly unsupported.\n", class_name.c_str());
313  exit(EXIT_FAILURE);
314 }
315 
316 
317 //====================================================================
318 #endif /* USE_MPI */
319 #endif /* USE_FFTWLIB */
CommonParameters::Nz
static int Nz()
Definition: commonParameters.h:107
CommonParameters::Lvol
static long_t Lvol()
Definition: commonParameters.h:95
Parameters::set_string
void set_string(const string &key, const string &value)
Definition: parameters.cpp:39
CommonParameters
Common parameter class: provides parameters as singleton.
Definition: commonParameters.h:42
Index_lex
Lexical site index.
Definition: index_lex.h:34
ThreadManager::get_num_threads
static int get_num_threads()
returns available number of threads.
Definition: threadManager.cpp:246
Parameters
Class for parameters.
Definition: parameters.h:46
Field::nex
int nex() const
Definition: field.h:128
CommonParameters::Ly
static int Ly()
Definition: commonParameters.h:92
Direction
Direction
Definition: bridge_defs.h:24
Field::nin
int nin() const
Definition: field.h:126
CommonParameters::Lt
static int Lt()
Definition: commonParameters.h:94
CommonParameters::Lx
static int Lx()
Definition: commonParameters.h:91
communicator_mpi.h
CommonParameters::Lz
static int Lz()
Definition: commonParameters.h:93
CommonParameters::Nt
static int Nt()
Definition: commonParameters.h:108
Communicator::npe
static int npe(const int dir)
logical grid extent
Definition: communicator.cpp:112
threadManager.h
index_lex.h
Index_lex::site
int site(const int &x, const int &y, const int &z, const int &t) const
Definition: index_lex.h:55
Field::ptr
const double * ptr(const int jin, const int site, const int jex) const
Definition: field.h:153
Bridge::BridgeIO::set_verbose_level
static VerboseLevel set_verbose_level(const std::string &str)
Definition: bridgeIO.cpp:133
scal
void scal(Field &x, const double a)
scal(x, a): x = a * x
Definition: field.cpp:261
Communicator::ipe
static int ipe(const int dir)
logical coordinate of current proc.
Definition: communicator.cpp:105
Parameters::fetch_string
int fetch_string(const string &key, string &value) const
Definition: parameters.cpp:378
Bridge::BridgeIO::crucial
void crucial(const char *format,...)
Definition: bridgeIO.cpp:180
Field
Container of Field-type object.
Definition: field.h:46
communicator.h
fft_3d_parallel1d.h
Bridge::BridgeIO::general
void general(const char *format,...)
Definition: bridgeIO.cpp:200
Bridge::vout
BridgeIO vout
Definition: bridgeIO.cpp:512
Bridge::BridgeIO::get_verbose_level
static std::string get_verbose_level(const VerboseLevel vl)
Definition: bridgeIO.cpp:154