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()
52 FFT_3d_parallel1d::~FFT_3d_parallel1d()
59 void FFT_3d_parallel1d::set_parameters(
const Parameters& params)
62 this->FFT::set_parameters(params);
64 std::string direction;
66 if (params.
fetch_string(
"FFT_direction", direction) == 0) {
67 set_parameters(direction);
73 void FFT_3d_parallel1d::set_parameters(
const std::string& direction)
75 if (direction ==
"Forward") {
76 m_direction = FORWARD;
77 }
else if (direction ==
"Backward") {
78 m_direction = BACKWARD;
82 vout.
crucial(m_vl,
"Error at %s: unsupported FFT direction \"%s\"\n", class_name.c_str(), direction.c_str());
89 bool FFT_3d_parallel1d::check_ok()
94 vout.
crucial(m_vl,
"%s: incompatible with xy parallelization.\n", class_name.c_str());
103 void FFT_3d_parallel1d::initialize()
106 int thread_ok = fftw_init_threads();
126 int local_rank = ipe_x + npe_x * (ipe_y + npe_y * ipe_z);
133 void FFT_3d_parallel1d::initialize_plan(
const Field& src)
138 if ((m_nv == src.
nin() / 2) && (m_vol == local_vol)) {
139 vout.
general(m_vl,
"%s: plan recycled.\n", class_name.c_str());
142 vout.
general(m_vl,
"%s: create plan.\n", class_name.c_str());
159 m_nv = src.
nin() / 2;
162 ptrdiff_t local_n0, local_0_start;
164 ptrdiff_t psize = fftw_mpi_local_size_many(m_ndim, m_nsize, m_nv,
165 FFTW_MPI_DEFAULT_BLOCK, m_comm,
166 &local_n0, &local_0_start);
171 if ((local_n0 != nz) || (local_0_start != nz * ipe_z)) {
172 vout.
crucial(m_vl,
"%s: data distribution plan not matched.\n", class_name.c_str());
176 m_buf_in = fftw_alloc_complex(psize);
177 m_buf_out = fftw_alloc_complex(psize);
179 if ((!m_buf_in) || (!m_buf_out)) {
180 vout.
crucial(m_vl,
"%s: memory allocation failed.\n", class_name.c_str());
184 m_plan_fw = fftw_mpi_plan_many_dft(m_ndim, m_nsize, m_nv,
185 FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,
191 m_plan_bw = fftw_mpi_plan_many_dft(m_ndim, m_nsize, m_nv,
192 FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,
198 if ((!m_plan_fw) || (!m_plan_bw)) {
199 vout.
crucial(m_vl,
"%s: create plan failed.\n", class_name.c_str());
206 void FFT_3d_parallel1d::clear_plan()
208 if (m_buf_in) fftw_free(m_buf_in);
209 if (m_buf_out) fftw_free(m_buf_out);
211 if (m_plan_fw) fftw_destroy_plan(m_plan_fw);
212 if (m_plan_bw) fftw_destroy_plan(m_plan_bw);
217 void FFT_3d_parallel1d::finalize()
221 MPI_Comm_free(&m_comm);
228 if (not ((dir == FORWARD) || (dir == BACKWARD))) {
229 vout.
crucial(m_vl,
"%s: unsupported direction. %d\n", class_name.c_str(), dir);
233 initialize_plan(src);
240 size_t count = m_nv * m_vol;
242 for (
int iex = 0; iex < nex; ++iex) {
243 for (
int it = 0; it < nt; ++it) {
244 memcpy(m_buf_in, src.
ptr(0, index.
site(0, 0, 0, it), iex),
sizeof(
double) * count * 2);
246 if (dir == FORWARD) {
247 fftw_execute(m_plan_fw);
248 }
else if (dir == BACKWARD) {
249 fftw_execute(m_plan_bw);
251 vout.
crucial(m_vl,
"%s: unsupported direction. %d\n", class_name.c_str(), dir);
255 memcpy(dst.
ptr(0, index.
site(0, 0, 0, it), iex), m_buf_out,
sizeof(
double) * count * 2);
259 if (dir == BACKWARD) {
261 scal(dst, 1.0 / global_vol);
267 void FFT_3d_parallel1d::fft(
Field& dst,
const Field& src)
269 return fft(dst, src, m_direction);
274 void FFT_3d_parallel1d::fft(
Field& field)
276 vout.
crucial(m_vl,
"Error at %s: fft on-the-fly unsupported.\n", class_name.c_str());
void scal(Field &x, const double a)
scal(x, a): x = a * x
static int get_num_threads()
returns available number of threads.
static int npe(const int dir)
logical grid extent
const double * ptr(const int jin, const int site, const int jex) const
int site(const int &x, const int &y, const int &z, const int &t) const
void general(const char *format,...)
Container of Field-type object.
static int ipe(const int dir)
logical coordinate of current proc.
int fetch_string(const string &key, string &value) const
static MPI_Comm & world()
retrieves current communicator.
void crucial(const char *format,...)