void ath_2d_fft(struct ath_2d_fft_plan *ath_plan, fftw_complex *data) { #ifdef FFT_BLOCK_DECOMP fft_2d(data, data, ath_plan->dir, ath_plan->plan); #else /* FFT_BLOCK_DECOMP */ /* Plan already includes forward/backward */ fftw_execute_dft(ath_plan->plan, data, data); #endif /* FFT_BLOCK_DECOMP */ return; }
/* FFT profile keys: inverse => BOOL; direct or inverse transform */ PImage IPA__Global_fft(PImage img,HV *profile) { #define METHOD "IPA::Global::fft" dPROFILE; Bool inverse = 0, failed = false; PImage ret = nil; double * buffer = nil; if ( sizeof(double) % 2) { warn("%s:'double' is even-sized on this platform", METHOD); return nil; } if ( !img || !kind_of(( Handle) img, CImage)) croak("%s: not an image passed", METHOD); if ( !pow2( img-> w)) croak("%s: image width is not a power of 2", METHOD); if ( !pow2( img-> h)) croak("%s: image height is not a power of 2", METHOD); if ( pexist( inverse)) inverse = pget_B( inverse); /* preparing structures */ ret = ( PImage) img-> self-> dup(( Handle) img); if ( !ret) fail( "%s: Return image allocation failed"); ++SvREFCNT( SvRV( ret-> mate)); ret-> self-> set_type(( Handle) ret, imDComplex); if ( ret-> type != imDComplex) { warn("%s:Cannot set image to imDComplex", METHOD); failed = 1; goto EXIT; } buffer = malloc((sizeof(double) * img-> w * 2)); if ( !buffer) { warn("%s: Error allocating %d bytes", METHOD, (int)(sizeof(double) * img-> w * 2)); failed = 1; goto EXIT; } fft_2d(( double *) ret-> data, ret-> w, ret-> h, inverse ? FFT_INVERSE : FFT_DIRECT, buffer); EXIT: free( buffer); if ( ret) --SvREFCNT( SvRV( ret-> mate)); return failed ? nil : ret; #undef METHOD }
int main(int argc, char** argv) { //Precompute FFT coefficients Wkn_fft = precompute_fft_coefficients(); Wkn_ifft = precompute_ifft_coefficients(); // Declare local variables int i, j, n; // Read in data // 1. allocate buffer space for the data. Holds Nx * Ny * Nf complex numbers. // 2. pass the filename and buffer to read_data which will read the file // into the buffer. printf("Reading Data ...\n"); tick(); complex* s = (complex*)safe_malloc(Nx * Ny * Nf * sizeof(complex), "Failed to allocate memory for radar data."); read_data(s, "scene_4.dat"); tock(); // Perform a single 2D FFT for each frequency // Each element s[i,j,n] is located at s[i * Ny * Nf + j * Nf + n] // Thus x-stride = Ny*Nf, y-stride = Nf, and z-stride = 1 // and each xy plane starts at s + 0 * Ny * Nf + 0 * Nf + n printf("Performing FFT\n"); tick(); for(n=0; n<Nf; n++) fft_2d(s + n, Nx, Ny, Ny*Nf, Nf); tock(); // Multiply each element in the frequency-domain signal by the // downward continuation phase operator. // 1. for each element (i,j,n) in the signal matrix // i in 0 ... Nx, j in 0 ... Ny, n in 0 ... Nf // 2. compute kx, ky, and k // kx = 2*pi/Dx * i/Nx if i < Nx/2, // 2*pi/Dx * (i-Nx)/Nx otherwise // ky = 2*pi/Dy * j/Ny if j < Ny/2, // 2*pi/Dy * (j-Ny)/Ny otherwise // w = 2*pi*(f0 + n*Df) // k = w/c // // 3. compute kz // kz = sqrt(4 * k^2 - kx^2 - ky^2 ) // 4. compute the phase delay // phi = exp(j * kz * z0) // 5. multiply the signal with the phase delay // where s(i,j,k) = s[i * Ny * Nf + j * Nf + n] printf("Performing Downward Continuation.\n"); tick(); for(i=0; i<Nx; i++) for(j=0; j<Ny; j++) for(n=0; n<Nf; n++){ float kx = i < Nx/2 ? 2*pi/Dx * i/Nx : 2*pi/Dx * (i - Nx)/Nx; float ky = j < Ny/2 ? 2*pi/Dy * j/Ny : 2*pi/Dy * (j - Ny)/Ny; float w = 2*pi*(f0 + n*Df); float k = w/c_speed; float kz = sqrt(4*k*k - kx*kx - ky*ky); complex phi = c_jexp(kz * z0); s[i * Ny * Nf + j * Nf + n] = c_mult(s[i * Ny * Nf + j * Nf + n], phi); } tock(); // Calculate the range of the Stolt interpolation indices. // The minimum angular frequency, w_min = 2*pi * f0 // The maximum angular frequency, w_max = 2*pi * (f0 + (N - 1)*Df) // From which the // minimum wavenumber, k_min = w_min / c // maximum wavenumber, k_max = w_max / c // The maximum wavenumber in the x direction, kx_max = 2*pi/Dx * 0.5 * (Nx-1)/Nx // The maximum wavenumber in the y direction, ky_max = 2*pi/Dy * 0.5 * (Ny-1)/Ny // The minimum wavenumbers in the x and y direction are assumed to be 0 // From which the // minimum wavenumber in the z direction, kz_min = sqrt(4*k_min^2 - kx_max^2 - ky_max^2) // maximum wavenumber in the z direction, kz_max = sqrt(4*k_max^2 - 0 - 0) float w_min = 2*pi * f0; float w_max = 2*pi * (f0 + (Nf - 1)*Df); float k_min = w_min / c_speed; float k_max = w_max / c_speed; float kx_max = 2*pi/Dx * 0.5 * (Nx-1)/Nx; float ky_max = 2*pi/Dy * 0.5 * (Ny-1)/Ny; float kz_min = sqrt(4*k_min*k_min - kx_max*kx_max - ky_max*ky_max); float kz_max = sqrt(4*k_max*k_max); // Perform Stolt Interpolation // 1. for each step in the x direction, i in 0 ... Nx // and each step in the y direction, j in 0 ... Ny // 2. compute kx, and ky as per step 2. above // 3. create float buffer of size Nf for storing the interpolation indices, n_interp // 4. for each step in frequency, n in 0 ... Nf // compute kz = kz_min + (kz_max - kz_min) * n/(Nf - 1) // 4. compute desired k = 0.5 * sqrt(kx^2 + ky^2 + kz^2) // 5. which corresponds to the interpolated array element // n_interp[n] = (c*k/(2*pi) - f0)/Df // 6. resample this line in s on interpolated indices n_interp // s[i,j,n] is at s[i * Ny * Nf + j * Nf + n] thus this line // starts at s + i * Ny * Nf + j * Nf + 0, has length Nf, and has stride 1 printf("Performing Stolt Interpolation.\n"); tick(); for(i=0; i<Nx; i++) for(j=0; j<Ny; j++){ float kx = i < Nx/2 ? 2*pi/Dx * i/Nx : 2*pi/Dx * (i - Nx)/Nx; float ky = j < Ny/2 ? 2*pi/Dy * j/Ny : 2*pi/Dy * (j - Ny)/Ny; float n_interp[Nf]; for(n=0; n<Nf; n++){ float kz = kz_min + (kz_max - kz_min) * n/(Nf - 1); float k = 0.5 * sqrt(kx*kx + ky*ky + kz*kz); n_interp[n] = (c_speed*k/(2*pi) - f0)/Df; } resample_1d(s + i*Ny*Nf + j*Nf, Nf, 1, n_interp); } tock(); // Perform a 3D IFFT on the signal // Each element s[i,j,n] is located at s[i * Ny * Nf + j * Nf + n] // Thus x-stride = Ny*Nf, y-stride = Nf, and z-stride = 1 printf("Performing IFFT.\n"); tick(); ifft_3d(s, Nx, Ny, Nf, Ny*Nf, Nf, 1); tock(); // End the simulation by writing out the computed signal and write it out to a file. // Pass the computed matrix and a output filename to write_data() printf("Writing data ...\n"); tick(); write_data(s, "scene_4.out"); tock(); printf("Done.\n"); // Free all the temporary memory free(s); }
PImage IPA__Global_band_filter(PImage img,HV *profile) { #define METHOD "IPA::Global::band_filter" dPROFILE; PImage ret; int spatial = 1, homomorph = 0, lw, failed = 0, LowPass = 0; double MinVal = 0.0, Power = 2.0, CutOff = 20.0, Boost = 0.7; double * data, * buffer = nil; if ( sizeof(double) % 2) { warn("%s:'double' is even-sized on this platform", METHOD); return nil; } if ( !img || !kind_of(( Handle) img, CImage)) croak("%s: not an image passed", METHOD); if ( pexist( spatial)) spatial = pget_i( spatial); if ( pexist( homomorph)) homomorph = pget_i( homomorph); if ( pexist( power)) Power = pget_f( power); if ( pexist( cutoff)) CutOff = pget_f( cutoff); if ( pexist( boost)) Boost = pget_f( boost); if ( pexist( low)) LowPass = pget_i( low); if ( homomorph && !spatial) croak("%s:Cannot perform the homomorph equalization in the spatial domain", METHOD); if ( LowPass && ( CutOff < 0.0000001)) croak("%s:cutoff is too small for low pass", METHOD); if ( !spatial && (( img-> type & imCategory) != imComplexNumber)) croak("%s: not an im::DComplex image passed", METHOD); ret = ( PImage) img-> self-> dup(( Handle) img); if ( !ret) fail( "%s: Return image allocation failed"); ++SvREFCNT( SvRV( ret-> mate)); if ( spatial) { ret-> self-> set_type(( Handle) ret, imDComplex); if ( ret-> type != imDComplex) { warn("%s: Cannot convert image to im::DComplex", METHOD); failed = 1; goto EXIT; } } data = ( double *) ret-> data; lw = ret-> w * 2; /* Take log of input image */ if ( homomorph) { long i, k = ret-> w * ret-> h * 2; MinVal = *data; for ( i = 0; i < k; i += 2) if ( MinVal > data[i]) MinVal = data[i]; for ( i = 0; i < k; i += 2) data[i] = ( double) log(( double) ( 1.0 + data[i] - MinVal)); } /* fft */ if ( spatial) { if ( !pow2( img-> w)) croak("%s: image width is not a power of 2", METHOD); if ( !pow2( img-> h)) croak("%s: image height is not a power of 2", METHOD); buffer = malloc((sizeof(double) * ret-> w * 2)); if ( !buffer) { warn("%s: Error allocating %d bytes", METHOD, (int)(sizeof(double) * img-> w * 2)); failed = 1; goto EXIT; } fft_2d( data, ret-> w, ret-> h, FFT_DIRECT, buffer); } butterworth( data, ret-> w, ret-> h, homomorph, LowPass, Power, CutOff, Boost); /* inverse fft */ if ( spatial) { fft_2d( data, ret-> w, ret-> h, FFT_INVERSE, buffer); free( buffer); buffer = nil; } /* Take exp of input image */ if ( homomorph) { long i, k = ret-> w * ret-> h * 2; for ( i = 0; i < k; i += 2) data[i] = ( double) ( exp( data[i]) - 1.0 + MinVal); } /* converting type back */ if ( spatial && ret-> self-> get_preserveType(( Handle) ret)) ret-> self-> set_type(( Handle) ret, img-> type); EXIT: free( buffer); if ( ret) --SvREFCNT( SvRV( ret-> mate)); return failed ? nil : ret; #undef METHOD }
int main(int argc, char **argv) { int scheme_flg, nfld; double *eta, *phi; double *velwM, *velwM2, *velw2M, *velw2M2; double t, dt, t_old; char init_data_buff[INIT_DATA_BUFSIZE], init_pars_buff[INIT_DATA_BUFSIZE], subid_buff[2], dtflag[20], nfld_buff[5]; fftw_complex *heta, *hphi; fftw_complex *hvelwM, *hvelwM2, *hvelw2M, *hvelw2M2; strncpy(init_pars_buff,"\0",INIT_DATA_BUFSIZE); //strncpy(init_pars_buff, Sim_root, strlen(Sim_root)); strncpy(init_pars_buff,"initpars.h5", strlen("initpars.h5")); /* Read input parameters file */ get_params(init_pars_buff); printf("Final time = %f\n",T); printf("dtsave = %f\n",dtsave); snprintf(subid_buff, 2,"%d",runsubid); strncpy(init_data_buff,"\0",INIT_DATA_BUFSIZE); strcat(init_data_buff,"initdata."); strcat(init_data_buff,subid_buff); strcat(init_data_buff,".h5"); nfld = 0; strncpy(savefile_buff,"\0",SAVE_FILE_BUFSIZE); strcat(savefile_buff,"data"); snprintf(nfld_buff, 5,"%d",nfld); strcat(savefile_buff,nfld_buff); strcat(savefile_buff,"."); strcat(savefile_buff,subid_buff); strcat(savefile_buff,".h5"); strncpy(savefile2_buff,"\0",SAVE_FILE_BUFSIZE); strcat(savefile2_buff,"data_extra"); snprintf(nfld_buff, 5,"%d",nfld); strcat(savefile2_buff,nfld_buff); strcat(savefile2_buff,"."); strcat(savefile2_buff,subid_buff); strcat(savefile2_buff,".h5"); Nxl = 4*Nx/2; Nyl = 4*Ny/2; g=1; NLevs=M; /* Define a total size to share time-stepping routines with 1d case */ /* N/2+1 = Nx*(Ny/2 + 1) */ N = 2*Nx*(Ny/2+1) - 2; eta = (double*) fftw_malloc(sizeof(double)*2*Nx*Ny); heta = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*2*Nx*(Ny/2+1)); phi = &eta[Nx*Ny]; hphi = &heta[Nx*(Ny/2+1)]; //hdummy = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*2*Nx*(Ny/2+1)); //k = malloc (sizeof(double)*Nx*(Ny/2+1)); f = malloc(sizeof(double)*Nx*Ny); ff = malloc(sizeof(double)*Nxl*Nyl); hf = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Nx*(Ny/2+1)); hff = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Nxl*(Nyl/2+1)); velwM = malloc(sizeof(double)*Nx*Ny); velwM2 = malloc(sizeof(double)*Nx*Ny); velw2M = malloc(sizeof(double)*Nx*Ny); velw2M2 = malloc(sizeof(double)*Nx*Ny); hvelwM = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Nx*(Ny/2+1)); hvelwM2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Nx*(Ny/2+1)); hvelw2M = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Nx*(Ny/2+1)); hvelw2M2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Nx*(Ny/2+1)); /* Setup fft routines */ //stat = fftw_init_threads(); //fftw_plan_with_nthreads(4); fftp = fftw_plan_dft_r2c_2d(Nx, Ny, f, hf, FFTW_ESTIMATE); ifftp = fftw_plan_dft_c2r_2d(Nx, Ny, hf, f, FFTW_ESTIMATE); fftp_large = fftw_plan_dft_r2c_2d(Nxl, Nyl, ff, hff, FFTW_ESTIMATE); ifftp_large = fftw_plan_dft_c2r_2d(Nxl, Nyl, hff, ff, FFTW_ESTIMATE); /* Read initial data */ printf("Reading initial condition from %s\n",init_data_buff); get_ic_2d(init_data_buff, eta, phi); /* Setup temporal scheme. */ scheme_flg=2; Setup_TimeScheme(scheme_flg); rhs_hos_setup(); t = 0; fft_2d(eta, heta, fftp); fft_2d(phi, hphi, fftp); ifft_2d(heta, eta, ifftp); ifft_2d(hphi, phi, ifftp); /* Dealiasing */ int mx, my, index; mx = floor( 0.5*Nx/(1 + 0.5*NLevs) ); my = floor( 0.5*Ny/(1 + 0.5*NLevs) ); for (int i=0; i<Nx; i++) { for (int j=0; j<Ny/2+1; j++) { if ( (i>=mx && i<(Nx-mx+1)) || (j>=my) ) { index = (Ny/2+1)*i + j; heta[index] = 0.0; hphi[index] = 0.0; } } } Zvel(heta, hvelwM, hvelwM2, hvelw2M, hvelw2M2, t); ifft_2d(hvelwM, velwM, ifftp); ifft_2d(hvelwM2, velwM2, ifftp); /* Save initial snapshot */ savefileid = create_file_2d(savefile_buff); write_header_2d(savefileid, t); write_field_2d(savefileid, eta, phi); status = close_file_2d(savefileid); savefileid2 = create_file_2d(savefile2_buff); write_header_2d(savefileid2, t); write_extra_2d(savefileid2, velwM, velwM2); status = close_file_2d(savefileid2); printf("Datafile written at t=%f\n",t); /* Time loop */ while (t<T-0.00000001) { t_old = t; dt = 0.025; sol_update_RK(heta,&t,dt,dtflag); //t = t + dt; if ( floor( (t*1.000000001)/dtsave) > floor((t_old*1.000000001)/dtsave) ) { nfld = nfld + 1; ifft_2d(heta, eta, ifftp); ifft_2d(hphi, phi, ifftp); /* Print field in output file */ strncpy(savefile_buff,"\0",SAVE_FILE_BUFSIZE); strcat(savefile_buff,"data"); snprintf(nfld_buff, 5,"%d",nfld); strcat(savefile_buff,nfld_buff); strcat(savefile_buff,"."); strcat(savefile_buff,subid_buff); strcat(savefile_buff,".h5"); strncpy(savefile2_buff,"\0",SAVE_FILE_BUFSIZE); strcat(savefile2_buff,"data_extra"); snprintf(nfld_buff, 5,"%d",nfld); strcat(savefile2_buff,nfld_buff); strcat(savefile2_buff,"."); strcat(savefile2_buff,subid_buff); strcat(savefile2_buff,".h5"); savefileid = create_file_2d(savefile_buff); write_header_2d(savefileid, t); write_field_2d(savefileid, eta, phi); status = close_file_2d(savefileid); savefileid2 = create_file_2d(savefile2_buff); write_header_2d(savefileid2, t); write_extra_2d(savefileid2, velwM, velwM2); status = close_file_2d(savefileid2); printf("Datafile written at t=%f\n",t); } } // // ifft_1d(heta, eta, ifftp); // ifft_1d(hphi, phi, ifftp); // // // fftw_destroy_plan(fftp); fftw_destroy_plan(ifftp); free(eta); fftw_free(heta); fftw_destroy_plan(fftp_large); fftw_destroy_plan(ifftp_large); return 0; }