26 const std::string FFT_3d_parallel1d::class_name =
"FFT_3d_parallel1d";
28 #ifdef USE_FACTORY_AUTOREGISTER
30 bool init = FFT_3d_parallel1d::register_factory();
35 FFT_3d_parallel1d::FFT_3d_parallel1d()
53 FFT_3d_parallel1d::FFT_3d_parallel1d(
const Parameters& params)
67 set_parameters(params);
72 FFT_3d_parallel1d::~FFT_3d_parallel1d()
79 void FFT_3d_parallel1d::set_parameters(
const Parameters& params)
86 std::string direction;
88 set_parameters(direction);
94 void FFT_3d_parallel1d::get_parameters(
Parameters& params)
const
96 if (m_direction == FORWARD) {
98 }
else if (m_direction == BACKWARD) {
99 params.
set_string(
"FFT_direction",
"Backward");
109 void FFT_3d_parallel1d::set_parameters(
const std::string& direction)
111 if (direction ==
"Forward") {
112 m_direction = FORWARD;
113 }
else if (direction ==
"Backward") {
114 m_direction = BACKWARD;
118 vout.
crucial(m_vl,
"Error at %s: unsupported FFT direction \"%s\"\n", class_name.c_str(), direction.c_str());
125 bool FFT_3d_parallel1d::check_ok()
130 vout.
crucial(m_vl,
"%s: incompatible with xy parallelization.\n", class_name.c_str());
139 void FFT_3d_parallel1d::initialize()
142 int thread_ok = fftw_init_threads();
162 int local_rank = ipe_x + npe_x * (ipe_y + npe_y * ipe_z);
164 MPI_Comm_split(Communicator_impl::world(), ipe_t, local_rank, &m_comm);
169 void FFT_3d_parallel1d::initialize_plan(
const Field& src)
174 if ((m_nv == src.
nin() / 2) && (m_vol == local_vol)) {
175 vout.
general(m_vl,
"%s: plan recycled.\n", class_name.c_str());
178 vout.
general(m_vl,
"%s: create plan.\n", class_name.c_str());
195 m_nv = src.
nin() / 2;
198 ptrdiff_t local_n0, local_0_start;
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);
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());
212 m_buf_in = fftw_alloc_complex(psize);
213 m_buf_out = fftw_alloc_complex(psize);
215 if ((!m_buf_in) || (!m_buf_out)) {
216 vout.
crucial(m_vl,
"%s: memory allocation failed.\n", class_name.c_str());
220 m_plan_fw = fftw_mpi_plan_many_dft(m_ndim, m_nsize, m_nv,
221 FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,
227 m_plan_bw = fftw_mpi_plan_many_dft(m_ndim, m_nsize, m_nv,
228 FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,
234 if ((!m_plan_fw) || (!m_plan_bw)) {
235 vout.
crucial(m_vl,
"%s: create plan failed.\n", class_name.c_str());
242 void FFT_3d_parallel1d::clear_plan()
244 if (m_buf_in) fftw_free(m_buf_in);
245 if (m_buf_out) fftw_free(m_buf_out);
247 if (m_plan_fw) fftw_destroy_plan(m_plan_fw);
248 if (m_plan_bw) fftw_destroy_plan(m_plan_bw);
253 void FFT_3d_parallel1d::finalize()
257 MPI_Comm_free(&m_comm);
264 if (not ((dir == FORWARD) || (dir == BACKWARD))) {
265 vout.
crucial(m_vl,
"%s: unsupported direction. %d\n", class_name.c_str(), dir);
269 initialize_plan(src);
276 size_t count = m_nv * m_vol;
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);
282 if (dir == FORWARD) {
283 fftw_execute(m_plan_fw);
284 }
else if (dir == BACKWARD) {
285 fftw_execute(m_plan_bw);
287 vout.
crucial(m_vl,
"%s: unsupported direction. %d\n", class_name.c_str(), dir);
291 memcpy(dst.
ptr(0, index.
site(0, 0, 0, it), iex), m_buf_out,
sizeof(
double) * count * 2);
295 if (dir == BACKWARD) {
297 scal(dst, 1.0 / global_vol);
303 void FFT_3d_parallel1d::fft(
Field& dst,
const Field& src)
305 return fft(dst, src, m_direction);
310 void FFT_3d_parallel1d::fft(
Field& field)
312 vout.
crucial(m_vl,
"Error at %s: fft on-the-fly unsupported.\n", class_name.c_str());