1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * Gromacs 4.0 Copyright (c) 1991-2003
5 * David van der Spoel, Erik Lindahl, University of Groningen.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * To help us fund GROMACS development, we humbly ask that you cite
13 * the research papers on the package. Check out http://www.gromacs.org
16 * Gnomes, ROck Monsters And Chili Sauce
31 #include "gmx_fatal.h"
34 /* For MKL version (<10.0), we should define MKL_LONG. */
36 #define MKL_LONG long int
41 #define GMX_DFTI_PREC DFTI_DOUBLE
43 #define GMX_DFTI_PREC DFTI_SINGLE
46 /* Contents of the Intel MKL FFT fft datatype.
48 * Note that this is one of several possible implementations of gmx_fft_t.
50 * The MKL _API_ supports 1D,2D, and 3D transforms, including real-to-complex.
51 * Unfortunately the actual library implementation does not support 3D real
52 * transforms as of version 7.2, and versions before 7.0 don't support 2D real
53 * either. In addition, the multi-dimensional storage format for real data
54 * is not compatible with our padding.
56 * To work around this we roll our own 2D and 3D real-to-complex transforms,
57 * using separate X/Y/Z handles defined to perform (ny*nz), (nx*nz), and
58 * (nx*ny) transforms at once when necessary. To perform strided multiple
59 * transforms out-of-place (i.e., without padding in the last dimension)
60 * on the fly we also need to separate the forward and backward
61 * handles for real-to-complex/complex-to-real data permutation.
63 * This makes it necessary to define 3 handles for in-place FFTs, and 4 for
64 * the out-of-place transforms. Still, whenever possible we try to use
65 * a single 3D-transform handle instead.
67 * So, the handles are enumerated as follows:
69 * 1D FFT (real too): Index 0 is the handle for the entire FFT
70 * 2D complex FFT: Index 0 is the handle for the entire FFT
71 * 3D complex FFT: Index 0 is the handle for the entire FFT
72 * 2D, inplace real FFT: 0=FFTx, 1=FFTy handle
73 * 2D, ooplace real FFT: 0=FFTx, 1=real-to-complex FFTy, 2=complex-to-real FFTy
74 * 3D, inplace real FFT: 0=FFTx, 1=FFTy, 2=FFTz handle
75 * 3D, ooplace real FFT: 0=FFTx, 1=FFTy, 2=r2c FFTz, 3=c2r FFTz
77 * Intel people reading this: Learn from FFTW what a good interface looks like :-)
82 int ndim
; /**< Number of dimensions in FFT */
83 int nx
; /**< Length of X transform */
84 int ny
; /**< Length of Y transform */
85 int nz
; /**< Length of Z transform */
86 int real_fft
; /**< 1 if real FFT, otherwise 0 */
87 DFTI_DESCRIPTOR
* inplace
[3]; /**< in-place FFT */
88 DFTI_DESCRIPTOR
* ooplace
[4]; /**< out-of-place FFT */
89 t_complex
* work
; /**< Enable out-of-place c2r FFT */
95 gmx_fft_init_1d(gmx_fft_t
* pfft
,
105 gmx_fatal(FARGS
,"Invalid opaque FFT datatype pointer.");
110 if( (fft
= (gmx_fft_t
)malloc(sizeof(struct gmx_fft
))) == NULL
)
115 /* Mark all handles invalid */
118 fft
->inplace
[d
] = fft
->ooplace
[d
] = NULL
;
120 fft
->ooplace
[3] = NULL
;
123 status
= DftiCreateDescriptor(&fft
->inplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,1,(MKL_LONG
)nx
);
126 status
= DftiSetValue(fft
->inplace
[0],DFTI_PLACEMENT
,DFTI_INPLACE
);
129 status
= DftiCommitDescriptor(fft
->inplace
[0]);
133 status
= DftiCreateDescriptor(&fft
->ooplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,1,(MKL_LONG
)nx
);
136 DftiSetValue(fft
->ooplace
[0],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
);
139 DftiCommitDescriptor(fft
->ooplace
[0]);
144 gmx_fatal(FARGS
,"Error initializing Intel MKL FFT; status=%d",status
);
145 gmx_fft_destroy(fft
);
161 gmx_fft_init_1d_real(gmx_fft_t
* pfft
,
171 gmx_fatal(FARGS
,"Invalid opaque FFT datatype pointer.");
176 if( (fft
= (gmx_fft_t
)malloc(sizeof(struct gmx_fft
))) == NULL
)
181 /* Mark all handles invalid */
184 fft
->inplace
[d
] = fft
->ooplace
[d
] = NULL
;
186 fft
->ooplace
[3] = NULL
;
188 status
= DftiCreateDescriptor(&fft
->inplace
[0],GMX_DFTI_PREC
,DFTI_REAL
,1,(MKL_LONG
)nx
);
191 status
= DftiSetValue(fft
->inplace
[0],DFTI_PLACEMENT
,DFTI_INPLACE
);
194 status
= DftiCommitDescriptor(fft
->inplace
[0]);
198 status
= DftiCreateDescriptor(&fft
->ooplace
[0],GMX_DFTI_PREC
,DFTI_REAL
,1,(MKL_LONG
)nx
);
201 status
= DftiSetValue(fft
->ooplace
[0],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
);
204 status
= DftiCommitDescriptor(fft
->ooplace
[0]);
207 if(status
== DFTI_UNIMPLEMENTED
)
210 "The linked Intel MKL version (<6.0?) cannot do real FFTs.");
211 gmx_fft_destroy(fft
);
218 gmx_fatal(FARGS
,"Error initializing Intel MKL FFT; status=%d",status
);
219 gmx_fft_destroy(fft
);
235 gmx_fft_init_2d(gmx_fft_t
* pfft
,
247 gmx_fatal(FARGS
,"Invalid opaque FFT datatype pointer.");
252 if( (fft
= (gmx_fft_t
)malloc(sizeof(struct gmx_fft
))) == NULL
)
257 /* Mark all handles invalid */
260 fft
->inplace
[d
] = fft
->ooplace
[d
] = NULL
;
262 fft
->ooplace
[3] = NULL
;
267 status
= DftiCreateDescriptor(&fft
->inplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,2,length
);
270 status
= DftiSetValue(fft
->inplace
[0],DFTI_PLACEMENT
,DFTI_INPLACE
);
273 status
= DftiCommitDescriptor(fft
->inplace
[0]);
277 status
= DftiCreateDescriptor(&fft
->ooplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,2,length
);
280 status
= DftiSetValue(fft
->ooplace
[0],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
);
283 status
= DftiCommitDescriptor(fft
->ooplace
[0]);
288 gmx_fatal(FARGS
,"Error initializing Intel MKL FFT; status=%d",status
);
289 gmx_fft_destroy(fft
);
306 gmx_fft_init_2d_real(gmx_fft_t
* pfft
,
319 gmx_fatal(FARGS
,"Invalid opaque FFT datatype pointer.");
324 if( (fft
= (gmx_fft_t
)malloc(sizeof(struct gmx_fft
))) == NULL
)
331 /* Mark all handles invalid */
334 fft
->inplace
[d
] = fft
->ooplace
[d
] = NULL
;
336 fft
->ooplace
[3] = NULL
;
338 /* Roll our own 2D real transform using multiple transforms in MKL,
339 * since the current MKL versions does not support our storage format,
340 * and all but the most recent don't even have 2D real FFTs.
344 status
= DftiCreateDescriptor(&fft
->inplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,1,(MKL_LONG
)nx
);
352 (DftiSetValue(fft
->inplace
[0],DFTI_PLACEMENT
,DFTI_INPLACE
) ||
353 DftiSetValue(fft
->inplace
[0],DFTI_NUMBER_OF_TRANSFORMS
,nyc
) ||
354 DftiSetValue(fft
->inplace
[0],DFTI_INPUT_DISTANCE
,1) ||
355 DftiSetValue(fft
->inplace
[0],DFTI_INPUT_STRIDES
,stride
) ||
356 DftiSetValue(fft
->inplace
[0],DFTI_OUTPUT_DISTANCE
,1) ||
357 DftiSetValue(fft
->inplace
[0],DFTI_OUTPUT_STRIDES
,stride
));
361 status
= DftiCommitDescriptor(fft
->inplace
[0]);
363 /* Out-of-place X FFT */
365 status
= DftiCreateDescriptor(&(fft
->ooplace
[0]),GMX_DFTI_PREC
,DFTI_COMPLEX
,1,(MKL_LONG
)nx
);
373 (DftiSetValue(fft
->ooplace
[0],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
) ||
374 DftiSetValue(fft
->ooplace
[0],DFTI_NUMBER_OF_TRANSFORMS
,nyc
) ||
375 DftiSetValue(fft
->ooplace
[0],DFTI_INPUT_DISTANCE
,1) ||
376 DftiSetValue(fft
->ooplace
[0],DFTI_INPUT_STRIDES
,stride
) ||
377 DftiSetValue(fft
->ooplace
[0],DFTI_OUTPUT_DISTANCE
,1) ||
378 DftiSetValue(fft
->ooplace
[0],DFTI_OUTPUT_STRIDES
,stride
));
382 status
= DftiCommitDescriptor(fft
->ooplace
[0]);
387 status
= DftiCreateDescriptor(&fft
->inplace
[1],GMX_DFTI_PREC
,DFTI_REAL
,1,(MKL_LONG
)ny
);
395 (DftiSetValue(fft
->inplace
[1],DFTI_PLACEMENT
,DFTI_INPLACE
) ||
396 DftiSetValue(fft
->inplace
[1],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)nx
) ||
397 DftiSetValue(fft
->inplace
[1],DFTI_INPUT_DISTANCE
,2*nyc
) ||
398 DftiSetValue(fft
->inplace
[1],DFTI_INPUT_STRIDES
,stride
) ||
399 DftiSetValue(fft
->inplace
[1],DFTI_OUTPUT_DISTANCE
,2*nyc
) ||
400 DftiSetValue(fft
->inplace
[1],DFTI_OUTPUT_STRIDES
,stride
) ||
401 DftiCommitDescriptor(fft
->inplace
[1]));
405 /* Out-of-place real-to-complex (affects output distance) Y FFT */
407 status
= DftiCreateDescriptor(&fft
->ooplace
[1],GMX_DFTI_PREC
,DFTI_REAL
,1,(MKL_LONG
)ny
);
415 (DftiSetValue(fft
->ooplace
[1],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
) ||
416 DftiSetValue(fft
->ooplace
[1],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)nx
) ||
417 DftiSetValue(fft
->ooplace
[1],DFTI_INPUT_DISTANCE
,(MKL_LONG
)ny
) ||
418 DftiSetValue(fft
->ooplace
[1],DFTI_INPUT_STRIDES
,stride
) ||
419 DftiSetValue(fft
->ooplace
[1],DFTI_OUTPUT_DISTANCE
,2*nyc
) ||
420 DftiSetValue(fft
->ooplace
[1],DFTI_OUTPUT_STRIDES
,stride
) ||
421 DftiCommitDescriptor(fft
->ooplace
[1]));
425 /* Out-of-place complex-to-real (affects output distance) Y FFT */
427 status
= DftiCreateDescriptor(&fft
->ooplace
[2],GMX_DFTI_PREC
,DFTI_REAL
,1,(MKL_LONG
)ny
);
435 (DftiSetValue(fft
->ooplace
[2],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
) ||
436 DftiSetValue(fft
->ooplace
[2],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)nx
) ||
437 DftiSetValue(fft
->ooplace
[2],DFTI_INPUT_DISTANCE
,2*nyc
) ||
438 DftiSetValue(fft
->ooplace
[2],DFTI_INPUT_STRIDES
,stride
) ||
439 DftiSetValue(fft
->ooplace
[2],DFTI_OUTPUT_DISTANCE
,(MKL_LONG
)ny
) ||
440 DftiSetValue(fft
->ooplace
[2],DFTI_OUTPUT_STRIDES
,stride
) ||
441 DftiCommitDescriptor(fft
->ooplace
[2]));
447 if ((fft
->work
= (t_complex
*)malloc(sizeof(t_complex
)*(nx
*(ny
/2+1)))) == NULL
)
455 gmx_fatal(FARGS
,"Error initializing Intel MKL FFT; status=%d",status
);
456 gmx_fft_destroy(fft
);
472 gmx_fft_init_3d(gmx_fft_t
* pfft
,
485 gmx_fatal(FARGS
,"Invalid opaque FFT datatype pointer.");
490 if( (fft
= (gmx_fft_t
)malloc(sizeof(struct gmx_fft
))) == NULL
)
495 /* Mark all handles invalid */
498 fft
->inplace
[d
] = fft
->ooplace
[d
] = NULL
;
500 fft
->ooplace
[3] = NULL
;
506 status
= DftiCreateDescriptor(&fft
->inplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,(MKL_LONG
)3,length
);
509 status
= DftiSetValue(fft
->inplace
[0],DFTI_PLACEMENT
,DFTI_INPLACE
);
512 status
= DftiCommitDescriptor(fft
->inplace
[0]);
516 status
= DftiCreateDescriptor(&fft
->ooplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,(MKL_LONG
)3,length
);
519 status
= DftiSetValue(fft
->ooplace
[0],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
);
522 status
= DftiCommitDescriptor(fft
->ooplace
[0]);
527 gmx_fatal(FARGS
,"Error initializing Intel MKL FFT; status=%d",status
);
528 gmx_fft_destroy(fft
);
548 gmx_fft_init_3d_real(gmx_fft_t
* pfft
,
562 gmx_fatal(FARGS
,"Invalid opaque FFT datatype pointer.");
569 if( (fft
= (gmx_fft_t
)malloc(sizeof(struct gmx_fft
))) == NULL
)
574 /* Mark all handles invalid */
577 fft
->inplace
[d
] = fft
->ooplace
[d
] = NULL
;
579 fft
->ooplace
[3] = NULL
;
581 /* Roll our own 3D real transform using multiple transforms in MKL,
582 * since the current MKL versions does not support our storage format
583 * or 3D real transforms.
587 * ny*nzc complex-to-complex transforms, length nx
588 * transform distance: 1
589 * element strides: ny*nzc
591 status
= DftiCreateDescriptor(&fft
->inplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,1,(MKL_LONG
)nx
);
599 (DftiSetValue(fft
->inplace
[0],DFTI_PLACEMENT
,DFTI_INPLACE
) ||
600 DftiSetValue(fft
->inplace
[0],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)ny
*nzc
) ||
601 DftiSetValue(fft
->inplace
[0],DFTI_INPUT_DISTANCE
,1) ||
602 DftiSetValue(fft
->inplace
[0],DFTI_INPUT_STRIDES
,stride
) ||
603 DftiSetValue(fft
->inplace
[0],DFTI_OUTPUT_DISTANCE
,1) ||
604 DftiSetValue(fft
->inplace
[0],DFTI_OUTPUT_STRIDES
,stride
) ||
605 DftiCommitDescriptor(fft
->inplace
[0]));
608 /* Out-of-place X FFT:
609 * ny*nzc complex-to-complex transforms, length nx
610 * transform distance: 1
611 * element strides: ny*nzc
614 status
= DftiCreateDescriptor(&fft
->ooplace
[0],GMX_DFTI_PREC
,DFTI_COMPLEX
,1,(MKL_LONG
)nx
);
622 (DftiSetValue(fft
->ooplace
[0],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
) ||
623 DftiSetValue(fft
->ooplace
[0],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)ny
*nzc
) ||
624 DftiSetValue(fft
->ooplace
[0],DFTI_INPUT_DISTANCE
,1) ||
625 DftiSetValue(fft
->ooplace
[0],DFTI_INPUT_STRIDES
,stride
) ||
626 DftiSetValue(fft
->ooplace
[0],DFTI_OUTPUT_DISTANCE
,1) ||
627 DftiSetValue(fft
->ooplace
[0],DFTI_OUTPUT_STRIDES
,stride
) ||
628 DftiCommitDescriptor(fft
->ooplace
[0]));
633 * We cannot do all NX*NZC transforms at once, so define a handle to do
634 * NZC transforms, and then execute it NX times.
635 * nzc complex-to-complex transforms, length ny
636 * transform distance: 1
637 * element strides: nzc
640 status
= DftiCreateDescriptor(&fft
->inplace
[1],GMX_DFTI_PREC
,DFTI_COMPLEX
,1,(MKL_LONG
)ny
);
648 (DftiSetValue(fft
->inplace
[1],DFTI_PLACEMENT
,DFTI_INPLACE
) ||
649 DftiSetValue(fft
->inplace
[1],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)nzc
) ||
650 DftiSetValue(fft
->inplace
[1],DFTI_INPUT_DISTANCE
,1) ||
651 DftiSetValue(fft
->inplace
[1],DFTI_INPUT_STRIDES
,stride
) ||
652 DftiSetValue(fft
->inplace
[1],DFTI_OUTPUT_DISTANCE
,1) ||
653 DftiSetValue(fft
->inplace
[1],DFTI_OUTPUT_STRIDES
,stride
) ||
654 DftiCommitDescriptor(fft
->inplace
[1]));
658 /* Out-of-place Y FFT:
659 * We cannot do all NX*NZC transforms at once, so define a handle to do
660 * NZC transforms, and then execute it NX times.
661 * nzc complex-to-complex transforms, length ny
662 * transform distance: 1
663 * element strides: nzc
666 status
= DftiCreateDescriptor(&fft
->ooplace
[1],GMX_DFTI_PREC
,DFTI_COMPLEX
,1,(MKL_LONG
)ny
);
674 (DftiSetValue(fft
->ooplace
[1],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
) ||
675 DftiSetValue(fft
->ooplace
[1],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)nzc
) ||
676 DftiSetValue(fft
->ooplace
[1],DFTI_INPUT_DISTANCE
,1) ||
677 DftiSetValue(fft
->ooplace
[1],DFTI_INPUT_STRIDES
,stride
) ||
678 DftiSetValue(fft
->ooplace
[1],DFTI_OUTPUT_DISTANCE
,1) ||
679 DftiSetValue(fft
->ooplace
[1],DFTI_OUTPUT_STRIDES
,stride
) ||
680 DftiCommitDescriptor(fft
->ooplace
[1]));
684 * nx*ny real-to-complex transforms, length nz
685 * transform distance: nzc*2 -> nzc*2
689 status
= DftiCreateDescriptor(&fft
->inplace
[2],GMX_DFTI_PREC
,DFTI_REAL
,1,(MKL_LONG
)nz
);
697 (DftiSetValue(fft
->inplace
[2],DFTI_PLACEMENT
,DFTI_INPLACE
) ||
698 DftiSetValue(fft
->inplace
[2],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)nx
*ny
) ||
699 DftiSetValue(fft
->inplace
[2],DFTI_INPUT_DISTANCE
,(MKL_LONG
)nzc
*2) ||
700 DftiSetValue(fft
->inplace
[2],DFTI_INPUT_STRIDES
,stride
) ||
701 DftiSetValue(fft
->inplace
[2],DFTI_OUTPUT_DISTANCE
,(MKL_LONG
)nzc
*2) ||
702 DftiSetValue(fft
->inplace
[2],DFTI_OUTPUT_STRIDES
,stride
) ||
703 DftiCommitDescriptor(fft
->inplace
[2]));
707 /* Out-of-place real-to-complex (affects distance) Z FFT:
708 * nx*ny real-to-complex transforms, length nz
709 * transform distance: nz -> nzc*2
713 status
= DftiCreateDescriptor(&fft
->ooplace
[2],GMX_DFTI_PREC
,DFTI_REAL
,1,(MKL_LONG
)nz
);
721 (DftiSetValue(fft
->ooplace
[2],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
) ||
722 DftiSetValue(fft
->ooplace
[2],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)nx
*ny
) ||
723 DftiSetValue(fft
->ooplace
[2],DFTI_INPUT_DISTANCE
,(MKL_LONG
)nz
) ||
724 DftiSetValue(fft
->ooplace
[2],DFTI_INPUT_STRIDES
,stride
) ||
725 DftiSetValue(fft
->ooplace
[2],DFTI_OUTPUT_DISTANCE
,(MKL_LONG
)nzc
*2) ||
726 DftiSetValue(fft
->ooplace
[2],DFTI_OUTPUT_STRIDES
,stride
) ||
727 DftiCommitDescriptor(fft
->ooplace
[2]));
731 /* Out-of-place complex-to-real (affects distance) Z FFT:
732 * nx*ny real-to-complex transforms, length nz
733 * transform distance: nzc*2 -> nz
737 status
= DftiCreateDescriptor(&fft
->ooplace
[3],GMX_DFTI_PREC
,DFTI_REAL
,1,(MKL_LONG
)nz
);
745 (DftiSetValue(fft
->ooplace
[3],DFTI_PLACEMENT
,DFTI_NOT_INPLACE
) ||
746 DftiSetValue(fft
->ooplace
[3],DFTI_NUMBER_OF_TRANSFORMS
,(MKL_LONG
)nx
*ny
) ||
747 DftiSetValue(fft
->ooplace
[3],DFTI_INPUT_DISTANCE
,(MKL_LONG
)nzc
*2) ||
748 DftiSetValue(fft
->ooplace
[3],DFTI_INPUT_STRIDES
,stride
) ||
749 DftiSetValue(fft
->ooplace
[3],DFTI_OUTPUT_DISTANCE
,(MKL_LONG
)nz
) ||
750 DftiSetValue(fft
->ooplace
[3],DFTI_OUTPUT_STRIDES
,stride
) ||
751 DftiCommitDescriptor(fft
->ooplace
[3]));
757 if ((fft
->work
= (t_complex
*)malloc(sizeof(t_complex
)*(nx
*ny
*(nz
/2+1)))) == NULL
)
766 gmx_fatal(FARGS
,"Error initializing Intel MKL FFT; status=%d",status
);
767 gmx_fft_destroy(fft
);
786 gmx_fft_1d(gmx_fft_t fft
,
787 enum gmx_fft_direction dir
,
791 int inplace
= (in_data
== out_data
);
794 if( (fft
->real_fft
== 1) || (fft
->ndim
!= 1) ||
795 ((dir
!= GMX_FFT_FORWARD
) && (dir
!= GMX_FFT_BACKWARD
)) )
797 gmx_fatal(FARGS
,"FFT plan mismatch - bad plan or direction.");
801 if(dir
==GMX_FFT_FORWARD
)
805 status
= DftiComputeForward(fft
->inplace
[0],in_data
);
809 status
= DftiComputeForward(fft
->ooplace
[0],in_data
,out_data
);
816 status
= DftiComputeBackward(fft
->inplace
[0],in_data
);
820 status
= DftiComputeBackward(fft
->ooplace
[0],in_data
,out_data
);
826 gmx_fatal(FARGS
,"Error executing Intel MKL FFT.");
836 gmx_fft_1d_real(gmx_fft_t fft
,
837 enum gmx_fft_direction dir
,
841 int inplace
= (in_data
== out_data
);
844 if( (fft
->real_fft
!= 1) || (fft
->ndim
!= 1) ||
845 ((dir
!= GMX_FFT_REAL_TO_COMPLEX
) && (dir
!= GMX_FFT_COMPLEX_TO_REAL
)) )
847 gmx_fatal(FARGS
,"FFT plan mismatch - bad plan or direction.");
851 if(dir
==GMX_FFT_REAL_TO_COMPLEX
)
855 status
= DftiComputeForward(fft
->inplace
[0],in_data
);
859 status
= DftiComputeForward(fft
->ooplace
[0],in_data
,out_data
);
866 status
= DftiComputeBackward(fft
->inplace
[0],in_data
);
870 status
= DftiComputeBackward(fft
->ooplace
[0],in_data
,out_data
);
876 gmx_fatal(FARGS
,"Error executing Intel MKL FFT.");
885 gmx_fft_2d(gmx_fft_t fft
,
886 enum gmx_fft_direction dir
,
890 int inplace
= (in_data
== out_data
);
893 if( (fft
->real_fft
== 1) || (fft
->ndim
!= 2) ||
894 ((dir
!= GMX_FFT_FORWARD
) && (dir
!= GMX_FFT_BACKWARD
)) )
896 gmx_fatal(FARGS
,"FFT plan mismatch - bad plan or direction.");
900 if(dir
==GMX_FFT_FORWARD
)
904 status
= DftiComputeForward(fft
->inplace
[0],in_data
);
908 status
= DftiComputeForward(fft
->ooplace
[0],in_data
,out_data
);
915 status
= DftiComputeBackward(fft
->inplace
[0],in_data
);
919 status
= DftiComputeBackward(fft
->ooplace
[0],in_data
,out_data
);
925 gmx_fatal(FARGS
,"Error executing Intel MKL FFT.");
934 gmx_fft_2d_real(gmx_fft_t fft
,
935 enum gmx_fft_direction dir
,
939 int inplace
= (in_data
== out_data
);
942 if( (fft
->real_fft
!= 1) || (fft
->ndim
!= 2) ||
943 ((dir
!= GMX_FFT_REAL_TO_COMPLEX
) && (dir
!= GMX_FFT_COMPLEX_TO_REAL
)) )
945 gmx_fatal(FARGS
,"FFT plan mismatch - bad plan or direction.");
949 if(dir
==GMX_FFT_REAL_TO_COMPLEX
)
953 /* real-to-complex in Y dimension, in-place */
954 status
= DftiComputeForward(fft
->inplace
[1],in_data
);
956 /* complex-to-complex in X dimension, in-place */
958 status
= DftiComputeForward(fft
->inplace
[0],in_data
);
962 /* real-to-complex in Y dimension, in_data to out_data */
963 status
= DftiComputeForward(fft
->ooplace
[1],in_data
,out_data
);
965 /* complex-to-complex in X dimension, in-place to out_data */
967 status
= DftiComputeForward(fft
->inplace
[0],out_data
);
974 /* complex-to-complex in X dimension, in-place */
975 status
= DftiComputeBackward(fft
->inplace
[0],in_data
);
977 /* complex-to-real in Y dimension, in-place */
979 status
= DftiComputeBackward(fft
->inplace
[1],in_data
);
984 /* complex-to-complex in X dimension, from in_data to work */
985 status
= DftiComputeBackward(fft
->ooplace
[0],in_data
,fft
->work
);
987 /* complex-to-real in Y dimension, from work to out_data */
989 status
= DftiComputeBackward(fft
->ooplace
[1],fft
->work
,out_data
);
996 gmx_fatal(FARGS
,"Error executing Intel MKL FFT.");
1005 gmx_fft_3d(gmx_fft_t fft
,
1006 enum gmx_fft_direction dir
,
1010 int inplace
= (in_data
== out_data
);
1013 if( (fft
->real_fft
== 1) || (fft
->ndim
!= 3) ||
1014 ((dir
!= GMX_FFT_FORWARD
) && (dir
!= GMX_FFT_BACKWARD
)) )
1016 gmx_fatal(FARGS
,"FFT plan mismatch - bad plan or direction.");
1020 if(dir
==GMX_FFT_FORWARD
)
1024 status
= DftiComputeForward(fft
->inplace
[0],in_data
);
1028 status
= DftiComputeForward(fft
->ooplace
[0],in_data
,out_data
);
1035 status
= DftiComputeBackward(fft
->inplace
[0],in_data
);
1039 status
= DftiComputeBackward(fft
->ooplace
[0],in_data
,out_data
);
1045 gmx_fatal(FARGS
,"Error executing Intel MKL FFT.");
1054 gmx_fft_3d_real(gmx_fft_t fft
,
1055 enum gmx_fft_direction dir
,
1059 int inplace
= (in_data
== out_data
);
1066 nzc
= fft
->nz
/2 + 1;
1068 if( (fft
->real_fft
!= 1) || (fft
->ndim
!= 3) ||
1069 ((dir
!= GMX_FFT_REAL_TO_COMPLEX
) && (dir
!= GMX_FFT_COMPLEX_TO_REAL
)) )
1071 gmx_fatal(FARGS
,"FFT plan mismatch - bad plan or direction.");
1075 if(dir
==GMX_FFT_REAL_TO_COMPLEX
)
1079 /* real-to-complex in Z dimension, in-place */
1080 status
= DftiComputeForward(fft
->inplace
[2],in_data
);
1082 /* complex-to-complex in Y dimension, in-place */
1086 status
= DftiComputeForward(fft
->inplace
[1],(t_complex
*)in_data
+i
*ny
*nzc
);
1089 /* complex-to-complex in X dimension, in-place */
1091 status
= DftiComputeForward(fft
->inplace
[0],in_data
);
1095 /* real-to-complex in Z dimension, from in_data to out_data */
1096 status
= DftiComputeForward(fft
->ooplace
[2],in_data
,out_data
);
1098 /* complex-to-complex in Y dimension, in-place */
1102 status
= DftiComputeForward(fft
->inplace
[1],(t_complex
*)out_data
+i
*ny
*nzc
);
1105 /* complex-to-complex in X dimension, in-place */
1107 status
= DftiComputeForward(fft
->inplace
[0],out_data
);
1114 /* complex-to-complex in X dimension, in-place */
1115 status
= DftiComputeBackward(fft
->inplace
[0],in_data
);
1117 /* complex-to-complex in Y dimension, in-place */
1121 status
= DftiComputeBackward(fft
->inplace
[1],(t_complex
*)in_data
+i
*ny
*nzc
);
1124 /* complex-to-real in Z dimension, in-place */
1126 status
= DftiComputeBackward(fft
->inplace
[2],in_data
);
1130 /* complex-to-complex in X dimension, from in_data to work */
1131 status
= DftiComputeBackward(fft
->ooplace
[0],in_data
,fft
->work
);
1133 /* complex-to-complex in Y dimension, in-place */
1137 status
= DftiComputeBackward(fft
->inplace
[1],fft
->work
+i
*ny
*nzc
);
1140 /* complex-to-real in Z dimension, work to out_data */
1142 status
= DftiComputeBackward(fft
->ooplace
[2],fft
->work
,out_data
);
1148 gmx_fatal(FARGS
,"Error executing Intel MKL FFT.");
1158 gmx_fft_destroy(gmx_fft_t fft
)
1166 if(fft
->inplace
[d
] != NULL
)
1168 DftiFreeDescriptor(&fft
->inplace
[d
]);
1170 if(fft
->ooplace
[d
] != NULL
)
1172 DftiFreeDescriptor(&fft
->ooplace
[d
]);
1175 if(fft
->ooplace
[3] != NULL
)
1177 DftiFreeDescriptor(&fft
->ooplace
[3]);
1186 #endif /* GMX_FFT_MKL */