/* This file is part of LPIC++, a particle-in-cell code for simulating the interaction of laser light with plasma. Copyright (C) 1994-1997 Roland Lichters LPIC++ 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include ////////////////////////////////////////////////////////////////////////////////////////// FFT2D::FFT2D( int Q_kw, int periods_1, int steps_pp_1, int screen_1, int periods_2, int steps_pp_2, int screen_2 ) { if (Q_kw){ periods_input_1 = periods_1; periods_input_2 = periods_2; steps_pp_input_1 = steps_pp_1; steps_pp_input_2 = steps_pp_2; screen_input_1 = screen_1; screen_input_2 = screen_2; steps_input_1 = periods_1 * steps_pp_1; steps_input_2 = periods_2 * steps_pp_2; dt_input_1 = (float) periods_input_1 / ( steps_input_1 - 1 ); dt_input_2 = (float) periods_input_2 / ( steps_input_2 - 1 ); steps_1 = steps_ft( steps_input_1 ); steps_2 = steps_ft( steps_input_1 ); steps_half_1 = (int) floor( 0.5*steps_1 + 0.5 ); steps_half_2 = (int) floor( 0.5*steps_2 + 0.5 ); dt_1 = (float) periods_input_1 / ( steps_1 - 1 ); // time step in periods dt_2 = (float) periods_input_2 / ( steps_2 - 1 ); // time step in periods df_1 = (float) 1.0 / periods_input_1; // frequency step df_2 = (float) 1.0 / periods_input_2; // frequency step nn = new int [ 3 ]; nn[1] = steps_1; nn[2] = steps_2; local = fmatrix( 0, steps_1, 0, steps_2 ); data = new float [ 2 * steps_1 * steps_2 + 1 ]; frequency_1 = new float [ steps_1 ]; frequency_2 = new float [ steps_2 ]; // co = fmatrix( 0, steps_half_1+1, 0, steps_2+1 );// pos and neg k, pos frequency! // si = fmatrix( 0, steps_half_1+1, 0, steps_2+1 ); power = fmatrix( 0, steps_half_1+1, 0, steps_2+1 ); if (!nn || !local || !data || !frequency_1 || !frequency_2 || !power) { printf( "\n allocation failure in FFT2D::constructor" ); exit(-1); } } } ////////////////////////////////////////////////////////////////////////////////////////// int FFT2D::steps_ft( int steps_input ) { int MAX_EXPO = 14; int expo, steps_ft; expo = (int) ceil( log(steps_input)/log(2) ); // steps_ft = next power of 2 // larger than steps_input if (expo > MAX_EXPO) { expo = MAX_EXPO; printf( "\n FFT2D: number of steps is 2^%d < %d\n", MAX_EXPO, steps_input ); } steps_ft = (int) pow( 2, expo ); return steps_ft; } ////////////////////////////////////////////////////////////////////////////////////////// float FFT2D::window( float t, int screen_input, int periods_input ) // input: time t in periods // window cuts off smoothly first and last period { float tscr = (float) screen_input; float toff = (float) periods_input - tscr; if ( t < tscr ) return pow( sin(0.5*PI*t/tscr), 2 ); else { if ( t > toff ) return pow( sin(0.5*PI*(1.0-(t-toff)/tscr)), 2 ); else return 1.0; } } ////////////////////////////////////////////////////////////////////////////////////////// void FFT2D::RealFt( float **input ) /* takes real input matrix [0, ..., steps_input_1 - 1] [0, ..., steps_input_2 - 1 ] interpolates to local matrix [0, ..., steps_1 - 1] [0, ..., steps_2 - 1], where steps_1 and steps_2 are powers of 2, usually larger than steps_input i.e. t_1=0 .... (steps_input_1-1) dt_1 i.e. t_2=0 .... (steps_input_2-1) dt_2 returns real output arrays [0, ... , steps_half_1] [0, ..., steps_2] i.e. f_1= 0 .... 1/(2*dt_1) i.e. f_2= -1/(2*dt_2) .... 1/(2*dt_2) returns cosine-transform co = re sine-transform si = im power spectrum pow = 2*(re*re+im*im) */ { int i, index, j; float t, x; int th, tl, xh, xl; float re, im; for( i=0; i=1;idim--) { n=nn[idim]; nrem=ntot/(n*nprev); ip1=nprev << 1; ip2=ip1*n; ip3=ip2*nrem; i2rev=1; for (i2=1;i2<=ip2;i2+=ip1) { if (i2 < i2rev) { for (i1=i2;i1<=i2+ip1-2;i1+=2) { for (i3=i1;i3<=ip3;i3+=ip2) { i3rev=i2rev+i3-i2; SWAP(data[i3],data[i3rev]); SWAP(data[i3+1],data[i3rev+1]); } } } ibit=ip2 >> 1; while (ibit >= ip1 && i2rev > ibit) { i2rev -= ibit; ibit >>= 1; } i2rev += ibit; } ifp1=ip1; while (ifp1 < ip2) { ifp2=ifp1 << 1; theta=isign*6.28318530717959/(ifp2/ip1); wtemp=sin(0.5*theta); wpr = -2.0*wtemp*wtemp; wpi=sin(theta); wr=1.0; wi=0.0; for (i3=1;i3<=ifp1;i3+=ip1) { for (i1=i3;i1<=i3+ip1-2;i1+=2) { for (i2=i1;i2<=ip3;i2+=ifp2) { k1=i2; k2=k1+ifp1; tempr=wr*data[k2]-wi*data[k2+1]; tempi=wr*data[k2+1]+wi*data[k2]; data[k2]=data[k1]-tempr; data[k2+1]=data[k1+1]-tempi; data[k1] += tempr; data[k1+1] += tempi; } } wr=(wtemp=wr)*wpr-wi*wpi+wr; wi=wi*wpr+wtemp*wpi+wi; } ifp1=ifp2; } nprev *= n; } } #undef SWAP ////////////////////////////////////////////////////////////////////////////////////////// //eof