27 const std::string FFT_3d_parallel1d::class_name =
"FFT_3d_parallel1d";
29 #ifdef USE_FACTORY_AUTOREGISTER
31 bool init = FFT_3d_parallel1d::register_factory();
36 FFT_3d_parallel1d::FFT_3d_parallel1d()
53 FFT_3d_parallel1d::~FFT_3d_parallel1d()
60 void FFT_3d_parallel1d::set_parameters(
const Parameters& params)
63 this->FFT::set_parameters(params);
65 std::string direction;
67 if (params.
fetch_string(
"FFT_direction", direction) == 0) {
68 set_parameters(direction);
74 void FFT_3d_parallel1d::set_parameters(
const std::string& direction)
76 if (direction ==
"Forward") {
77 m_direction = FORWARD;
78 }
else if (direction ==
"Backward") {
79 m_direction = BACKWARD;
83 vout.
crucial(m_vl,
"Error at %s: unsupported FFT direction \"%s\"\n", class_name.c_str(), direction.c_str());
90 bool FFT_3d_parallel1d::check_ok()
95 vout.
crucial(m_vl,
"%s: incompatible with xy parallelization.\n", class_name.c_str());
104 void FFT_3d_parallel1d::initialize()
107 int thread_ok = fftw_init_threads();
127 int local_rank = ipe_x + npe_x * (ipe_y + npe_y * ipe_z);
134 void FFT_3d_parallel1d::initialize_plan(
const Field& src)
139 if ((m_nv == src.
nin() / 2) && (m_vol == local_vol)) {
140 vout.
general(m_vl,
"%s: plan recycled.\n", class_name.c_str());
143 vout.
general(m_vl,
"%s: create plan.\n", class_name.c_str());
160 m_nv = src.
nin() / 2;
163 ptrdiff_t local_n0, local_0_start;
165 ptrdiff_t psize = fftw_mpi_local_size_many(m_ndim, m_nsize, m_nv,
166 FFTW_MPI_DEFAULT_BLOCK, m_comm,
167 &local_n0, &local_0_start);
172 if ((local_n0 != nz) || (local_0_start != nz * ipe_z)) {
173 vout.
crucial(m_vl,
"%s: data distribution plan not matched.\n", class_name.c_str());
177 m_buf_in = fftw_alloc_complex(psize);
178 m_buf_out = fftw_alloc_complex(psize);
180 if ((!m_buf_in) || (!m_buf_out)) {
181 vout.
crucial(m_vl,
"%s: memory allocation failed.\n", class_name.c_str());
185 m_plan_fw = fftw_mpi_plan_many_dft(m_ndim, m_nsize, m_nv,
186 FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,
192 m_plan_bw = fftw_mpi_plan_many_dft(m_ndim, m_nsize, m_nv,
193 FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,
199 if ((!m_plan_fw) || (!m_plan_bw)) {
200 vout.
crucial(m_vl,
"%s: create plan failed.\n", class_name.c_str());
207 void FFT_3d_parallel1d::clear_plan()
209 if (m_buf_in) fftw_free(m_buf_in);
210 if (m_buf_out) fftw_free(m_buf_out);
212 if (m_plan_fw) fftw_destroy_plan(m_plan_fw);
213 if (m_plan_bw) fftw_destroy_plan(m_plan_bw);
218 void FFT_3d_parallel1d::finalize()
222 MPI_Comm_free(&m_comm);
229 if (not ((dir == FORWARD) || (dir == BACKWARD))) {
230 vout.
crucial(m_vl,
"%s: unsupported direction. %d\n", class_name.c_str(), dir);
234 initialize_plan(src);
241 size_t count = m_nv * m_vol;
243 for (
int iex = 0; iex < nex; ++iex) {
244 for (
int it = 0; it < nt; ++it) {
245 memcpy(m_buf_in, src.
ptr(0, index.
site(0, 0, 0, it), iex),
sizeof(
double) * count * 2);
247 if (dir == FORWARD) {
248 fftw_execute(m_plan_fw);
249 }
else if (dir == BACKWARD) {
250 fftw_execute(m_plan_bw);
252 vout.
crucial(m_vl,
"%s: unsupported direction. %d\n", class_name.c_str(), dir);
256 memcpy(dst.
ptr(0, index.
site(0, 0, 0, it), iex), m_buf_out,
sizeof(
double) * count * 2);
260 if (dir == BACKWARD) {
262 scal(dst, 1.0 / global_vol);
268 void FFT_3d_parallel1d::fft(
Field& dst,
const Field& src)
270 return fft(dst, src, m_direction);
275 void FFT_3d_parallel1d::fft(
Field& field)
277 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,...)