Fixes for FFT libraries
authorRoland Schulz <roland@utk.edu>
Mon, 4 Jun 2012 15:56:42 +0000 (11:56 -0400)
committerRoland Schulz <roland@utk.edu>
Wed, 4 Jul 2012 02:37:06 +0000 (22:37 -0400)
- Updated documentation
- Added gmx_fft_cleanup for any cleanup after using FFT
    (removing memory leak otherwise caused by FFTW)
- Replaced TMPI_THREAD_MUTEX_INITIALIZER with tMPI::mutex
    (otherwise tmpi leaks memory)

Change-Id: If3e9012da14ebf74d87d4d4647c2f17bd8380fc1

src/gromacs/legacyheaders/gmx_fft.h
src/gromacs/legacyheaders/gmx_parallel_3dfft.h
src/gromacs/legacyheaders/gmxcomplex.h
src/gromacs/mdlib/CMakeLists.txt
src/gromacs/mdlib/fft5d.cpp [moved from src/gromacs/mdlib/fft5d.c with 98% similarity]
src/gromacs/mdlib/fft5d.h
src/gromacs/mdlib/gmx_fft.c
src/gromacs/mdlib/gmx_fft_fftpack.c
src/gromacs/mdlib/gmx_fft_fftw3.cpp [moved from src/gromacs/mdlib/gmx_fft_fftw3.c with 95% similarity]
src/gromacs/mdlib/gmx_fft_mkl.c
src/gromacs/mdlib/gmx_parallel_3dfft.c

index 2398e6f7bd3d5fc3c7e8d32640dd771cb7f242b3..3dec7300aa1ca594043040c65cc38ff2c8e873d0 100644 (file)
@@ -584,6 +584,12 @@ gmx_fft_transpose_2d_nelem(t_complex *        in_data,
                            t_complex *        work);
 
 
+/*! \brief Cleanup global data of FFT
+ *
+ *  Any plans are invalid after this function. Should be called
+ *  after all plans have been destroyed.s
+ * */
+void gmx_fft_cleanup();
 
 
 #ifdef __cplusplus
index 55582be42c108abb776dd4ad48ca0bf6fd438480..eb17c785414350653b1cbac37a9791509a1d808f 100644 (file)
 #include "gmxcomplex.h"
 #include "gmx_fft.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct gmx_parallel_3dfft *
 gmx_parallel_3dfft_t;
 
@@ -41,14 +45,14 @@ gmx_parallel_3dfft_t;
  *
  *  \param pfft_setup     Pointer to parallel 3dfft setup structure, previously
  *                        allocated or with automatic storage.
- *  \param ngridx         Global number of grid cells in the x direction. Must be
- *                        divisible by the number of nodes.
- *  \param ngridy         Global number of grid cells in the y direction. Must be
- *                        divisible by the number of nodes.
- *  \param ngridz         Global number of grid cells in the z direction.
- *  \param node2slab      Node id to slab index array, can be NULL.
- *  \param slab2grid_x    Slab index to grid_x array (nnodes+1), can be NULL.
- *  \param comm           MPI communicator, must have been initialized. 
+ *  \param ndata          Number of grid cells in each direction
+ *  \param real_data      Real data. Input for forward and output for backward.
+ *  \param complex_data   Complex data.
+ *  \param comm           MPI communicator for both parallelization axis.
+ *                        Needs to be either initialized or MPI_NULL for
+ *                        no parallelization in that axis.
+ *  \param slab2index_major Not used
+ *  \param slab2index_minor Not used
  *  \param bReproducible  Try to avoid FFT timing optimizations and other stuff
  *                        that could make results differ for two runs with
  *                        identical input (reproducibility for debugging).
@@ -117,7 +121,9 @@ gmx_parallel_3dfft_execute(gmx_parallel_3dfft_t    pfft_setup,
 int
 gmx_parallel_3dfft_destroy(gmx_parallel_3dfft_t    pfft_setup);
 
-
+#ifdef __cplusplus
+}
+#endif
 
 
 #endif /* _gmx_parallel_3dfft_h_ */
