22 return new FFT_xyz_3dim();
26 bool init = FFT::Factory::Register(
"FFT_xyz_3dim", create_object);
30 const std::string FFT_xyz_3dim::class_name =
"FFT_xyz_3dim";
33 void FFT_xyz_3dim::set_parameters(
const Parameters& params)
35 const std::string str_vlevel = params.
get_string(
"verbose_level");
40 string str_fft_direction;
43 err += params.
fetch_string(
"FFT_direction", str_fft_direction);
46 vout.
crucial(m_vl,
"Error at %s: input parameter not found.\n", class_name.c_str());
50 set_parameters(str_fft_direction);
55 void FFT_xyz_3dim::set_parameters(
const string str_fft_direction)
59 vout.
general(m_vl,
" FFT_direction = %s\n", str_fft_direction.c_str());
64 if (str_fft_direction ==
"Forward") {
66 }
else if (str_fft_direction ==
"Backward") {
69 vout.
crucial(m_vl,
"Error at %s: unsupported FFT direction \"%s\"\n", class_name.c_str(), str_fft_direction.c_str());
76 void FFT_xyz_3dim::init()
84 int threads_ok = fftw_init_threads();
93 if ((NPE_x * NPE_y * NPE_t) != 1) {
94 vout.
crucial(m_vl,
"Error at %s: FFTW supports parallelization only in z-direction.\n",
108 ptrdiff_t fftw_size_p = fftw_mpi_local_size_3d(Lz_p, Ly_p, Lx_p,
110 &m_Nz_p, &m_z_start_p);
112 m_in = fftw_alloc_complex(fftw_size_p);
113 m_out = fftw_alloc_complex(fftw_size_p);
115 if (!m_in || !m_out) {
116 vout.
crucial(m_vl,
"Error at %s: failed to allocate memory %d [Byte].\n",
117 class_name.c_str(), (int)fftw_size_p);
122 const size_t fftw_size =
sizeof(fftw_complex) * Lx * Ly * Lz;
123 m_in = (fftw_complex *)fftw_malloc(fftw_size);
124 m_out = (fftw_complex *)fftw_malloc(fftw_size);
126 if (!m_in || !m_out) {
127 vout.
crucial(m_vl,
"Error at %s: failed to allocate memory %d [Byte].\n",
128 class_name.c_str(), (int)fftw_size);
136 void FFT_xyz_3dim::tidy_up()
138 if (m_in) fftw_free(m_in);
139 if (m_out) fftw_free(m_out);
140 if (m_plan) fftw_destroy_plan(m_plan);
145 void FFT_xyz_3dim::fft(
Field& field)
152 const int Lxyz = Lx * Ly * Lz;
157 const int Nin = field.
nin();
158 const int Nex = field.
nex();
164 fftw_plan_with_nthreads(Nthread);
172 m_plan = fftw_mpi_plan_dft_3d(Lz_p, Ly_p, Lx_p, m_in, m_out,
174 FFTW_FORWARD, FFTW_ESTIMATE);
176 m_plan = fftw_mpi_plan_dft_3d(Lz_p, Ly_p, Lx_p, m_in, m_out,
178 FFTW_BACKWARD, FFTW_ESTIMATE);
182 m_plan = fftw_plan_dft_3d(Lz, Ly, Lx, m_in, m_out,
183 FFTW_FORWARD, FFTW_ESTIMATE);
185 m_plan = fftw_plan_dft_3d(Lz, Ly, Lx, m_in, m_out,
186 FFTW_BACKWARD, FFTW_ESTIMATE);
193 for (
int in2 = 0; in2 < Nin / 2; ++in2) {
194 for (
int t_global = 0; t_global < Lt; t_global++) {
195 for (
int ex = 0; ex < Nex; ++ex) {
197 for (
int z = 0; z < Nz; z++) {
198 for (
int y_global = 0; y_global < Ly; y_global++) {
199 for (
int x_global = 0; x_global < Lx; x_global++) {
200 int isite_xyz_local = x_global + Lx * (y_global + Ly * z);
202 int isite = m_index.site(x_global, y_global, z, t_global);
203 int i_real = 2 * in2;
204 int i_imag = 2 * in2 + 1;
206 m_in[isite_xyz_local][0] = field.
cmp(i_real, isite, ex);
207 m_in[isite_xyz_local][1] = field.
cmp(i_imag, isite, ex);
213 fftw_execute(m_plan);
217 for (
int z = 0; z < Nz; z++) {
218 for (
int y_global = 0; y_global < Ly; y_global++) {
219 for (
int x_global = 0; x_global < Lx; x_global++) {
220 int isite_xyz_local = x_global + Lx * (y_global + Ly * z);
222 int isite = m_index.site(x_global, y_global, z, t_global);
223 int i_real = 2 * in2;
224 int i_imag = 2 * in2 + 1;
226 field.
set(i_real, isite, ex, m_out[isite_xyz_local][0]);
227 field.
set(i_imag, isite, ex, m_out[isite_xyz_local][1]);
238 scal(field, 1.0 / Lxyz);
244 void FFT_xyz_3dim::fft(
Field& field_out,
const Field& field_in)
251 const int Lxyz = Lx * Ly * Lz;
256 const int Nin = field_in.
nin();
257 const int Nex = field_in.
nex();
263 fftw_plan_with_nthreads(Nthread);
271 m_plan = fftw_mpi_plan_dft_3d(Lz_p, Ly_p, Lx_p, m_in, m_out,
273 FFTW_FORWARD, FFTW_ESTIMATE);
275 m_plan = fftw_mpi_plan_dft_3d(Lz_p, Ly_p, Lx_p, m_in, m_out,
277 FFTW_BACKWARD, FFTW_ESTIMATE);
281 m_plan = fftw_plan_dft_3d(Lz, Ly, Lx, m_in, m_out,
282 FFTW_FORWARD, FFTW_ESTIMATE);
284 m_plan = fftw_plan_dft_3d(Lz, Ly, Lx, m_in, m_out,
285 FFTW_BACKWARD, FFTW_ESTIMATE);
292 for (
int in2 = 0; in2 < Nin / 2; ++in2) {
293 for (
int t_global = 0; t_global < Lt; t_global++) {
294 for (
int ex = 0; ex < Nex; ++ex) {
296 for (
int z = 0; z < Nz; z++) {
297 for (
int y_global = 0; y_global < Ly; y_global++) {
298 for (
int x_global = 0; x_global < Lx; x_global++) {
299 int isite_xyz_local = x_global + Lx * (y_global + Ly * z);
301 int isite = m_index.site(x_global, y_global, z, t_global);
302 int i_real = 2 * in2;
303 int i_imag = 2 * in2 + 1;
305 m_in[isite_xyz_local][0] = field_in.
cmp(i_real, isite, ex);
306 m_in[isite_xyz_local][1] = field_in.
cmp(i_imag, isite, ex);
312 fftw_execute(m_plan);
316 for (
int z = 0; z < Nz; z++) {
317 for (
int y_global = 0; y_global < Ly; y_global++) {
318 for (
int x_global = 0; x_global < Lx; x_global++) {
319 int isite_xyz_local = x_global + Lx * (y_global + Ly * z);
321 int isite = m_index.site(x_global, y_global, z, t_global);
322 int i_real = 2 * in2;
323 int i_imag = 2 * in2 + 1;
325 field_out.
set(i_real, isite, ex, m_out[isite_xyz_local][0]);
326 field_out.
set(i_imag, isite, ex, m_out[isite_xyz_local][1]);
337 scal(field_out, 1.0 / Lxyz);
void scal(Field &x, const double a)
scal(x, a): x = a * x
static int get_num_threads()
returns available number of threads.
void set(const int jin, const int site, const int jex, double v)
void general(const char *format,...)
Container of Field-type object.
double cmp(const int jin, const int site, const int jex) const
int fetch_string(const string &key, string &value) const
void crucial(const char *format,...)
string get_string(const string &key) const
static VerboseLevel set_verbose_level(const std::string &str)