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 */