kspaceFirstOrder3D-OMP  1.1
The C++ implementation of the k-wave toolbox for the time-domain simulation of acoustic wave fields in 3D
 All Classes Files Functions Variables Typedefs Enumerations Friends Pages
FFTWComplexMatrix.cpp
Go to the documentation of this file.
1 /**
2  * @file FFTWComplexMatrix.cpp
3  * @author Jiri Jaros \n
4  * Faculty of Information Technology\n
5  * Brno University of Technology \n
6  * jarosjir@fit.vutbr.cz
7  *
8  * @brief The implementation file containing the class that implements
9  * 3D FFT using the FFTW interface
10  *
11  * @version kspaceFirstOrder3D 2.15
12  * @date 09 August 2011, 13:10 (created) \n
13  * 25 September 2014, 13:47 (revised)
14  *
15  * @section License
16  * This file is part of the C++ extension of the k-Wave Toolbox (http://www.k-wave.org).\n
17  * Copyright (C) 2014 Jiri Jaros and Bradley Treeby
18  *
19  * This file is part of k-Wave. k-Wave is free software: you can redistribute it
20  * and/or modify it under the terms of the GNU Lesser General Public License as
21  * published by the Free Software Foundation, either version 3 of the License,
22  * or (at your option) any later version.
23  *
24  * k-Wave is distributed in the hope that it will be useful, but
25  * WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
27  * See the GNU Lesser General Public License for more details.
28  *
29  * You should have received a copy of the GNU Lesser General Public License
30  * along with k-Wave. If not, see <http://www.gnu.org/licenses/>.
31  */
32 
35 
36 #include <Parameters/Parameters.h>
37 #include <Utils/ErrorMessages.h>
38 
39 #include <stdexcept>
40 #include <string.h>
41 #include <cstdio>
42 using namespace std;
43 
44 
45 
46 //----------------------------------------------------------------------------//
47 // Constants //
48 //----------------------------------------------------------------------------//
49 const string TFFTWComplexMatrix::FFTW_Wisdom_FileName_Extension = "FFTW_Wisdom";
50 
51 //----------------------------------------------------------------------------//
52 // Public methods //
53 //----------------------------------------------------------------------------//
54 
55 
56 /**
57  * Constructor.
58  * @param [in] DimensionSizes - Dimension sizes of the reduced complex matrix
59  */
62  fftw_plan_3D_R2C(NULL), fftw_plan_3D_C2R(NULL),
63  fftw_plan_1DX_R2C(NULL), fftw_plan_1DY_R2C(NULL), fftw_plan_1DZ_R2C(NULL),
64  fftw_plan_1DX_C2R(NULL), fftw_plan_1DY_C2R(NULL), fftw_plan_1DZ_C2R(NULL)
65 {
66  InitDimensions(DimensionSizes);
68 }// end of TFFTWComplexMatrix
69 //------------------------------------------------------------------------------
70 
71 
72 
73 /**
74  * Destructor.
75  */
77 {
78  FreeMemory();
79 
80  // free 3D plans
81  if (fftw_plan_3D_R2C) fftwf_destroy_plan(fftw_plan_3D_R2C);
82  if (fftw_plan_3D_C2R) fftwf_destroy_plan(fftw_plan_3D_C2R);
83 
84  //free 1D plans.
85  if (fftw_plan_1DX_R2C) fftwf_destroy_plan(fftw_plan_1DX_R2C);
86  if (fftw_plan_1DY_R2C) fftwf_destroy_plan(fftw_plan_1DY_R2C);
87  if (fftw_plan_1DZ_R2C) fftwf_destroy_plan(fftw_plan_1DZ_R2C);
88 
89  if (fftw_plan_1DX_C2R) fftwf_destroy_plan(fftw_plan_1DX_C2R);
90  if (fftw_plan_1DY_C2R) fftwf_destroy_plan(fftw_plan_1DY_C2R);
91  if (fftw_plan_1DZ_C2R) fftwf_destroy_plan(fftw_plan_1DZ_C2R);
92 
93  fftw_plan_3D_R2C = NULL;
94  fftw_plan_3D_C2R = NULL;
95 
96  fftw_plan_1DX_R2C = NULL;
97  fftw_plan_1DY_R2C = NULL;
98  fftw_plan_1DZ_R2C = NULL;
99 
100  fftw_plan_1DX_C2R = NULL;
101  fftw_plan_1DY_C2R = NULL;
102  fftw_plan_1DZ_C2R = NULL;
103 
104 }// end of ~TFFTWComplexMatrix()
105 //------------------------------------------------------------------------------
106 
107 
108 
109 /**
110  * Create an FFTW plan for 3D Real-to-Complex.
111  * @param [in,out] InMatrix - RealMatrix of which to create the plan
112  * @warning Unless FFTW_ESTIMATE flag is specified, the content of the InMatrix is destroyed!
113  * @throw runtime_error if the plan can't be created.
114  */
116 {
117  fftw_plan_3D_R2C = fftwf_plan_dft_r2c_3d(InMatrix.GetDimensionSizes().Z,
118  InMatrix.GetDimensionSizes().Y,
119  InMatrix.GetDimensionSizes().X,
120  InMatrix.GetRawData(),
121  (fftwf_complex *) pMatrixData,
123 
124  if (!fftw_plan_3D_R2C)
125  {
126  char ErrorMessage[256];
127  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_PlanNotCreated, "FFT_3D_R2C");
128  throw runtime_error(ErrorMessage);
129  }
130 }// end of Create_FFT_Plan_3D_R2C
131 //------------------------------------------------------------------------------
132 
133 /**
134  * Create an FFTW plan for 3D Complex-to-Real.
135  * @param [in, out] OutMatrix - RealMatrix of which to create the plan.
136  * @warning Unless FFTW_ESTIMATE flag is specified, the content of the InMatrix
137  * is destroyed!
138  * @throw runtime_error if the plan can't be created.
139  */
141 {
142  fftw_plan_3D_C2R = fftwf_plan_dft_c2r_3d(OutMatrix.GetDimensionSizes().Z,
143  OutMatrix.GetDimensionSizes().Y,
144  OutMatrix.GetDimensionSizes().X,
145  (fftwf_complex *) (pMatrixData),
146  OutMatrix.GetRawData(),
148 
149  if (!fftw_plan_3D_C2R)
150  {
151  char ErrorMessage[256];
152  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_PlanNotCreated, "FFT_3D_C2R");
153  throw runtime_error(ErrorMessage);
154  }
155 }//end of Create_FFT_Plan_3D_C2R
156 //------------------------------------------------------------------------------
157 
158 
159 /**
160  * Create an FFTW plan for 1D Real-to-Complex in the X dimension.
161  * There are two versions of this routine for GCC+FFTW and ICPC + MKL, otherwise it will not build!
162  * The FFTW version processes the whole matrix at one while the MKL slab by slab
163  * @param [in,out] InMatrix - RealMatrix of which to create the plan
164  * @warning Unless FFTW_ESTIMATE flag is specified, the content of the InMatrix is destroyed!
165  * @throw runtime_error if the plan can't be created.
166  */
168 {
169  // the FFTW uses here 32b interface although it is internally 64b, it doesn't mind
170  // since the size of 1 domain will never be bigger than 2^31 - however it it not a clear solution :)
171  const int X = static_cast<int> (InMatrix.GetDimensionSizes().X);
172  const int Y = static_cast<int> (InMatrix.GetDimensionSizes().Y);
173  const int Z = static_cast<int> (InMatrix.GetDimensionSizes().Z);
174  const int X_2 = ((X / 2) + 1);
175 
176  // 1D FFT definition - over the X axis
177  const int fft_rank = 1;
178  fftw_iodim fft_dims[1];
179 
180  fft_dims[0].is = 1;
181  fft_dims[0].n = X;
182  fft_dims[0].os = 1;
183 
184  // GNU Compiler + FFTW
185  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
186  // How many definition - other dims
187  const int fft_howmany_rank = 2;
188  fftw_iodim fft_howmany_dims[2];
189 
190  // Z dim
191  fft_howmany_dims[0].is = X * Y;
192  fft_howmany_dims[0].n = Z;
193  fft_howmany_dims[0].os = X_2 * Y;
194 
195  // Y dim
196  fft_howmany_dims[1].is = X;
197  fft_howmany_dims[1].n = Y;
198  fft_howmany_dims[1].os = X_2;
199  #endif
200 
201  // Intel Compiler + MKL
202  #if (defined(__INTEL_COMPILER))
203  const int fft_howmany_rank = 1;
204  fftw_iodim fft_howmany_dims[1];
205 
206  // Y dim
207  fft_howmany_dims[0].is = X;
208  fft_howmany_dims[0].n = Y;
209  fft_howmany_dims[0].os = X_2;
210  #endif
211 
212  fftw_plan_1DX_R2C = fftwf_plan_guru_dft_r2c(fft_rank, // 1D FFT rank
213  fft_dims, // 1D FFT dimensions of X
214 
215  fft_howmany_rank, // how many in Y and Z
216  fft_howmany_dims, // Dims and strides in Y and Z
217 
218  InMatrix.GetRawData(), // input data
219  (fftwf_complex *) pMatrixData, // output data
220  TFFTWComplexMatrix_FFT_FLAG); // flags
221 
222  if (!fftw_plan_1DX_R2C)
223  {
224  char ErrorMessage[256];
225  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_PlanNotCreated, "FFT_1DX_R2C");
226  throw runtime_error(ErrorMessage);
227  }
228 }// end of Create_FFT_Plan_1DX_R2C
229 //------------------------------------------------------------------------------
230 
231 
232 /**
233  * Create an FFTW plan for 1D Real-to-Complex in the Y dimension.
234  * There are two versions of this routine for GCC+FFTW and ICPC + MKL, otherwise it will not build!
235  * The FFTW version processes the whole matrix at one while the MKL slab by slab
236  * @param [in,out] InMatrix - RealMatrix of which to create the plan
237  * @warning Unless FFTW_ESTIMATE flag is specified, the content of the InMatrix
238  * is destroyed!
239  * @warning The FFTW matrix must be able to store 2 * (X * (Y/2 + 1) * Z) elements -
240  * possibly more than reduced dims!
241  * @throw runtime_error if the plan can't be created.
242  */
244 {
245  // the FFTW uses here 32b interface although it is internally 64b, it doesn't mind
246  // since the size of 1 domain will never be bigger than 2^31 - however it it not a clear solution :)
247  const int X = static_cast<int> (InMatrix.GetDimensionSizes().X);
248  const int Y = static_cast<int> (InMatrix.GetDimensionSizes().Y);
249  const int Z = static_cast<int> (InMatrix.GetDimensionSizes().Z);
250  const int Y_2 = ((Y / 2) + 1);
251 
252  // 1D FFT definition - over the Y axis
253  const int fft_rank = 1;
254  fftw_iodim fft_dims[1];
255 
256  fft_dims[0].is = X;
257  fft_dims[0].n = Y;
258  fft_dims[0].os = X;
259 
260  // GNU Compiler + FFTW
261  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
262  // How many definition - other dims
263  const int fft_howmany_rank = 2;
264  fftw_iodim fft_howmany_dims[2];
265 
266  // Z dim
267  fft_howmany_dims[0].is = X * Y;
268  fft_howmany_dims[0].n = Z;
269  fft_howmany_dims[0].os = X * Y_2 ;
270 
271  // X dim
272  fft_howmany_dims[1].is = 1;
273  fft_howmany_dims[1].n = X;
274  fft_howmany_dims[1].os = 1;
275  #endif
276 
277  // Intel Compiler + MKL
278  #if (defined(__INTEL_COMPILER))
279  const int fft_howmany_rank = 1;
280  fftw_iodim fft_howmany_dims[1];
281 
282  // X dim
283  fft_howmany_dims[0].is = 1;
284  fft_howmany_dims[0].n = X;
285  fft_howmany_dims[0].os = 1;
286  #endif
287 
288  fftw_plan_1DY_R2C = fftwf_plan_guru_dft_r2c(fft_rank, // 1D FFT rank
289  fft_dims, // 1D FFT dimensions of Y
290 
291  fft_howmany_rank, // how many in X and Z
292  fft_howmany_dims, // Dims and strides in X and Z
293 
294  InMatrix.GetRawData(), // input data
295  (fftwf_complex *) pMatrixData, // output data
296  TFFTWComplexMatrix_FFT_FLAG); // flags
297 
298  if (!fftw_plan_1DY_R2C)
299  {
300  char ErrorMessage[256];
301  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_PlanNotCreated, "FFT_1DY_R2C");
302  throw runtime_error(ErrorMessage);
303  }
304 }// end of Create_FFT_Plan_1DY_R2C
305 //------------------------------------------------------------------------------
306 
307 
308 /**
309  * Create an FFTW plan for 1D Real-to-Complex in the Z dimension.
310  * There are two versions of this routine for GCC+FFTW and ICPC + MKL, otherwise it will not build!
311  * The FFTW version processes the whole matrix at one while the MKL slab by slab
312  * @param [in,out] InMatrix - RealMatrix of which to create the plan
313  * @warning Unless FFTW_ESTIMATE flag is specified, the content of the InMatrix
314  * is destroyed!
315  * @warning The FFTW matrix must be able to store 2 * (X * Y * (Z/2+1) ) elements -
316  * possibly more than reduced dims!
317  * @throw runtime_error if the plan can't be created.
318  */
320 {
321  // the FFTW uses here 32b interface although it is internally 64b, it doesn't mind
322  // since the size of 1 domain will never be bigger than 2^31 - however it it not a clear solution :)
323  const int X = static_cast<int> (InMatrix.GetDimensionSizes().X);
324  const int Y = static_cast<int> (InMatrix.GetDimensionSizes().Y);
325  const int Z = static_cast<int> (InMatrix.GetDimensionSizes().Z);
326 
327  // 1D FFT definition - over the Y axis
328  const int fft_rank = 1;
329  fftw_iodim fft_dims[1];
330 
331  fft_dims[0].is = X * Y;
332  fft_dims[0].n = Z;
333  fft_dims[0].os = X * Y;
334 
335  // GNU Compiler + FFTW
336  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
337  // How many definition - other dims
338  const int fft_howmany_rank = 2;
339  fftw_iodim fft_howmany_dims[2];
340 
341  // Y dim
342  fft_howmany_dims[0].is = X;
343  fft_howmany_dims[0].n = Y;
344  fft_howmany_dims[0].os = X;
345 
346  // X dim
347  fft_howmany_dims[1].is = 1;
348  fft_howmany_dims[1].n = X;
349  fft_howmany_dims[1].os = 1;
350  #endif
351 
352  // Intel Compiler + MKL
353  #if (defined(__INTEL_COMPILER))
354  const int fft_howmany_rank = 1;
355  fftw_iodim fft_howmany_dims[1];
356 
357  // X dim
358  fft_howmany_dims[0].is = 1;
359  fft_howmany_dims[0].n = X;
360  fft_howmany_dims[0].os = 1;
361  #endif
362 
363  fftw_plan_1DZ_R2C = fftwf_plan_guru_dft_r2c(fft_rank, // 1D FFT rank
364  fft_dims, // 1D FFT dimensions of Y
365 
366  fft_howmany_rank, // how many in X and Z
367  fft_howmany_dims, // Dims and strides in X and Z
368 
369  InMatrix.GetRawData(), // input data
370  (fftwf_complex *) pMatrixData, // output data
371  TFFTWComplexMatrix_FFT_FLAG); // flags
372 
373  if (!fftw_plan_1DZ_R2C)
374  {
375  char ErrorMessage[256];
376  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_PlanNotCreated, "FFT_1DZ_R2C");
377  throw runtime_error(ErrorMessage);
378  }
379 }// end of Create_FFT_Plan_1DZ_R2C
380 //------------------------------------------------------------------------------
381 
382 
383 /**
384  * Create FFTW plan for Complex-to-Real in the X dimension.
385  * There are two versions of this routine for GCC+FFTW and ICPC + MKL, otherwise it will not build!
386  * The FFTW version processes the whole matrix at one while the MKL slab by slab
387  * @param [in, out] OutMatrix - RealMatrix of which to create the plan.
388  * @warning Unless FFTW_ESTIMATE flag is specified, the content of the InMatrix
389  * is destroyed!
390  * @throw runtime_error if the plan can't be created.
391  */
393 {
394  // the FFTW uses here 32b interface although it is internally 64b, it doesn't mind
395  // since the size of 1 domain will never be bigger than 2^31 - however it it not a clear solution :)
396  const int X = static_cast<int> (OutMatrix.GetDimensionSizes().X);
397  const int Y = static_cast<int> (OutMatrix.GetDimensionSizes().Y);
398  const int Z = static_cast<int> (OutMatrix.GetDimensionSizes().Z);
399  const int X_2 = ((X / 2) + 1);
400 
401  // 1D FFT definition - over the X axis
402  const int fft_rank = 1;
403  fftw_iodim fft_dims[1];
404 
405  fft_dims[0].is = 1;
406  fft_dims[0].n = X;
407  fft_dims[0].os = 1;
408 
409  // GNU Compiler + FFTW
410  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
411  // How many definition - other dims
412  const int fft_howmany_rank = 2;
413  fftw_iodim fft_howmany_dims[2];
414 
415  // Z dim
416  fft_howmany_dims[0].is = X_2 * Y;
417  fft_howmany_dims[0].n = Z;
418  fft_howmany_dims[0].os = X * Y;
419 
420  // Y dim
421  fft_howmany_dims[1].is = X_2;
422  fft_howmany_dims[1].n = Y;
423  fft_howmany_dims[1].os = X;
424  #endif
425 
426  // Intel Compiler + MKL
427  #if (defined(__INTEL_COMPILER))
428  const int fft_howmany_rank = 1;
429  fftw_iodim fft_howmany_dims[1];
430 
431  // Y dim
432  fft_howmany_dims[0].is = X_2;
433  fft_howmany_dims[0].n = Y;
434  fft_howmany_dims[0].os = X;
435  #endif
436 
437  fftw_plan_1DX_C2R = fftwf_plan_guru_dft_c2r(fft_rank, // 1D FFT rank
438  fft_dims, // 1D FFT dimensions of X
439 
440  fft_howmany_rank, // how many in Y and Z
441  fft_howmany_dims, // Dims and strides in Y and Z
442 
443  (fftwf_complex *) pMatrixData, // input data
444  OutMatrix.GetRawData(), // output data
445  TFFTWComplexMatrix_FFT_FLAG); // flags
446 
447  if (!fftw_plan_1DX_C2R)
448  {
449  char ErrorMessage[256];
450  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_PlanNotCreated, "FFT_1DX_C2R");
451  throw runtime_error(ErrorMessage);
452  }
453 }// end of Create_FFT_Plan_1DX_C2R
454 //------------------------------------------------------------------------------
455 
456 
457 
458 /**
459  * Create FFTW plan for Complex-to-Real in the Y dimension.
460  * There are two versions of this routine for GCC+FFTW and ICPC + MKL, otherwise it will not build!
461  * The FFTW version processes the whole matrix at one while the MKL slab by slab
462  * @param [in, out] OutMatrix - RealMatrix of which to create the plan.
463  * @warning Unless FFTW_ESTIMATE flag is specified, the content of the InMatrix is destroyed!
464  * @throw runtime_error if the plan can't be created.
465  */
467 {
468  // the FFTW uses here 32b interface although it is internally 64b, it doesn't mind
469  // since the size of 1 domain will never be bigger than 2^31 - however it it not a clear solution :)
470  const int X = static_cast<int> (OutMatrix.GetDimensionSizes().X);
471  const int Y = static_cast<int> (OutMatrix.GetDimensionSizes().Y);
472  const int Z = static_cast<int> (OutMatrix.GetDimensionSizes().Z);
473  const int Y_2 = ((Y / 2) + 1);
474 
475  // 1D FFT definition - over the Y axis
476  const int fft_rank = 1;
477 
478  fftw_iodim fft_dims[1];
479  fft_dims[0].is = X;
480  fft_dims[0].n = Y;
481  fft_dims[0].os = X;
482 
483  // GNU Compiler + FFTW
484  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
485  // How many definition - other dims
486  const int fft_howmany_rank = 2;
487  fftw_iodim fft_howmany_dims[2];
488 
489  // Z dim
490  fft_howmany_dims[0].is = X * Y_2;
491  fft_howmany_dims[0].n = Z;
492  fft_howmany_dims[0].os = X * Y;
493 
494  // X dim
495  fft_howmany_dims[1].is = 1;
496  fft_howmany_dims[1].n = X;
497  fft_howmany_dims[1].os = 1;
498  #endif
499 
500 // Intel Compiler + MKL
501  #if (defined(__INTEL_COMPILER))
502  const int fft_howmany_rank = 1;
503  fftw_iodim fft_howmany_dims[1];
504 
505  // X dim
506  fft_howmany_dims[0].is = 1;
507  fft_howmany_dims[0].n = X;
508  fft_howmany_dims[0].os = 1;
509  #endif
510 
511  fftw_plan_1DY_C2R = fftwf_plan_guru_dft_c2r(fft_rank, // 1D FFT rank
512  fft_dims, // 1D FFT dimensions of Y
513 
514  fft_howmany_rank, // how many in X and Z
515  fft_howmany_dims, // Dims and strides in X and Z
516 
517  (fftwf_complex *) pMatrixData, // input data
518  OutMatrix.GetRawData(), // output data
519  TFFTWComplexMatrix_FFT_FLAG); // flags
520 
521  if (!fftw_plan_1DY_C2R)
522  {
523  char ErrorMessage[256];
524  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_PlanNotCreated, "FFT_1DY_C2R");
525  throw runtime_error(ErrorMessage);
526  }
527 }// end of Create_FFT_Plan_1DY_C2R
528 //------------------------------------------------------------------------------
529 
530 
531 /**
532  * Create FFTW plan for Complex-to-Real in the Z dimension.
533  * There are two versions of this routine for GCC+FFTW and ICPC + MKL, otherwise it will not build!
534  * The FFTW version processes the whole matrix at one while the MKL slab by slab
535  * @param [in, out] OutMatrix - RealMatrix of which to create the plan.
536  * @warning Unless FFTW_ESTIMATE flag is specified, the content of the InMatrix is destroyed!
537  * @throw runtime_error if the plan can't be created.
538  */
540 {
541  // the FFTW uses here 32b interface although it is internally 64b, it doesn't mind
542  // since the size of 1 domain will never be bigger than 2^31 - however it it not a clear solution :)
543  const int X = static_cast<int> (OutMatrix.GetDimensionSizes().X);
544  const int Y = static_cast<int> (OutMatrix.GetDimensionSizes().Y);
545  const int Z = static_cast<int> (OutMatrix.GetDimensionSizes().Z);
546 
547  // 1D FFT definition - over the Y axis
548  const int fft_rank = 1;
549  fftw_iodim fft_dims[1];
550 
551  fft_dims[0].is = X * Y;
552  fft_dims[0].n = Z;
553  fft_dims[0].os = X * Y;
554 
555  // GNU Compiler + FFTW
556  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
557  // How many definition - other dims
558  const int fft_howmany_rank = 2;
559  fftw_iodim fft_howmany_dims[2];
560 
561  // Y dim
562  fft_howmany_dims[0].is = X;
563  fft_howmany_dims[0].n = Y;
564  fft_howmany_dims[0].os = X;
565 
566  // X dim
567  fft_howmany_dims[1].is = 1;
568  fft_howmany_dims[1].n = X;
569  fft_howmany_dims[1].os = 1;
570  #endif
571 
572  // Intel Compiler + MKL
573  #if (defined(__INTEL_COMPILER))
574  const int fft_howmany_rank = 1;
575  fftw_iodim fft_howmany_dims[1];
576 
577  // X dim
578  fft_howmany_dims[0].is = 1;
579  fft_howmany_dims[0].n = X;
580  fft_howmany_dims[0].os = 1;
581  #endif
582 
583  fftw_plan_1DZ_C2R = fftwf_plan_guru_dft_c2r(fft_rank, // 1D FFT rank
584  fft_dims, // 1D FFT dimensions of Y
585 
586  fft_howmany_rank, // how many in X and Z
587  fft_howmany_dims, // Dims and strides in X and Z
588 
589  (fftwf_complex *) pMatrixData, // input data
590  OutMatrix.GetRawData(), // output data
591  TFFTWComplexMatrix_FFT_FLAG); // flags
592 
593  if (!fftw_plan_1DZ_C2R)
594  {
595  char ErrorMessage[256];
596  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_PlanNotCreated, "FFT_1DZ_C2R");
597  throw runtime_error(ErrorMessage);
598  }
599 }// end of Create_FFT_Plan_1DZ_C2R
600 //------------------------------------------------------------------------------
601 
602 
603 /**
604  * Computer forward out-of place 3D Real-to-Complex FFT.
605  * @param [in] InMatrix - Input Matrix
606  * @throw runtime_error if the plan is not valid.
607  */
609 {
610  if (fftw_plan_3D_R2C)
611  {
612  fftwf_execute_dft_r2c(fftw_plan_3D_R2C, InMatrix.GetRawData(), (fftwf_complex *) pMatrixData);
613  }
614  else //error
615  {
616  char ErrorMessage[256];
617  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_InvalidPlan, "FFT_3D_R2C");
618  throw runtime_error(ErrorMessage);
619  }
620 }// end of Compute_FFT_3D_R2C
621 //------------------------------------------------------------------------------
622 
623 /**
624  * Compute inverse out-of-place 3D Complex to Real FFT.
625  * @param [out] OutMatrix
626  * @throw runtime_error if the plan is not valid.
627  */
629 {
630  if (fftw_plan_3D_C2R)
631  {
632  fftwf_execute_dft_c2r(fftw_plan_3D_C2R,(fftwf_complex *) pMatrixData, OutMatrix.GetRawData());
633  }
634  else // error
635  {
636  char ErrorMessage[256];
637  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_InvalidPlan, "FFT_3D_C2R");
638  throw runtime_error(ErrorMessage);
639  }
640 }// end of Compute_FFT_3D_C2R
641 //------------------------------------------------------------------------------
642 
643 
644 
645 /**
646  * Compute 1D out-of-place Real-to-Complex FFT in the X dimension.
647  * There are two versions of this routine for GCC+FFTW and ICPC + MKL, otherwise it will not build!
648  * The FFTW version processes the whole matrix at one while the MKL slab by slab
649  * @param [in] InMatrix
650  * @throw runtime_error if the plan is not valid.
651  */
653 {
654  if (fftw_plan_1DX_R2C)
655  {
656  // GNU Compiler + FFTW
657  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
658  fftwf_execute_dft_r2c(fftw_plan_1DX_R2C,
659  InMatrix.GetRawData(),
660  (fftwf_complex *) pMatrixData);
661  #endif
662 
663  // Intel Compiler + MKL
664  #if (defined(__INTEL_COMPILER))
666  for (size_t slab_id = 0; slab_id < Dims.Z; slab_id++)
667  {
668  fftwf_execute_dft_r2c(fftw_plan_1DX_R2C,
669  &InMatrix.GetRawData()[slab_id * Dims.X * Dims.Y],
670  (fftwf_complex *) &pMatrixData[slab_id * 2 * (Dims.X/2 + 1) * Dims.Y]);
671  }
672  #endif
673  }
674  else //error
675  {
676  char ErrorMessage[256];
677  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_InvalidPlan, "FFT_1DX_R2C");
678  throw runtime_error(ErrorMessage);
679  }
680 }// end of Compute_FFT_1DX_R2C
681 //------------------------------------------------------------------------------
682 
683 /**
684  * Compute 1D out-of-place Real-to-Complex FFT in the Y dimension.
685  * @param [in] InMatrix
686  * @throw runtime_error if the plan is not valid.
687  */
689 {
690  if (fftw_plan_1DY_R2C)
691  {
692  // GNU Compiler + FFTW
693  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
694  fftwf_execute_dft_r2c(fftw_plan_1DY_R2C,
695  InMatrix.GetRawData(),
696  (fftwf_complex *) pMatrixData);
697  #endif
698 
699  // Intel Compiler + MKL
700  #if (defined(__INTEL_COMPILER))
702  for (size_t slab_id = 0; slab_id < Dims.Z; slab_id++)
703  {
704  fftwf_execute_dft_r2c(fftw_plan_1DY_R2C,
705  &InMatrix.GetRawData()[slab_id * Dims.X * Dims.Y],
706  (fftwf_complex *) &pMatrixData[slab_id * Dims.X * 2 * (Dims.Y/2 + 1)]);
707  }
708  #endif
709  }
710  else //error
711  {
712  char ErrorMessage[256];
713  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_InvalidPlan, "FFT_1DY_R2C");
714  throw runtime_error(ErrorMessage);
715  }
716 }// end of Compute_FFT_1DY_R2C
717 //------------------------------------------------------------------------------
718 
719 /**
720  * Compute 1D out-of-place Real-to-Complex FFT in the Z dimension.
721  * @param [in] InMatrix
722  * @throw runtime_error if the plan is not valid.
723  */
725 {
726  if (fftw_plan_1DZ_R2C)
727  {
728  // GNU Compiler + FFTW
729  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
730  fftwf_execute_dft_r2c(fftw_plan_1DZ_R2C,
731  InMatrix.GetRawData(),
732  (fftwf_complex *) pMatrixData);
733  #endif
734 
735  // Intel Compiler + MKL
736  #if (defined(__INTEL_COMPILER))
738  for (size_t slab_id = 0; slab_id < Dims.Y; slab_id++)
739  {
740  fftwf_execute_dft_r2c(fftw_plan_1DZ_R2C,
741  &InMatrix.GetRawData()[slab_id * Dims.X],
742  (fftwf_complex *) &pMatrixData[slab_id * 2 * Dims.X]);
743  }
744  #endif
745  }
746  else //error
747  {
748  char ErrorMessage[256];
749  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_InvalidPlan, "FFT_1DZ_R2C");
750  throw runtime_error(ErrorMessage);
751  }
752 }// end of Compute_FFT_1DZ_R2C
753 //------------------------------------------------------------------------------
754 
755 
756 /**
757  * Compute 1D out-of-place Complex-to-Real FFT in the X dimension.
758  * @param [out] OutMatrix
759  * @throw runtime_error if the plan is not valid.
760  */
762 {
763  if (fftw_plan_1DX_C2R)
764  {
765  // GNU Compiler + FFTW
766  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
767  fftwf_execute_dft_c2r(fftw_plan_1DX_C2R,
768  (fftwf_complex *) pMatrixData,
769  OutMatrix.GetRawData());
770  #endif
771 
772  // Intel Compiler + MKL
773  #if (defined(__INTEL_COMPILER))
775  for (size_t slab_id = 0; slab_id < Dims.Z; slab_id++)
776  {
777  fftwf_execute_dft_c2r(fftw_plan_1DX_C2R,
778  (fftwf_complex *) &pMatrixData[slab_id * 2 * (Dims.X/2 + 1) * Dims.Y],
779  &OutMatrix.GetRawData()[slab_id * Dims.X * Dims.Y]);
780  }
781  #endif
782  }
783  else //error
784  {
785  char ErrorMessage[256];
786  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_InvalidPlan, "FFT_1DX_C2R");
787  throw runtime_error(ErrorMessage);
788  }
789 }// end of Compute_FFT_1DX_C2R
790 //------------------------------------------------------------------------------
791 
792 /**
793  * Compute 1D out-of-place Complex-to-Real FFT in the Y dimension.
794  * @param [out] OutMatrix
795  * @throw runtime_error if the plan is not valid.
796  */
798 {
799  if (fftw_plan_1DY_C2R)
800  {
801  // GNU Compiler + FFTW
802  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
803  fftwf_execute_dft_c2r(fftw_plan_1DY_C2R,
804  (fftwf_complex *) pMatrixData,
805  OutMatrix.GetRawData());
806  #endif
807 
808  // Intel Compiler + MKL
809  #if (defined(__INTEL_COMPILER))
811  for (size_t slab_id = 0; slab_id < Dims.Z; slab_id++)
812  {
813  fftwf_execute_dft_c2r(fftw_plan_1DY_C2R,
814  (fftwf_complex *) &pMatrixData[slab_id * Dims.X * 2 * (Dims.Y/2 + 1) ],
815  &OutMatrix.GetRawData()[slab_id * Dims.X * Dims.Y]);
816  }
817  #endif
818  }
819  else //error
820  {
821  char ErrorMessage[256];
822  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_InvalidPlan, "FFT_1DY_C2R");
823  throw runtime_error(ErrorMessage);
824  }
825 }// end of Compute_FFT_1DY_C2R
826 //------------------------------------------------------------------------------
827 
828 /**
829  * Compute 1D out-of-place Complex-to-Real FFT in the Z dimension
830  * @param [out] OutMatrix
831  * @throw runtime_error if the plan is not valid.
832  */
834 {
835  if (fftw_plan_1DZ_C2R)
836  {
837  // GNU Compiler + FFTW
838  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
839  fftwf_execute_dft_c2r(fftw_plan_1DZ_C2R,
840  (fftwf_complex *) pMatrixData,
841  OutMatrix.GetRawData());
842  #endif
843 
844  // Intel Compiler + MKL
845  #if (defined(__INTEL_COMPILER))
847  for (size_t slab_id = 0; slab_id < Dims.Y; slab_id++)
848  {
849  fftwf_execute_dft_c2r(fftw_plan_1DZ_C2R,
850  (fftwf_complex *) &pMatrixData[slab_id * 2 * Dims.X ],
851  &OutMatrix.GetRawData()[slab_id * Dims.X]);
852  }
853  #endif
854  }
855  else //error
856  {
857  char ErrorMessage[256];
858  sprintf(ErrorMessage, FFTWComplexMatrix_ERR_FMT_InvalidPlan, "FFT_1DZ_C2R");
859  throw runtime_error(ErrorMessage);
860  }
861 }// end of Compute_FFT_1DZ_C2R
862 //------------------------------------------------------------------------------
863 
864 
865 /**
866  * Export wisdom to the file.
867  * @warning This routine is supported only while compiling with the GNU C++ compiler.
868  */
870 {
871  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
872  int success = fftwf_export_wisdom_to_filename(GetWisdomFileName().c_str());
873 
874  if (success == 0)
875  {
876  fprintf(stderr,FFTW_WARNING_FMT_WisdomNotExported);
877  }
878  #endif
879 }// end of ExportWisdom
880 //------------------------------------------------------------------------------
881 
882 
883 
884 /**
885  * Import wisdom from the file.
886  * @warning This routine is supported only while compiling with the GNU C++ compiler.
887  */
889 {
890  #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER))
891  int success = fftwf_import_wisdom_from_filename(GetWisdomFileName().c_str());
892  if (success == 0)
893  {
894  fprintf(stderr,FFTW_WARNING_FMT_WisdomNotImported);
895  }
896  #endif
897 }// end of Import wisdom
898 //------------------------------------------------------------------------------
899 
900 /**
901  * Delete stored wisdom (delete the file).
902  */
904 {
905  std::remove(GetWisdomFileName().c_str());
906 }// end of DeleteStoredWisdom
907 //------------------------------------------------------------------------------
908 
909 
910 //----------------------------------------------------------------------------//
911 // Protected methods //
912 //----------------------------------------------------------------------------//
913 
914 /**
915  * Allocate Memory using fftwf_malloc function to ensure correct alignment.
916  *
917  */
919 {
920  /* No memory allocated before this function*/
921  pMatrixData = (float *) fftwf_malloc(pTotalAllocatedElementCount * sizeof (float));
922 
923  if (!pMatrixData)
924  {
925  fprintf(stderr,Matrix_ERR_FMT_NotEnoughMemory, "TFFTWComplexMatrix");
926  throw bad_alloc();
927  }
928 
929  // first touch
930  #pragma omp parallel for schedule(static)
931  for (size_t i=0; i<pTotalAllocatedElementCount; i++)
932  {
933  pMatrixData[i] = 0.0f;
934  }
935 }// end of AllocateMemory
936 //------------------------------------------------------------------------------
937 
938 
939  /**
940  * Free memory using fftwf_free.
941  */
943 {
944  if (pMatrixData) fftwf_free( pMatrixData);
945  pMatrixData = NULL;
946  }// end of FreeMemory
947  //-----------------------------------------------------------------------------
948 
949 /**
950  * Get Wisdom file name (derive it form the checkpoint filename).
951  * @return the filename for wisdom.
952  */
954 {
955  string FileName = TParameters::GetInstance()->GetCheckpointFileName();
956  FileName.erase(FileName.find_last_of("."), string::npos);
957 
958  FileName.append(".");
959  FileName.append(FFTW_Wisdom_FileName_Extension);
960 
961  return FileName;
962 }// end of GetWisdomFileName
963 //------------------------------------------------------------------------------
964 
965 
966 
967 //----------------------------------------------------------------------------//
968 // Private methods //
969 //----------------------------------------------------------------------------//
size_t Z
Z dimension size.
virtual float * GetRawData()
Get raw data out of the class (for direct kernel access).
const char *const FFTWComplexMatrix_ERR_FMT_InvalidPlan
FFTW error message.
static void ExportWisdom()
Export wisdom to the file.
virtual void FreeMemory()
Free memory of the FFTW matrix.
fftwf_plan fftw_plan_1DY_R2C
FFTW plan for the 3D Real-to-Complex transform in the Y dimension.
void Compute_FFT_1DY_R2C(TRealMatrix &InMatrix)
Compute 1D out-of-place Real-to-Complex FFT in the Y dimension.
static const unsigned TFFTWComplexMatrix_FFT_FLAG
FFTW plan flag.
void Create_FFT_Plan_1DZ_C2R(TRealMatrix &OutMatrix)
Create FFTW plan for Complex-to-Real in the Z dimension.
void Compute_FFT_1DX_C2R(TRealMatrix &OutMatrix)
Compute 1D out-of-place Complex-to-Real FFT in the X dimension.
void Create_FFT_Plan_1DY_R2C(TRealMatrix &InMatrix)
Create FFTW plan for Real-to-Complex in the Y dimension.
The header file containing the class for real matrices.
void Create_FFT_Plan_3D_R2C(TRealMatrix &InMatrix)
Create FFTW plan for Real-to-Complex.
void Compute_FFT_1DZ_C2R(TRealMatrix &OutMatrix)
Compute 1D out-of-place Complex-to-Real FFT in the Z dimension.
fftwf_plan fftw_plan_1DZ_R2C
FFTW plan for the 3D Real-to-Complex transform in the Z dimension.
fftwf_plan fftw_plan_3D_R2C
FFTW plan for the 3D Real-to-Complex transform.
virtual void AllocateMemory()
Allocate memory for the FFTW matrix.
string GetCheckpointFileName() const
Get checkpoint filename.
Definition: Parameters.h:205
virtual void InitDimensions(const TDimensionSizes &DimensionSizes)
Initialize dimension sizes and related structures.
fftwf_plan fftw_plan_3D_C2R
FFTW plan for the 3D Complex-to-Real transform.
size_t X
X dimension size.
The header file containing the parameters of the simulation.
TFFTWComplexMatrix()
Default constructor not allowed for public.
void Create_FFT_Plan_1DX_R2C(TRealMatrix &InMatrix)
Create FFTW plan for Real-to-Complex in the X dimension.
size_t pTotalAllocatedElementCount
Total number of allocated elements (in terms of floats).
virtual TDimensionSizes GetDimensionSizes() const
Get dimension sizes of the matrix.
const char *const FFTW_WARNING_FMT_WisdomNotImported
FFTW error message.
void Create_FFT_Plan_1DZ_R2C(TRealMatrix &InMatrix)
Create FFTW plan for Real-to-Complex in the Z dimension.
TDimensionSizes GetFullDimensionSizes() const
Full dimension sizes of the simulation (real classes).
Definition: Parameters.h:84
void Compute_FFT_3D_C2R(TRealMatrix &OutMatrix)
Compute 3D out-of-place Complex-to-Real FFT.
void Compute_FFT_1DX_R2C(TRealMatrix &InMatrix)
Compute 1D out-of-place Real-to-Complex FFT in the X dimension.
static void DeleteStoredWisdom()
Destroy wisdom in the file (delete it).
fftwf_plan fftw_plan_1DZ_C2R
FFTW plan for the 3Z Complex-to-Real transform in the Z dimension.
void Create_FFT_Plan_1DY_C2R(TRealMatrix &OutMatrix)
Create FFTW plan for Complex-to-Real in the Y dimension.
void Compute_FFT_1DY_C2R(TRealMatrix &OutMatrix)
Compute 1D out-of-place Complex-to-Real FFT in the Y dimension.
static string GetWisdomFileName()
Get Wisdom file name, base on the checkpoint filename.
The header file containing all error messages of the project.
static void ImportWisdom()
Import wisdom from the file.
const char *const FFTWComplexMatrix_ERR_FMT_PlanNotCreated
FFTW error message.
const char *const FFTW_WARNING_FMT_WisdomNotExported
FFTW error message.
The class for real matrices.
Definition: RealMatrix.h:48
size_t Y
Y dimension size.
static const string FFTW_Wisdom_FileName_Extension
The file extension for FFTW wisdom.
void Compute_FFT_1DZ_R2C(TRealMatrix &InMatrix)
Compute 1D out-of-place Real-to-Complex FFT in the Z dimension.
void Create_FFT_Plan_3D_C2R(TRealMatrix &OutMatrix)
Create FFTW plan for Complex-to-Real.
void Compute_FFT_3D_R2C(TRealMatrix &InMatrix)
Compute 3D out-of-place Real-to-Complex FFT.
fftwf_plan fftw_plan_1DX_C2R
FFTW plan for the 3D Complex-to-Real transform in the X dimension.
fftwf_plan fftw_plan_1DY_C2R
FFTW plan for the 3D Complex-to-Real transform in the Y dimension.
fftwf_plan fftw_plan_1DX_R2C
FFTW plan for the 1D Real-to-Complex transform in the X dimension.
The class for complex matrices.
Definition: ComplexMatrix.h:64
float * pMatrixData
Raw matrix data.
const char *const Matrix_ERR_FMT_NotEnoughMemory
Matrix class error message.
Definition: ErrorMessages.h:81
void Create_FFT_Plan_1DX_C2R(TRealMatrix &OutMatrix)
Create FFTW plan for Complex-to-Real in the X dimension.
virtual ~TFFTWComplexMatrix()
Destructor.
Structure with 4D dimension sizes (3 in space and 1 in time).
The header file containing the class that implements 3D FFT using the FFTW interface.
static TParameters * GetInstance()
Get instance of the singleton class.
Definition: Parameters.cpp:74