index 902f93f9286ceaaaf91a27c3669bd098d3990fa9..9b5916c510dcb80ec549a60d73b17f542c4b57d0 100644 (file)
@@ -45,8 +45,6 @@ typedef struct {
 
 typedef t_complex cvec[DIM];
 
-static t_complex cnul = { 0.0, 0.0 };
-
 static t_complex rcmul(real r,t_complex c)
 {
   t_complex d;
index 4871f08f8e2cef93d43815cbec13fb1b379e748f..222a53bc0fb0b3b9e24d9e7c3497221fae6163d8 100644 (file)
@@ -1,4 +1,4 @@
-file(GLOB MDLIB_SOURCES *.c)
+file(GLOB MDLIB_SOURCES *.c *.cpp)
 if(GMX_FFT_FFTPACK)
 list(APPEND MDLIB_SOURCES ${CMAKE_SOURCE_DIR}/src/external/fftpack/fftpack.c)
 endif()
similarity index 98%
rename from src/gromacs/mdlib/fft5d.c
rename to src/gromacs/mdlib/fft5d.cpp
index 1337c1119574ebc42b87e6f09da3e6d3b12e8276..43838b30dd49c42cc340a6904c071e23f7d6536c 100644 (file)
@@ -35,6 +35,7 @@
 #include <config.h>
 #endif
 
+#include <algorithm>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -85,27 +86,19 @@ FILE* debug=0;
 
 
 #ifdef GMX_FFT_FFTW3 
-#ifdef GMX_THREAD_MPI
+#include "thread_mpi/mutex.h"
+#include "gromacs/utility/exceptions.h"
 /* none of the fftw3 calls, except execute(), are thread-safe, so 
    we need to serialize them with this mutex. */
-static tMPI_Thread_mutex_t big_fftw_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
-
-#define FFTW_LOCK tMPI_Thread_mutex_lock(&big_fftw_mutex)
-#define FFTW_UNLOCK tMPI_Thread_mutex_unlock(&big_fftw_mutex)
-#else /* GMX_THREAD_MPI */
-#define FFTW_LOCK 
-#define FFTW_UNLOCK 
-#endif /* GMX_THREAD_MPI */
+static tMPI::mutex big_fftw_mutex;
+#define FFTW_LOCK try { big_fftw_mutex.lock(); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
+#define FFTW_UNLOCK try { big_fftw_mutex.unlock(); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
 #endif /* GMX_FFT_FFTW3 */
 
-static double fft5d_fmax(double a, double b){
-       return (a>b)?a:b;
-}
-
 /* largest factor smaller than sqrt */
 static int lfactor(int z) {  
        int i;
-       for (i=sqrt(z);;i--)
+       for (i=static_cast<int>(sqrt(static_cast<double>(z)));;i--)
                if (z%i==0) return i;
        return 1;
 }
@@ -123,7 +116,7 @@ static int l2factor(int z) {
 static int lpfactor(int z) {
        int f = l2factor(z);
        if (f==1) return z;
-       return fft5d_fmax(lpfactor(f),lpfactor(z/f));
+       return std::max(lpfactor(f),lpfactor(z/f));
 }
 
 #ifndef GMX_MPI
@@ -377,7 +370,7 @@ fft5d_plan fft5d_plan_3d(int NG, int MG, int KG, MPI_Comm comm[2], int flags, t_
     */
     
     /* int lsize = fmax(N[0]*M[0]*K[0]*nP[0],N[1]*M[1]*K[1]*nP[1]); */
-    lsize = fft5d_fmax(N[0]*M[0]*K[0]*nP[0],fft5d_fmax(N[1]*M[1]*K[1]*nP[1],C[2]*M[2]*K[2])); 
+    lsize = std::max(N[0]*M[0]*K[0]*nP[0],std::max(N[1]*M[1]*K[1]*nP[1],C[2]*M[2]*K[2]));
     /* int lsize = fmax(C[0]*M[0]*K[0],fmax(C[1]*M[1]*K[1],C[2]*M[2]*K[2])); */
     if (!(flags&FFT5D_NOMALLOC)) { 
         snew_aligned(lin, lsize, 32);
@@ -809,7 +802,7 @@ static void compute_offsets(fft5d_plan plan, int xs[], int xl[], int xc[], int N
 }
 
 static void print_localdata(const t_complex* lin, const char* txt, int s, fft5d_plan plan) {
-    int x,y,z,l,t;
+    int x,y,z,l;
     int *coor = plan->coor;
     int xs[3],xl[3],xc[3],NG[3];        
     int ll=(plan->flags&FFT5D_REALCOMPLEX)?1:2;
@@ -844,8 +837,9 @@ void fft5d_execute(fft5d_plan plan,int thread,fft5d_time times) {
 #ifdef GMX_MPI
     MPI_Comm *cart=plan->cart;
 #endif
-
+#ifdef NOGMX
     double time_fft=0,time_local=0,time_mpi[2]={0},time=0;    
+#endif
     int *N=plan->N,*M=plan->M,*K=plan->K,*pN=plan->pN,*pM=plan->pM,*pK=plan->pK,
         *C=plan->C,*P=plan->P,**iNin=plan->iNin,**oNin=plan->oNin,**iNout=plan->iNout,**oNout=plan->oNout;
     int s=0,tstart,tend,bParallelDim;
@@ -1128,11 +1122,12 @@ void fft5d_destroy(fft5d_plan plan) {
     {
         FFTW(destroy_plan)(plan->mpip[s]);
     }
+#endif /* FFT5D_MPI_TRANSPOS */
     if (plan->p3d)
     {
         FFTW(destroy_plan)(plan->p3d);
     }
-#endif /* FFT5D_MPI_TRANSPOS */
+    FFTW_UNLOCK;
 #endif /* GMX_FFT_FFTW3 */
 
     if (!(plan->flags&FFT5D_NOMALLOC))
index cfc7c9328c683fa76371f798c7cfc6e5624868c9..38bf30cf32a8d5ca229bc17fa5f0ba38e6a50e54 100644 (file)
 #include <config.h>
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef NOGMX
 /*#define GMX_MPI*/
 /*#define GMX_FFT_FFTW3*/
@@ -122,5 +126,9 @@ void fft5d_local_size(fft5d_plan plan,int* N1,int* M0,int* K0,int* K1,int** coor
 void fft5d_destroy(fft5d_plan plan);
 fft5d_plan fft5d_plan_3d_cart(int N, int M, int K, MPI_Comm comm, int P0, int flags, t_complex** lin, t_complex** lin2, t_complex** lout2, t_complex** lout3, int nthreads);
 void fft5d_compare_data(const t_complex* lin, const t_complex* in, fft5d_plan plan, int bothLocal, int normarlize);
+
+#ifdef __cplusplus
+}
+#endif
 #endif /*FFTLIB_H_*/
 
index c07a0c3f836c09394f847b94c0fc77be37fe4748..1c3c3c225db2cf45fa6d8944d14687359e1debad 100644 (file)
@@ -152,7 +152,7 @@ gmx_many_fft_destroy(gmx_fft_t    fft)
     }
 }
 
-#endif
+#endif //not GMX_FFT_FFTW3
 
 int gmx_fft_transpose_2d(t_complex *          in_data,
                          t_complex *          out_data,
index 1091d2c63bce6f7489a1b9f3322a057fd26154b9..b146cf2be0c0a2021679e75a65c1cbc19ffca519 100644 (file)
@@ -922,4 +922,8 @@ gmx_fft_destroy(gmx_fft_t      fft)
         free(fft);
     }
 }
+
+void gmx_fft_cleanup()
+{
+}
 #endif /* GMX_FFT_FFTPACK */
similarity index 95%
rename from src/gromacs/mdlib/gmx_fft_fftw3.c
rename to src/gromacs/mdlib/gmx_fft_fftw3.cpp
index f63d140fdf7eec544ba91ef07137ac741505e472..b54a42242548539cf763c29d1f413b3b1c5aaf4b 100644 (file)
 #include "gmx_fft.h"
 #include "gmx_fatal.h"
 
-
 #ifdef GMX_DOUBLE
 #define FFTWPREFIX(name) fftw_ ## name
 #else
 #define FFTWPREFIX(name) fftwf_ ## name
 #endif
 
-#ifdef GMX_THREAD_MPI
-#include "thread_mpi/threads.h"
-#endif
-
+#include "thread_mpi/mutex.h"
+#include "gromacs/utility/exceptions.h"
 
-#ifdef GMX_THREAD_MPI
 /* none of the fftw3 calls, except execute(), are thread-safe, so 
    we need to serialize them with this mutex. */
-static tMPI_Thread_mutex_t big_fftw_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
-static gmx_bool gmx_fft_threads_initialized=FALSE;
-#define FFTW_LOCK tMPI_Thread_mutex_lock(&big_fftw_mutex)
-#define FFTW_UNLOCK tMPI_Thread_mutex_unlock(&big_fftw_mutex)
-#else /* GMX_THREAD_MPI */
-#define FFTW_LOCK 
-#define FFTW_UNLOCK 
-#endif /* GMX_THREAD_MPI */
+static tMPI::mutex big_fftw_mutex;
+#define FFTW_LOCK try { big_fftw_mutex.lock(); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
+#define FFTW_UNLOCK try { big_fftw_mutex.unlock(); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
 
 /* We assume here that aligned memory starts at multiple of 16 bytes and unaligned memory starts at multiple of 8 bytes. The later is guranteed for all malloc implementation. 
    Consequesences:
@@ -78,7 +69,7 @@ struct gmx_fft
 int
 gmx_fft_init_1d(gmx_fft_t *        pfft,
                 int                nx,
-                gmx_fft_flag       flags) 
+                gmx_fft_flag       flags)
 {
     return gmx_fft_init_many_1d(pfft,nx,1,flags);
 }
@@ -86,21 +77,21 @@ gmx_fft_init_1d(gmx_fft_t *        pfft,
 
 int
 gmx_fft_init_many_1d(gmx_fft_t *        pfft,
-                    int                nx,
-                    int                howmany,
-                    gmx_fft_flag       flags) 
+             int                nx,
+             int                howmany,
+             gmx_fft_flag       flags)
 {
     gmx_fft_t              fft;
     FFTWPREFIX(complex)   *p1,*p2,*up1,*up2;
     size_t                 pc;
     int                    i,j,k;
     int                    fftw_flags;
-    
+
 #ifdef GMX_DISABLE_FFTW_MEASURE
     flags |= GMX_FFT_FLAG_CONSERVATIVE;
 #endif
-    
-    fftw_flags = (flags & GMX_FFT_FLAG_CONSERVATIVE) ? FFTW_ESTIMATE : FFTW_MEASURE;    
+
+    fftw_flags = (flags & GMX_FFT_FLAG_CONSERVATIVE) ? FFTW_ESTIMATE : FFTW_MEASURE;
 
     if(pfft==NULL)
     {
@@ -108,14 +99,14 @@ gmx_fft_init_many_1d(gmx_fft_t *        pfft,
         return EINVAL;
     }
     *pfft = NULL;
-        
+
     FFTW_LOCK;
     if( (fft = (gmx_fft_t)FFTWPREFIX(malloc)(sizeof(struct gmx_fft))) == NULL)
     {
         FFTW_UNLOCK;
         return ENOMEM;
-    }    
-    
+    }
+
     /* allocate aligned, and extra memory to make it unaligned */
     p1  = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2)*howmany);
     if(p1==NULL)
@@ -124,7 +115,7 @@ gmx_fft_init_many_1d(gmx_fft_t *        pfft,
         FFTW_UNLOCK;
         return ENOMEM;
     }
-    
+
     p2  = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2)*howmany);
     if(p2==NULL)
     {
@@ -133,33 +124,33 @@ gmx_fft_init_many_1d(gmx_fft_t *        pfft,
         FFTW_UNLOCK;
         return ENOMEM;
     }
-    
-    /* make unaligned pointers. 
+
+    /* make unaligned pointers.
      * In double precision the actual complex datatype will be 16 bytes,
      * so go to a char pointer and force an offset of 8 bytes instead.
      */
     pc = (size_t)p1;
-    pc += 8; 
+    pc += 8;
     up1 = (FFTWPREFIX(complex) *)pc;
-    
+
     pc = (size_t)p2;
-    pc += 8; 
+    pc += 8;
     up2 = (FFTWPREFIX(complex) *)pc;
-    
+
     /*                            int rank, const int *n, int howmany,
                                   fftw_complex *in, const int *inembed,
                                   int istride, int idist,
                                   fftw_complex *out, const int *onembed,
                                   int ostride, int odist,
                                   int sign, unsigned flags */
-    fft->plan[0][0][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up2,&nx,1,nx,FFTW_BACKWARD,fftw_flags); 
-    fft->plan[0][0][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up2,&nx,1,nx,FFTW_FORWARD,fftw_flags); 
-    fft->plan[0][1][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up1,&nx,1,nx,FFTW_BACKWARD,fftw_flags); 
-    fft->plan[0][1][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up1,&nx,1,nx,FFTW_FORWARD,fftw_flags); 
-    fft->plan[1][0][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p2,&nx,1,nx,FFTW_BACKWARD,fftw_flags); 
-    fft->plan[1][0][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p2,&nx,1,nx,FFTW_FORWARD,fftw_flags); 
-    fft->plan[1][1][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p1,&nx,1,nx,FFTW_BACKWARD,fftw_flags); 
-    fft->plan[1][1][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p1,&nx,1,nx,FFTW_FORWARD,fftw_flags); 
+    fft->plan[0][0][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up2,&nx,1,nx,FFTW_BACKWARD,fftw_flags);
+    fft->plan[0][0][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up2,&nx,1,nx,FFTW_FORWARD,fftw_flags);
+    fft->plan[0][1][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up1,&nx,1,nx,FFTW_BACKWARD,fftw_flags);
+    fft->plan[0][1][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up1,&nx,1,nx,FFTW_FORWARD,fftw_flags);
+    fft->plan[1][0][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p2,&nx,1,nx,FFTW_BACKWARD,fftw_flags);
+    fft->plan[1][0][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p2,&nx,1,nx,FFTW_FORWARD,fftw_flags);
+    fft->plan[1][1][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p1,&nx,1,nx,FFTW_BACKWARD,fftw_flags);
+    fft->plan[1][1][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p1,&nx,1,nx,FFTW_FORWARD,fftw_flags);
 
     for(i=0;i<2;i++)
     {
@@ -180,20 +171,19 @@ gmx_fft_init_many_1d(gmx_fft_t *        pfft,
                 }
             }
         }
-    } 
-    
+    }
+
     FFTWPREFIX(free)(p1);
     FFTWPREFIX(free)(p2);
