/*
DFT++ is a density functional package developed by the research group
of Professor Tomas Arias
Copyright 1996-2003 Sohrab Ismail-Beigi
This file is part of DFT++.
DFT++ is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DFT++ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DFT++; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Please see the file CREDITS for a list of authors.
For academic users, we request that publications using results obtained with
this software reference
"New algebraic formulation of density functional calculation," by Sohrab Ismail-Beigi
and T.A. Arias, Computer Physics Communications 128:1-2, 1-45 (June 2000).
and, if using the wavelet basis, further reference
"Multiresolution analysis of electronic structure: semicardinal and wavelet bases,"
T.A. Arias, Reviews of Modern Physics 71:1, 267-311 (January 1999).
and
"Robust ab initio calculation of condensed matter: transparent convergence through
semicardinal multiresolution analysis,'' I.P. Daykov, T.A. Arias, and
Torkel D. Engeness, Physical Review Letters, 90:21, 216402 (May 2003).
For your convenience, preprints of the above articles may be obtained from
http://arXiv.org/abs/cond-mat/9909130, 9805262, and 0204411, respectively.
*/
/*
* ft.c: Sohrab Ismail-Beigi 7/18/96, 4/7/97
*
* A set of routines to do discrete Fourier transforms on 1D and 3D boxes.
*
*
* The routines now use the FFTW package from the MIT LCS written by
* Steven G. Johnson and Matteo Frigo.
*
* void FFT3D() -- Uses FFTW
*/
/* $Id: ft.cpp,v 1.8.2.3 2003/05/29 18:54:25 ivan Exp $ */
#include "header.h"
/*
* Include the FFTW header and also define two routines which allow us
* to make usable duplicates of plans for in-place transforms.
* Courtesy of Steven G. Johnson.
*/
#include "fftw.h"
/*
* This is a 3D FFT which uses the FFTW package.
*
* The transform performed is:
*
* if (sign == -1)
* data(kx,ky,kz) <- sum_(x,y,z) { exp(-i*k.r))*data(x,y,z) } / (nx*ny*nz)
*
* if (sign == 1)
* data(x,y,z) <- sum_(kx,ky,kz) { exp(i*k.r))*data(kx,ky,kz) }
*
* nx, ny, nz: size of FFT box
*
* FFTW routines do not divide by (nx*ny*nz) in the sign==-1 case, so
* I do it by hand.
*
* The plus_- and minus_plan's are static so that we do the setup only once
* and on all future calls on FFT boxes of the same size we use those
* plans.
*
* NOTE: setupFFT3D() must be called before using FFT3D().
*
*/
/* Plans used by FFT3D...they are created by setupFFT3D() */
static int plan_nx,plan_ny,plan_nz;
static fftwnd_plan plus_plan,minus_plan;
static int FFTWsetupwasdone = 0;
void setupFFT3D(int nx,int ny,int nz)
{
plan_nx = nx;
plan_ny = ny;
plan_nz = nz;
dft_log("----- setupFFT3D() -----\nSetting up the FFTW subsystem\n");
dft_log("Box size: %d x %d x %d\n", nx, ny, nz);
dft_log_flush();
plus_plan = fftw3d_create_plan(nx,ny,nz, FFTW_BACKWARD,
FFTW_MEASURE|FFTW_IN_PLACE|
FFTW_THREADSAFE|FFTW_USE_WISDOM);
minus_plan = fftw3d_create_plan(nx,ny,nz, FFTW_FORWARD,
FFTW_MEASURE|FFTW_IN_PLACE|
FFTW_THREADSAFE|FFTW_USE_WISDOM);
if (!plus_plan || !minus_plan)
die("\nCan't create plans for FFTW in setupFFT3D()\n\n");
FFTWsetupwasdone = 1;
dft_log_flush();
dft_log("FFTW setup done\n");
dft_log_flush();
}
void FFT3D(int nx,int ny,int nz,complex *data,int sign)
{
#ifdef DFT_PROFILING
timerOn(40); // FFT3D timer
counterIncr(16);
#endif
if (!FFTWsetupwasdone)
die("\n\nFFTW setup was not called! Call setupFFT3D() first!\n\n");
if (nx != plan_nx || ny != plan_ny || nz != plan_nz)
die("\n\nFFT3D() called with sizes different from the static plans!\n\n");
if (sign == 1)
{
fftwnd(plus_plan,1,(FFTW_COMPLEX *)data,1,0,NULL,0,0);
}
else if (sign == -1)
{
fftwnd(minus_plan,1,(FFTW_COMPLEX *)data,1,0,NULL,0,0);
const int nxyz = nx*ny*nz;
const real scale = (real)1.0/(real)(nx*ny*nz);
int i;
for (i=0; i < nxyz; i++)
{
data[i].x *= scale;
data[i].y *= scale;
}
}
#ifdef DFT_PROFILING
timerOff(40); // FFT3D timer
#endif
}
syntax highlighted by Code2HTML, v. 0.9.1