// Fourier transform from x back to (complex) k: kTable* xTable::Transform() const { kTable *kt = new kTable( N, 2*PI/(N*dx) ); fftw_plan plan = fftw_plan_dft_r2c_2d(N,N, array, reinterpret_cast<fftw_complex*> (kt->array), FFTW_ESTIMATE); if (plan==NULL) throw FFTInvalid(); fftw_execute(plan); fftw_destroy_plan(plan); // Now scale the k spectrum and flip signs for x=0 in middle. double fac = scaleby * dx * dx; size_t ind=0; for (int i=0; i<N; i++) for (int j=0; j<=N/2; j++) { if ( (i+j)%2==0) kt->array[ind] *= fac; else kt->array[ind] *= -fac; ind++; } return kt; }
// Fourier transform from x back to (complex) k: void XTable::transform(KTable& kt) const { check_array(); // Make a new copy of data array since measurement will overwrite: FFTW_Array<double> t_array = _array; fftw_plan plan = fftw_plan_dft_r2c_2d( _N,_N, t_array.get_fftw(), kt._array.get_fftw(), FFTW_ESTIMATE); #ifdef FFT_DEBUG if (plan==NULL) throw FFTInvalid(); #endif fftw_execute(plan); fftw_destroy_plan(plan); // Now scale the k spectrum and flip signs for x=0 in middle. double fac = _dx * _dx; size_t ind=0; for (int iy=0; iy<_N; iy++) { for (int ix=0; ix<=_N/2; ix++) { if ( (ix+iy)%2==0) kt._array[ind] *= fac; else kt._array[ind] *= -fac; ind++; } } kt._dk = 2*M_PI/(_N*_dx); }
// Fourier transform from (complex) k to x: xTable* kTable::Transform() const { // We'll need a new k array because FFTW kills the k array in this // operation. Also, to put x=0 in center of array, we need to flop // every other sign of k array, and need to scale. DComplex* t_array = (DComplex*) fftw_malloc(sizeof(DComplex)*N*(N/2+1)); double fac = scaleby * dk * dk / (4*PI*PI); long int ind=0; for (int i=0; i<N; i++) for (int j=0; j<=N/2; j++) { if ( (i+j)%2==0) t_array[ind]=fac * array[ind]; else t_array[ind] = -fac* array[ind]; ind++; } xTable *xt = new xTable( N, 2*PI/(N*dk) ); fftw_plan plan = fftw_plan_dft_c2r_2d(N, N, reinterpret_cast<fftw_complex*> (t_array), xt->array, FFTW_ESTIMATE); if (plan==NULL) throw FFTInvalid(); // Run the transform: fftw_execute(plan); fftw_destroy_plan(plan); fftw_free(t_array); return xt; }
void XTable::fftwMeasure() const { // Make a new copy of data array since measurement will overwrite: // Copy data into new array to avoid NaN's, etc., but not bothering // with scaling, etc. FFTW_Array<double> t_array = _array; KTable kt( _N, 2*M_PI/(_N*_dx) ); fftw_plan plan = fftw_plan_dft_r2c_2d( _N,_N, t_array.get_fftw(), kt._array.get_fftw(), FFTW_MEASURE); #ifdef FFT_DEBUG if (plan==NULL) throw FFTInvalid(); #endif fftw_destroy_plan(plan); }
// Have FFTW develop "wisdom" on doing this kind of transform void KTable::fftwMeasure() const { // Copy data into new array to avoid NaN's, etc., but not bothering // with scaling, etc. FFTW_Array<std::complex<double> > t_array = _array; XTable xt( _N, 2*M_PI/(_N*_dk) ); // Note: The fftw_execute function is the only thread-safe FFTW routine. // So if we decide to go with some kind of multi-threading (rather than multi-process // parallelism) all of the plan creation and destruction calls in this file // will need to be placed in critical blocks or the equivalent (mutex locks, etc.). fftw_plan plan = fftw_plan_dft_c2r_2d( _N, _N, t_array.get_fftw(), xt._array.get_fftw(), FFTW_MEASURE); #ifdef FFT_DEBUG if (plan==NULL) throw FFTInvalid(); #endif fftw_destroy_plan(plan); }
// Fourier transform from (complex) k to x: // This version takes XTable reference as argument void KTable::transform(XTable& xt) const { check_array(); // check proper dimensions for xt assert(_N==xt.getN()); // We'll need a new k array because FFTW kills the k array in this // operation. Also, to put x=0 in center of array, we need to flop // every other sign of k array, and need to scale. dbg<<"Before make t_array"<<std::endl; FFTW_Array<std::complex<double> > t_array(_N); dbg<<"After make t_array"<<std::endl; double fac = _dk * _dk / (4*M_PI*M_PI); long int ind=0; dbg<<"t_array.size = "<<t_array.size()<<std::endl; for (int iy=0; iy<_N; iy++) { dbg<<"ind = "<<ind<<std::endl; for (int ix=0; ix<=_N/2; ix++) { if ( (ix+iy)%2==0) t_array[ind]=fac * _array[ind]; else t_array[ind] = -fac* _array[ind]; ind++; } } dbg<<"After fill t_array"<<std::endl; fftw_plan plan = fftw_plan_dft_c2r_2d( _N, _N, t_array.get_fftw(), xt._array.get_fftw(), FFTW_ESTIMATE); dbg<<"After make plan"<<std::endl; #ifdef FFT_DEBUG if (plan==NULL) throw FFTInvalid(); #endif // Run the transform: fftw_execute(plan); dbg<<"After exec plan"<<std::endl; fftw_destroy_plan(plan); dbg<<"After destroy plan"<<std::endl; xt._dx = 2*M_PI/(_N*_dk); dbg<<"Done transform"<<std::endl; }
// Have FFTW develop "wisdom" on doing this kind of transform void kTable::fftwMeasure() const { DComplex* t_array = (DComplex*) fftw_malloc(sizeof(DComplex)*N*(N/2+1)); // Copy data into new array to avoid NaN's, etc., but not bothering // with scaling, etc. for (int i=0; i<N*(N/2+1); i++) t_array[i] = array[i]; xTable *xt = new xTable( N, 2*PI/(N*dk) ); fftw_plan plan = fftw_plan_dft_c2r_2d(N, N, reinterpret_cast<fftw_complex*> (t_array), xt->array, FFTW_MEASURE); if (plan==NULL) throw FFTInvalid(); delete xt; fftw_free(t_array); fftw_destroy_plan(plan); }
void xTable::fftwMeasure() const { // Make a new copy of data array since measurement will overwrite: double* t_array = (double*) fftw_malloc(sizeof(double)*N*N); // Copy data into new array to avoid NaN's, etc., but not bothering // with scaling, etc. for (int i=0; i<N*N; i++) t_array[i] = array[i]; kTable *kt = new kTable( N, 2*PI/(N*dx) ); fftw_plan plan = fftw_plan_dft_r2c_2d(N,N, t_array, reinterpret_cast<fftw_complex*> (kt->array), FFTW_MEASURE); if (plan==NULL) throw FFTInvalid(); delete kt; fftw_free(t_array); fftw_destroy_plan(plan); }
// same function, takes xTable reference as agrument void kTable::Transform(xTable& xt) const { // ??? check proper dimensions for xt ? Assert(N==xt.getN()); // We'll need a new k array because FFTW kills the k array in this // operation. Also, to put x=0 in center of array, we need to flop // every other sign of k array, and need to scale. DComplex* t_array = (DComplex*) fftw_malloc(sizeof(DComplex)*N*(N/2+1)); double fac = scaleby * dk * dk / (4*PI*PI); long int ind=0; for (int i=0; i<N; i++) for (int j=0; j<=N/2; j++) { if ( (i+j)%2==0) t_array[ind]=fac * array[ind]; else t_array[ind] = -fac* array[ind]; ind++; } fftw_plan plan = fftw_plan_dft_c2r_2d(N, N, reinterpret_cast<fftw_complex*> (t_array), xt.array, FFTW_ESTIMATE); if (plan==NULL) throw FFTInvalid(); // Run the transform: fftw_execute(plan); fftw_destroy_plan(plan); fftw_free(t_array); xt.dx = 2*PI/(N*dk); xt.scaleby = 1.; xt.valid = true; }