OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
FFT.h
Go to the documentation of this file.
1//
2// IPPL FFT
3//
4// Copyright (c) 2008-2018
5// Paul Scherrer Institut, Villigen PSI, Switzerland
6// All rights reserved.
7//
8// OPAL is licensed under GNU GPL version 3.
9//
10
18#ifndef IPPL_FFT_FFT_H
19#define IPPL_FFT_FFT_H
20
21#include "FFT/FFTBase.h"
22
23// forward declarations
24//template <unsigned Dim> class FieldLayout;
26template <class T, unsigned Dim> class BareField;
27template <class T, unsigned Dim> class LField;
28
29
30
34class CCTransform {};
38class RCTransform {};
43
47template <class Transform, size_t Dim, class T>
48class FFT : public FFTBase<Dim,T> {};
49
53template <size_t Dim, class T>
54class FFT<CCTransform,Dim,T> : public FFTBase<Dim,T> {
55
56public:
57
59 typedef std::complex<T> Complex_t;
63
69 FFT(const Domain_t& cdomain, const bool transformTheseDims[Dim],
70 const bool& compressTemps=false);
71
78FFT(const Domain_t& cdomain, const bool& compressTemps=false)
80
81 // construct array of axis lengths
82 int lengths[Dim];
83 size_t d;
84 for (d=0; d<Dim; ++d)
85 lengths[d] = cdomain[d].length();
86
87 // construct array of transform types for FFT Engine, compute normalization
88 int transformTypes[Dim];
89 T& normFact = this->getNormFact();
90 normFact = 1.0;
91 for (d=0; d<Dim; ++d) {
92 transformTypes[d] = FFTBase<Dim,T>::ccFFT; // all transforms are complex-to-complex
93 normFact /= lengths[d];
94 }
95
96 // set up FFT Engine
97 this->getEngine().setup(Dim, transformTypes, lengths);
98 // set up the temporary fields
99 setup();
100 }
101
102
103 // Destructor
104 ~FFT(void);
105
113 void transform(int direction, ComplexField_t& f, ComplexField_t& g,
114 const bool& constInput=false);
118 void transform(const char* directionName, ComplexField_t& f,
119 ComplexField_t& g, const bool& constInput=false);
120
123 void transform(int direction, ComplexField_t& f);
124
125 void transform(const char* directionName, ComplexField_t& f) {
126 // invoke in-place transform function using direction name string
127 int direction = this->getDirection(directionName);
128
129 // Check domain of incoming Field
130 const Layout_t& in_layout = f.getLayout();
131 const Domain_t& in_dom = in_layout.getDomain();
132 PAssert_EQ(this->checkDomain(this->getDomain(),in_dom), true);
133
134 // Common loop iterate and other vars:
135 size_t d;
136 int idim; // idim loops over the number of transform dims.
137 int begdim, enddim; // beginning and end of transform dim loop
138 size_t nTransformDims = this->numTransformDims();
139 // Field* for temp Field management:
140 ComplexField_t* temp = &f;
141 // Local work array passed to FFT:
142 Complex_t* localdata;
143
144 // Loop over the dimensions be transformed:
145 begdim = (direction == +1) ? 0 : (nTransformDims-1);
146 enddim = (direction == +1) ? nTransformDims : -1;
147 for (idim = begdim; idim != enddim; idim += direction) {
148
149 // Now do the serial transforms along this dimension:
150
151 bool skipTranspose = false;
152 // if this is the first transform dimension, we might be able
153 // to skip the transpose into the first temporary Field
154 if (idim == begdim) {
155 // get domain for comparison
156 const Domain_t& first_dom = tempLayouts_m[idim]->getDomain();
157 // check that zeroth axis is the same and is serial
158 // and that there are no guard cells
159 skipTranspose = ( (in_dom[0].sameBase(first_dom[0])) &&
160 (in_dom[0].length() == first_dom[0].length()) &&
161 (in_layout.getDistribution(0) == SERIAL) &&
163 }
164
165 // if this is the last transform dimension, we might be able
166 // to skip the last temporary and transpose right into f
167 if (idim == enddim-direction) {
168 // get domain for comparison
169 const Domain_t& last_dom = tempLayouts_m[idim]->getDomain();
170 // check that zeroth axis is the same and is serial
171 // and that there are no guard cells
172 skipTranspose = ( (in_dom[0].sameBase(last_dom[0])) &&
173 (in_dom[0].length() == last_dom[0].length()) &&
174 (in_layout.getDistribution(0) == SERIAL) &&
176 }
177
178 if (!skipTranspose) {
179 // transpose and permute to Field with transform dim first
180 (*tempFields_m[idim])[tempLayouts_m[idim]->getDomain()] =
181 (*temp)[temp->getLayout().getDomain()];
182
183 // Compress out previous iterate's storage:
184 if (this->compressTemps() && temp != &f) *temp = 0;
185 temp = tempFields_m[idim]; // Field* management aid
186 }
187 else if (idim == enddim-direction && temp != &f) {
188 // last transform and we can skip the last temporary field
189 // so do the transpose here using f instead
190
191 // transpose and permute to Field with transform dim first
192 f[in_dom] = (*temp)[temp->getLayout().getDomain()];
193
194 // Compress out previous iterate's storage:
195 if (this->compressTemps()) *temp = 0;
196 temp = &f; // Field* management aid
197 }
198
199
200
201 // Loop over all the Vnodes, working on the LField in each.
202 typename ComplexField_t::const_iterator_if l_i, l_end = temp->end_if();
203 for (l_i = temp->begin_if(); l_i != l_end; ++l_i) {
204
205 // Get the LField
206 ComplexLField_t* ldf = (*l_i).second.get();
207 // make sure we are uncompressed
208 ldf->Uncompress();
209 // get the raw data pointer
210 localdata = ldf->getP();
211
212 // Do 1D complex-to-complex FFT's on all the strips in the LField:
213 int nstrips = 1, length = ldf->size(0);
214 for (d=1; d<Dim; ++d) nstrips *= ldf->size(d);
215 for (int istrip=0; istrip<nstrips; ++istrip) {
216 // Do the 1D FFT:
217 this->getEngine().callFFT(idim, direction, localdata);
218 // advance the data pointer
219 localdata += length;
220 } // loop over 1D strips
221 } // loop over all the LFields
222
223
224 } // loop over all transformed dimensions
225
226 // skip final assignment and compress if we used f as final temporary
227 if (temp != &f) {
228
229 // Now assign back into original Field, and compress last temp's storage:
230 f[in_dom] = (*temp)[temp->getLayout().getDomain()];
231 if (this->compressTemps()) *temp = 0;
232
233 }
234
235 // Normalize:
236 if (direction == +1)
237 f *= Complex_t(this->getNormFact(), 0.0);
238 return;
239 }
240private:
241
246 void setup(void);
247
255
260
261};
262
263
267template <size_t Dim, class T>
268inline void
270 const char* directionName,
273 const bool& constInput)
274{
275 int dir = this->getDirection(directionName);
276 transform(dir, f, g, constInput);
277 return;
278}
279
280
284template <class T>
285class FFT<CCTransform,1U,T> : public FFTBase<1U,T> {
286
287public:
288
289 // typedefs
291 typedef std::complex<T> Complex_t;
295
296 // Constructors:
297
303 FFT(const Domain_t& cdomain, const bool transformTheseDims[1U],
304 const bool& compressTemps=false);
311 FFT(const Domain_t& cdomain, const bool& compressTemps=false);
312
313 // Destructor
314 ~FFT(void);
315
323 void transform(int direction, ComplexField_t& f, ComplexField_t& g,
324 const bool& constInput=false);
328 void transform(const char* directionName, ComplexField_t& f,
329 ComplexField_t& g, const bool& constInput=false);
330
334 void transform(int direction, ComplexField_t& f);
335 void transform(const char* directionName, ComplexField_t& f);
336
337private:
338
343 void setup(void);
344
349
354
355};
356
357
358// inline function definitions
359
363template <class T>
364inline void
366 const char* directionName,
369 const bool& constInput)
370{
371 int dir = this->getDirection(directionName);
372 transform(dir, f, g, constInput);
373 return;
374}
375
379template <class T>
380inline void
382 const char* directionName,
384{
385 int dir = this->getDirection(directionName);
386 transform(dir, f);
387 return;
388}
389
390
394template <size_t Dim, class T>
395class FFT<RCTransform,Dim,T> : public FFTBase<Dim,T> {
396
397private:
398
399public:
400
401 // typedefs
405 typedef std::complex<T> Complex_t;
409
410 // Constructors:
411
417 FFT(const Domain_t& rdomain, const Domain_t& cdomain,
418 const bool transformTheseDims[Dim], const bool& compressTemps=false);
419
423 FFT(const Domain_t& rdomain, const Domain_t& cdomain,
424 const bool& compressTemps=false, int serialAxes = 1);
425
426 // Destructor
427 ~FFT(void);
428
436 void transform(int direction, RealField_t& f, ComplexField_t& g,
437 const bool& constInput=false);
438 void transform(const char* directionName, RealField_t& f,
439 ComplexField_t& g, const bool& constInput=false);
440
447 void transform(int direction, ComplexField_t& f, RealField_t& g,
448 const bool& constInput=false);
449 void transform(const char* directionName, ComplexField_t& f,
450 RealField_t& g, const bool& constInput=false);
451
456private:
457
462 void setup(void);
463
470
475
480
485
491
496};
497
498// Inline function definitions
499
503template <size_t Dim, class T>
504inline void
506 const char* directionName,
509 const bool& constInput)
510{
511 int dir = this->getDirection(directionName);
512 transform(dir, f, g, constInput);
513 return;
514}
515
519template <size_t Dim, class T>
520inline void
522 const char* directionName,
525 const bool& constInput)
526{
527 int dir = this->getDirection(directionName);
528 transform(dir, f, g, constInput);
529 return;
530}
531
532
536template <class T>
537class FFT<RCTransform,1U,T> : public FFTBase<1U,T> {
538
539public:
540
541 // typedefs
545 typedef std::complex<T> Complex_t;
549
550 // Constructors:
551
558 FFT(const Domain_t& rdomain, const Domain_t& cdomain,
559 const bool transformTheseDims[1U], const bool& compressTemps=false);
563 FFT(const Domain_t& rdomain, const Domain_t& cdomain,
564 const bool& compressTemps=false);
565
569 ~FFT(void);
570
579 void transform(int direction, RealField_t& f, ComplexField_t& g,
580 const bool& constInput=false);
581 void transform(const char* directionName, RealField_t& f,
582 ComplexField_t& g, const bool& constInput=false);
583
588 void transform(int direction, ComplexField_t& f, RealField_t& g,
589 const bool& constInput=false);
590 void transform(const char* directionName, ComplexField_t& f,
591 RealField_t& g, const bool& constInput=false);
592
593private:
594
599 void setup(void);
600
605
610
615
620 // const Domain_t& complexDomain_m;
622};
623
627template <class T>
628inline void
630 const char* directionName,
633 const bool& constInput)
634{
635 int dir = this->getDirection(directionName);
636 transform(dir, f, g, constInput);
637 return;
638}
639
643template <class T>
644inline void
646 const char* directionName,
649 const bool& constInput)
650{
651 int dir = this->getDirection(directionName);
652 transform(dir, f, g, constInput);
653 return;
654}
655
659template <size_t Dim, class T>
660class FFT<SineTransform,Dim,T> : public FFTBase<Dim,T> {
661
662public:
663
664 // typedefs
668 typedef std::complex<T> Complex_t;
672
680 FFT(const Domain_t& rdomain, const Domain_t& cdomain,
681 const bool transformTheseDims[Dim],
682 const bool sineTransformDims[Dim], const bool& compressTemps=false);
686 FFT(const Domain_t& rdomain, const Domain_t& cdomain,
687 const bool sineTransformDims[Dim], const bool& compressTemps=false);
695 FFT(const Domain_t& rdomain, const bool sineTransformDims[Dim],
696 const bool& compressTemps=false);
700 FFT(const Domain_t& rdomain, const bool& compressTemps=false);
701
702 ~FFT(void);
703
714 void transform(int direction, RealField_t& f, ComplexField_t& g,
715 const bool& constInput=false);
716 void transform(const char* directionName, RealField_t& f,
717 ComplexField_t& g, const bool& constInput=false);
718
723 void transform(int direction, ComplexField_t& f, RealField_t& g,
724 const bool& constInput=false);
725 void transform(const char* directionName, ComplexField_t& f,
726 RealField_t& g, const bool& constInput=false);
727
737 void transform(int direction, RealField_t& f, RealField_t& g,
738 const bool& constInput=false);
739 void transform(const char* directionName, RealField_t& f,
740 RealField_t& g, const bool& constInput=false);
741
745 void transform(int direction, RealField_t& f);
746 void transform(const char* directionName, RealField_t& f);
747
748private:
749
754 void setup(void);
755
756
757
761 bool sineTransformDims_m[Dim];
762
767
776
781
786
791
796};
797
801template <size_t Dim, class T>
802inline void
804 const char* directionName,
807 const bool& constInput)
808{
809 int dir = this->getDirection(directionName);
810 transform(dir, f, g, constInput);
811 return;
812}
813
817template <size_t Dim, class T>
818inline void
820 const char* directionName,
823 const bool& constInput)
824{
825 int dir = this->getDirection(directionName);
826 transform(dir, f, g, constInput);
827 return;
828}
829
833template <size_t Dim, class T>
834inline void
836 const char* directionName,
839 const bool& constInput)
840{
841 int dir = this->getDirection(directionName);
842 transform(dir, f, g, constInput);
843 return;
844}
845
849template <size_t Dim, class T>
850inline void
852 const char* directionName,
854{
855 int dir = this->getDirection(directionName);
856 transform(dir, f);
857 return;
858}
859
860
864template <class T>
865class FFT<SineTransform,1U,T> : public FFTBase<1U,T> {
866
867public:
868
873
881 FFT(const Domain_t& rdomain, const bool sineTransformDims[1U],
882 const bool& compressTemps=false);
886 FFT(const Domain_t& rdomain, const bool& compressTemps=false);
887
888
889 ~FFT(void);
890
899 void transform(int direction, RealField_t& f, RealField_t& g,
900 const bool& constInput=false);
901 void transform(const char* directionName, RealField_t& f,
902 RealField_t& g, const bool& constInput=false);
903
907 void transform(int direction, RealField_t& f);
908 void transform(const char* directionName, RealField_t& f);
909
910private:
911
916 void setup(void);
917
922
927
928};
929
933template <class T>
934inline void
936 const char* directionName,
939 const bool& constInput)
940{
941 int dir = this->getDirection(directionName);
942 transform(dir, f, g, constInput);
943 return;
944}
945
949template <class T>
950inline void
952 const char* directionName,
954{
955 int dir = this->getDirection(directionName);
956 transform(dir, f);
957 return;
958}
959#include "FFT/FFT.hpp"
960#endif // IPPL_FFT_FFT_H
const unsigned Dim
@ SERIAL
Definition: FieldLayout.h:55
#define PAssert_EQ(a, b)
Definition: PAssert.h:104
const GuardCellSizes< Dim > & getGC() const
Definition: BareField.h:146
iterator_if begin_if()
Definition: BareField.h:100
ac_id_larray::const_iterator const_iterator_if
Definition: BareField.h:93
Layout_t & getLayout() const
Definition: BareField.h:131
iterator_if end_if()
Definition: BareField.h:101
Definition: LField.h:58
T * getP()
Definition: LField.h:100
int size(unsigned d) const
Definition: LField.h:97
void Uncompress(bool fill_domain=true)
Definition: LField.h:172
Definition: FFT.h:48
void transform(int direction, ComplexField_t &f, ComplexField_t &g, const bool &constInput=false)
BareField< Complex_t, Dim > ComplexField_t
Definition: FFT.h:60
LField< Complex_t, Dim > ComplexLField_t
Definition: FFT.h:61
FFTBase< Dim, T >::Domain_t Domain_t
Definition: FFT.h:62
FieldLayout< Dim > Layout_t
Definition: FFT.h:58
void transform(const char *directionName, ComplexField_t &f)
Definition: FFT.h:125
FFT(const Domain_t &cdomain, const bool &compressTemps=false)
Definition: FFT.h:78
std::complex< T > Complex_t
Definition: FFT.h:59
void transform(int direction, ComplexField_t &f)
FFT(const Domain_t &cdomain, const bool transformTheseDims[Dim], const bool &compressTemps=false)
Layout_t ** tempLayouts_m
Definition: FFT.h:254
void transform(const char *directionName, ComplexField_t &f, ComplexField_t &g, const bool &constInput=false)
ComplexField_t ** tempFields_m
Definition: FFT.h:259
FFTBase< 1U, T >::Domain_t Domain_t
Definition: FFT.h:294
void transform(const char *directionName, ComplexField_t &f, ComplexField_t &g, const bool &constInput=false)
void transform(const char *directionName, ComplexField_t &f)
Layout_t * tempLayouts_m
Definition: FFT.h:348
std::complex< T > Complex_t
Definition: FFT.h:291
FFT(const Domain_t &cdomain, const bool transformTheseDims[1U], const bool &compressTemps=false)
void transform(int direction, ComplexField_t &f, ComplexField_t &g, const bool &constInput=false)
LField< Complex_t, 1U > ComplexLField_t
Definition: FFT.h:293
FFT(const Domain_t &cdomain, const bool &compressTemps=false)
void transform(int direction, ComplexField_t &f)
FieldLayout< 1U > Layout_t
Definition: FFT.h:290
BareField< Complex_t, 1U > ComplexField_t
Definition: FFT.h:292
ComplexField_t * tempFields_m
Definition: FFT.h:353
BareField< Complex_t, Dim > ComplexField_t
Definition: FFT.h:406
ComplexField_t ** tempFields_m
Definition: FFT.h:479
std::complex< T > Complex_t
Definition: FFT.h:405
Layout_t * tempRLayout_m
Definition: FFT.h:474
FFTBase< Dim, T >::Domain_t Domain_t
Definition: FFT.h:408
void transform(const char *directionName, ComplexField_t &f, RealField_t &g, const bool &constInput=false)
void transform(int direction, RealField_t &f, ComplexField_t &g, const bool &constInput=false)
RealField_t * tempRField_m
Definition: FFT.h:484
FFT(const Domain_t &rdomain, const Domain_t &cdomain, const bool &compressTemps=false, int serialAxes=1)
Layout_t ** tempLayouts_m
Definition: FFT.h:469
LField< Complex_t, Dim > ComplexLField_t
Definition: FFT.h:407
Domain_t complexDomain_m
Definition: FFT.h:490
void transform(const char *directionName, RealField_t &f, ComplexField_t &g, const bool &constInput=false)
FieldLayout< Dim > Layout_t
Definition: FFT.h:402
BareField< T, Dim > RealField_t
Definition: FFT.h:403
LField< T, Dim > RealLField_t
Definition: FFT.h:404
void transform(int direction, ComplexField_t &f, RealField_t &g, const bool &constInput=false)
FFT(const Domain_t &rdomain, const Domain_t &cdomain, const bool transformTheseDims[Dim], const bool &compressTemps=false)
void transform(const char *directionName, ComplexField_t &f, RealField_t &g, const bool &constInput=false)
std::complex< T > Complex_t
Definition: FFT.h:545
LField< Complex_t, 1U > ComplexLField_t
Definition: FFT.h:547
FieldLayout< 1U > Layout_t
Definition: FFT.h:542
FFTBase< 1U, T >::Domain_t Domain_t
Definition: FFT.h:548
void transform(int direction, RealField_t &f, ComplexField_t &g, const bool &constInput=false)
BareField< T, 1U > RealField_t
Definition: FFT.h:543
FFT(const Domain_t &rdomain, const Domain_t &cdomain, const bool transformTheseDims[1U], const bool &compressTemps=false)
void transform(const char *directionName, RealField_t &f, ComplexField_t &g, const bool &constInput=false)
BareField< Complex_t, 1U > ComplexField_t
Definition: FFT.h:546
ComplexField_t * tempFields_m
Definition: FFT.h:609
FFT(const Domain_t &rdomain, const Domain_t &cdomain, const bool &compressTemps=false)
LField< T, 1U > RealLField_t
Definition: FFT.h:544
Domain_t complexDomain_m
Definition: FFT.h:621
void transform(int direction, ComplexField_t &f, RealField_t &g, const bool &constInput=false)
Layout_t * tempRLayout_m
Definition: FFT.h:614
Layout_t * tempLayouts_m
Definition: FFT.h:604
BareField< T, Dim > RealField_t
Definition: FFT.h:666
void transform(int direction, RealField_t &f)
ComplexField_t ** tempFields_m
Definition: FFT.h:785
void transform(int direction, RealField_t &f, ComplexField_t &g, const bool &constInput=false)
void transform(int direction, ComplexField_t &f, RealField_t &g, const bool &constInput=false)
const Domain_t * complexDomain_m
Definition: FFT.h:795
std::complex< T > Complex_t
Definition: FFT.h:668
Layout_t ** tempRLayouts_m
Definition: FFT.h:780
Layout_t ** tempLayouts_m
Definition: FFT.h:775
FFT(const Domain_t &rdomain, const bool sineTransformDims[Dim], const bool &compressTemps=false)
FFT(const Domain_t &rdomain, const bool &compressTemps=false)
FFT(const Domain_t &rdomain, const Domain_t &cdomain, const bool transformTheseDims[Dim], const bool sineTransformDims[Dim], const bool &compressTemps=false)
void transform(int direction, RealField_t &f, RealField_t &g, const bool &constInput=false)
BareField< Complex_t, Dim > ComplexField_t
Definition: FFT.h:669
RealField_t ** tempRFields_m
Definition: FFT.h:790
FFT(const Domain_t &rdomain, const Domain_t &cdomain, const bool sineTransformDims[Dim], const bool &compressTemps=false)
FFTBase< Dim, T >::Domain_t Domain_t
Definition: FFT.h:671
LField< Complex_t, Dim > ComplexLField_t
Definition: FFT.h:670
void transform(const char *directionName, RealField_t &f, RealField_t &g, const bool &constInput=false)
LField< T, Dim > RealLField_t
Definition: FFT.h:667
void transform(const char *directionName, RealField_t &f, ComplexField_t &g, const bool &constInput=false)
void transform(const char *directionName, ComplexField_t &f, RealField_t &g, const bool &constInput=false)
void transform(const char *directionName, RealField_t &f)
FieldLayout< Dim > Layout_t
Definition: FFT.h:665
Layout_t * tempRLayouts_m
Definition: FFT.h:921
void transform(int direction, RealField_t &f)
FFT(const Domain_t &rdomain, const bool sineTransformDims[1U], const bool &compressTemps=false)
FieldLayout< 1U > Layout_t
Definition: FFT.h:869
RealField_t * tempRFields_m
Definition: FFT.h:926
void transform(const char *directionName, RealField_t &f, RealField_t &g, const bool &constInput=false)
FFT(const Domain_t &rdomain, const bool &compressTemps=false)
void transform(int direction, RealField_t &f, RealField_t &g, const bool &constInput=false)
void transform(const char *directionName, RealField_t &f)
FFTBase< 1U, T >::Domain_t Domain_t
Definition: FFT.h:872
LField< T, 1U > RealLField_t
Definition: FFT.h:871
BareField< T, 1U > RealField_t
Definition: FFT.h:870
int getDirection(const char *directionName) const
translate direction name string into dimension number
Definition: FFTBase.h:225
Precision_t & getNormFact(void)
get the FFT normalization factor
Definition: FFTBase.h:157
const Domain_t & getDomain(void) const
get our domain
Definition: FFTBase.h:160
unsigned numTransformDims(void) const
query number of transform dimensions
Definition: FFTBase.h:148
bool compressTemps(void) const
do we compress temps?
Definition: FFTBase.h:166
InternalFFT_t & getEngine(void)
access the internal FFT Engine
Definition: FFTBase.h:154
@ ccFFT
Definition: FFTBase.h:63
bool checkDomain(const Domain_t &dom1, const Domain_t &dom2) const
compare indexes of two domains
Definition: FFTBase.h:269
void callFFT(unsigned transformDim, int direction, Complex_t *data)
void setup(unsigned numTransformDims, const int *transformTypes, const int *axisLengths)
Definition: fftpack_FFT.h:153
const NDIndex< Dim > & getDomain() const
Definition: FieldLayout.h:325
e_dim_tag getDistribution(unsigned int d) const
Definition: FieldLayout.h:396