2 * This file is part of the GROMACS molecular simulation package.
4 * Gromacs 4.0 Copyright (c) 1991-2003
5 * Erik Lindahl, David van der Spoel, University of Groningen.
6 * Copyright (c) 2012, by the GROMACS development team, led by
7 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
8 * others, as listed in the AUTHORS file in the top-level source
9 * directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
47 #include "types/simple.h"
48 #include "gmxcomplex.h"
51 #include "gmx_fatal.h"
54 /* This file contains common fft utility functions, but not
55 * the actual transform implementations. Check the
56 * files like gmx_fft_fftw3.c or gmx_fft_intel_mkl.c for that.
67 typedef struct gmx_many_fft* gmx_many_fft_t ;
70 gmx_fft_init_many_1d(gmx_fft_t * pfft,
78 gmx_fatal(FARGS,"Invalid opaque FFT datatype pointer.");
83 if( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
88 gmx_fft_init_1d(&fft->fft,nx,flags);
89 fft->howmany = howmany;
92 *pfft = (gmx_fft_t)fft;
97 gmx_fft_init_many_1d_real(gmx_fft_t * pfft,
105 gmx_fatal(FARGS,"Invalid opaque FFT datatype pointer.");
110 if( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
115 gmx_fft_init_1d_real(&fft->fft,nx,flags);
116 fft->howmany = howmany;
117 fft->dist = 2*(nx/2+1);
119 *pfft = (gmx_fft_t)fft;
124 gmx_fft_many_1d (gmx_fft_t fft,
125 enum gmx_fft_direction dir,
129 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
131 for (i=0;i<mfft->howmany;i++)
133 ret=gmx_fft_1d(mfft->fft,dir,in_data,out_data);
134 if (ret!=0) return ret;
135 in_data=(real*)in_data+mfft->dist;
136 out_data=(real*)out_data+mfft->dist;
142 gmx_fft_many_1d_real (gmx_fft_t fft,
143 enum gmx_fft_direction dir,
147 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
149 for (i=0;i<mfft->howmany;i++)
151 ret=gmx_fft_1d_real(mfft->fft,dir,in_data,out_data);
152 if (ret!=0) return ret;
153 in_data=(real*)in_data+mfft->dist;
154 out_data=(real*)out_data+mfft->dist;
161 gmx_many_fft_destroy(gmx_fft_t fft)
163 gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
168 gmx_fft_destroy(mfft->fft);
176 int gmx_fft_transpose_2d(t_complex * in_data,
177 t_complex * out_data,
181 int i,j,k,im,n,ncount,done1,done2;
182 int i1,i1c,i2,i2c,kmi,max;
184 t_complex tmp1,tmp2,tmp3;
187 /* Use 500 bytes on stack to indicate moves.
188 * This is just for optimization, it does not limit any dimensions.
195 if(in_data != out_data)
197 memcpy(out_data,in_data,sizeof(t_complex)*nx*ny);
202 /* Out-of-place transposes are easy */
203 if(in_data != out_data)
209 out_data[j*nx+i].re = in_data[i*ny+j].re;
210 out_data[j*nx+i].im = in_data[i*ny+j].im;
216 /* In-place transform. in_data=out_data=data */
221 /* trivial case, just swap elements */
226 tmp1.re = data[i*nx+j].re;
227 tmp1.im = data[i*nx+j].im;
228 data[i*nx+j].re = data[j*nx+i].re;
229 data[i*nx+j].im = data[j*nx+i].im;
230 data[j*nx+i].re = tmp1.re;
231 data[j*nx+i].im = tmp1.im;
268 tmp1.re = data[i1].re;
269 tmp1.im = data[i1].im;
271 tmp2.re = data[i1c].re;
272 tmp2.im = data[i1c].im;
277 i2 = ny*i1-k*(i1/nx);
304 data[i1].re = data[i2].re;
305 data[i1].im = data[i2].im;
306 data[i1c].re = data[i2c].re;
307 data[i1c].im = data[i2c].im;
314 data[i1].re = tmp1.re;
315 data[i1].im = tmp1.im;
316 data[i1c].re = tmp2.re;
317 data[i1c].im = tmp2.im;
340 while(i2>i && i2<max)
343 i2 = ny*i1-k*(i1/nx);
366 /* Same as the above, but assume each (x,y) position holds
367 * nelem complex numbers.
368 * This is used when transposing the x/y dimensions of a
369 * 3D matrix; set nelem to nz in this case.
372 gmx_fft_transpose_2d_nelem(t_complex * in_data,
373 t_complex * out_data,
379 int i,j,k,im,n,ncount,done1,done2;
380 int i1,i1c,i2,i2c,kmi,max,ncpy;
382 t_complex *tmp1,*tmp2,*tmp3;
385 /* Use 500 bytes on stack to indicate moves.
386 * This is just for optimization, it does not limit any dimensions.
391 ncpy = nelem*sizeof(t_complex);
395 if(in_data != out_data)
397 memcpy(out_data,in_data,ncpy*nx*ny);
402 /* Out-of-place transposes are easy */
403 if(in_data != out_data)
409 memcpy(out_data + (j*nx+i)*nelem,
410 in_data + (i*ny+j)*nelem,
418 /* In-place transform. in_data=out_data=data */
422 /* Check the work array */
426 "No work array provided to gmx_fft_transpose_2d_nelem().");
435 /* trivial case, just swap elements */
440 memcpy(tmp1,data+(i*nx+j)*nelem,ncpy);
441 memcpy(data+(i*nx+j)*nelem,data+(j*nx+i)*nelem,ncpy);
442 memcpy(data+(j*nx+i)*nelem,tmp1,ncpy);
480 memcpy(tmp1,data+i1*nelem,ncpy);
481 memcpy(tmp2,data+i1c*nelem,ncpy);
486 i2 = ny*i1-k*(i1/nx);
503 /* Swapping pointers instead of copying data */
511 memcpy(data+i1*nelem,data+i2*nelem,ncpy);
512 memcpy(data+i1c*nelem,data+i2c*nelem,ncpy);
519 memcpy(data+i1*nelem,tmp1,ncpy);
520 memcpy(data+i1c*nelem,tmp2,ncpy);
543 while(i2>i && i2<max)