-    
+
     fft->real_transform = 0;
     fft->ndim           = 1;
-    
+
     *pfft = fft;
     FFTW_UNLOCK;
     return 0;
 }
 
-
 int
 gmx_fft_init_1d_real(gmx_fft_t *        pfft,
                      int                nx,
@@ -756,32 +746,32 @@ gmx_fft_1d               (gmx_fft_t                  fft,
     int           aligned   = ((((size_t)in_data | (size_t)out_data) & 0xf)==0);
     int           inplace   = (in_data == out_data);
     int           isforward = (dir == GMX_FFT_FORWARD);
-    
+
     /* Some checks */
     if( (fft->real_transform == 1) || (fft->ndim != 1) ||
         ((dir != GMX_FFT_FORWARD) && (dir != GMX_FFT_BACKWARD)) )
     {
         gmx_fatal(FARGS,"FFT plan mismatch - bad plan or direction.");
         return EINVAL;
-    }    
+    }
 
     FFTWPREFIX(execute_dft)(fft->plan[aligned][inplace][isforward],
                             (FFTWPREFIX(complex) *)in_data,
                             (FFTWPREFIX(complex) *)out_data);
-    
+
     return 0;
 }
 
 int
 gmx_fft_many_1d               (gmx_fft_t                  fft,
-                              enum gmx_fft_direction     dir,
-                              void *                     in_data,
-                              void *                     out_data)
+                   enum gmx_fft_direction     dir,
+                   void *                     in_data,
+                   void *                     out_data)
 {
     return gmx_fft_1d(fft,dir,in_data,out_data);
 }
 
