1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
28 #include "fftRenumber.H"
30 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 #define SWAP(a,b) tempr=(a); (a)=(b); (b)=tempr
38 #define TWOPI 6.28318530717959
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 transformDirection isign
51 // Check for power of two
52 unsigned int dimCount = nn[idim];
53 if (!dimCount || (dimCount & (dimCount - 1)))
57 "fft::transform(complexField&, const labelList&, "
59 ) << "number of elements in direction " << idim
60 << " is not a power of 2" << endl
61 << " Number of elements in each direction = " << nn
66 const label ndim = nn.size();
68 label i1, i2, i3, i2rev, i3rev, ip1, ip2, ip3, ifp1, ifp2;
69 label ibit, k1, k2, n, nprev, nrem, idim;
71 scalar theta, wi, wpi, wpr, wr, wtemp;
72 scalar* data = reinterpret_cast<scalar*>(field.begin()) - 1;
75 // if inverse transform : renumber before transform
77 if (isign == REVERSE_TRANSFORM)
79 fftRenumber(field, nn);
92 for (idim=ndim; idim>=1; idim--)
95 nrem = ntot/(n*nprev);
101 for (i2=1; i2<=ip2; i2+=ip1)
105 for (i1=i2; i1<=i2 + ip1 - 2; i1+=2)
107 for (i3=i1; i3<=ip3; i3+=ip2)
109 i3rev = i2rev + i3 - i2;
110 SWAP(data[i3], data[i3rev]);
111 SWAP(data[i3 + 1], data[i3rev + 1]);
117 while (ibit >= ip1 && i2rev > ibit)
131 theta = isign*TWOPI/(ifp2/ip1);
132 wtemp = sin(0.5*theta);
133 wpr = -2.0*wtemp*wtemp;
138 for (i3 = 1; i3 <= ifp1; i3 += ip1)
140 for (i1 = i3; i1 <= i3 + ip1 - 2; i1 += 2)
142 for (i2 = i1; i2 <= ip3; i2 += ifp2)
146 tempr = scalar(wr*data[k2]) - scalar(wi*data[k2 + 1]);
147 tempi = scalar(wr*data[k2 + 1]) + scalar(wi*data[k2]);
148 data[k2] = data[k1] - tempr;
149 data[k2 + 1] = data[k1 + 1] - tempi;
151 data[k1 + 1] += tempi;
155 wr = (wtemp = wr)*wpr - wi*wpi + wr;
156 wi = wi*wpr + wtemp*wpi + wi;
164 // if forward transform : renumber after transform
166 if (isign == FORWARD_TRANSFORM)
168 fftRenumber(field, nn);
172 // scale result (symmetric scale both forward and inverse transform)
174 scalar recRootN = 1.0/sqrt(scalar(ntot));
178 field[i] *= recRootN;
183 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
188 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
190 tmp<complexField> fft::forwardTransform
192 const tmp<complexField>& tfield,
196 tmp<complexField> tfftField(new complexField(tfield));
198 transform(tfftField(), nn, FORWARD_TRANSFORM);
206 tmp<complexField> fft::reverseTransform
208 const tmp<complexField>& tfield,
212 tmp<complexField> tifftField(new complexField(tfield));
214 transform(tifftField(), nn, REVERSE_TRANSFORM);
222 tmp<complexVectorField> fft::forwardTransform
224 const tmp<complexVectorField>& tfield,
228 tmp<complexVectorField> tfftVectorField
230 new complexVectorField
236 for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
238 tfftVectorField().replace
241 forwardTransform(tfield().component(cmpt), nn)
247 return tfftVectorField;
251 tmp<complexVectorField> fft::reverseTransform
253 const tmp<complexVectorField>& tfield,
257 tmp<complexVectorField> tifftVectorField
259 new complexVectorField
265 for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
267 tifftVectorField().replace
270 reverseTransform(tfield().component(cmpt), nn)
276 return tifftVectorField;
280 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
282 } // End namespace Foam
284 // ************************************************************************* //