-int 
+int
 gmx_fft_1d_real          (gmx_fft_t                  fft,
                           enum gmx_fft_direction     dir,
                           void *                     in_data,
@@ -982,7 +972,8 @@ gmx_many_fft_destroy(gmx_fft_t    fft)
     gmx_fft_destroy(fft);
 }
 
-#else
-int
-gmx_fft_fftw3_empty;
+void gmx_fft_cleanup()
+{
+    FFTWPREFIX(cleanup)();
+}
 #endif /* GMX_FFT_FFTW3 */
index 8f4cd4d0dbca7c5656045f3df29f27cb88596236..7e744f22a4e95841d224c7016658ee72705281de 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 
 #include <mkl_dfti.h>
+#include <mkl_service.h>
 
 
 #include "gmx_fft.h"
@@ -969,26 +970,8 @@ gmx_fft_2d_real(gmx_fft_t                  fft,
     }
     else
     {
-        if(inplace)
-        {
-            /* complex-to-complex in X dimension, in-place */
-            status = DftiComputeBackward(fft->inplace[0],in_data);
-            
-            /* complex-to-real in Y dimension, in-place */
-            if ( status == 0 )
-                status = DftiComputeBackward(fft->inplace[1],in_data);
-                        
-        }
-        else
-        {
-            /* complex-to-complex in X dimension, from in_data to work */
-            status = DftiComputeBackward(fft->ooplace[0],in_data,fft->work);
-            
-            /* complex-to-real in Y dimension, from work to out_data */
-            if ( status == 0 )
-                status = DftiComputeBackward(fft->ooplace[1],fft->work,out_data);
-            
-        }
+        /* prior implementation was incorrect. See fft.cpp unit test */
+        gmx_incons("Complex -> Real is not supported by MKL.");
     }
     
     if( status != 0 )
@@ -1176,10 +1159,19 @@ gmx_fft_destroy(gmx_fft_t    fft)
         {
             DftiFreeDescriptor(&fft->ooplace[3]);
         }
+        if (fft->work != NULL)
+        {
+            free(fft->work);
+        }
         free(fft);
     }
 }
 
+void gmx_fft_cleanup()
+{
+    mkl_free_buffers();
+}
+
 #else
 int
 gmx_fft_mkl_empty;
index fef1ac6083227088a1adfe470d5f8310d3f930f6..d80364e00d7aaf99696d58482b600705a1d6a718 100644 (file)
@@ -83,9 +83,6 @@ fft5d_limits(fft5d_plan p,
              ivec                      local_offset,
              ivec                      local_size) 
 {
-    int N1,M0,K0,K1,*coor;
-    fft5d_local_size(p,&N1,&M0,&K0,&K1,&coor);  /* M0=MG/P[0], K1=KG/P[1], NG,MG,KG global sizes */
-    
     local_offset[2]=0;
     local_offset[1]=p->oM[0];  /*=p->coor[0]*p->MG/p->P[0]; */
     local_offset[0]=p->oK[0];  /*=p->coor[1]*p->KG/p->P[1]; */
@@ -95,6 +92,7 @@ fft5d_limits(fft5d_plan p,
     local_ndata[0]=p->pK[0]; 
     
     if ((!(p->flags&FFT5D_BACKWARD)) && (p->flags&FFT5D_REALCOMPLEX)) {
+        //C is length in multiples of complex local_size in multiples of real
         local_size[2]=p->C[0]*2;
     } else {
         local_size[2]=p->C[0];
@@ -167,9 +165,12 @@ gmx_parallel_3dfft_execute(gmx_parallel_3dfft_t    pfft_setup,
 
 int
 gmx_parallel_3dfft_destroy(gmx_parallel_3dfft_t    pfft_setup) {
-    fft5d_destroy(pfft_setup->p2);
-    fft5d_destroy(pfft_setup->p1);
-    sfree(pfft_setup);
+    if (pfft_setup)
+    {
+        fft5d_destroy(pfft_setup->p2);
+        fft5d_destroy(pfft_setup->p1);
+        sfree(pfft_setup);
+    }
     return 0;
 }