问题
I am manually initializing a state in the 2d frequency domain by setting the real components of certain modes in a 16x16 data set. I then perform a 2d IDFT to acquire the real domain data. This all works as expected.
I then perform a DFT on the real domain data to get back (what should be) identical frequency modes to those that I manually initialized. However, they come back with their amplitudes halfed, and their vertical frequencies "mirrored". To illustrate:
Input modes:
k[1, 0]: 32 + 0i
k[2, 0]: 16 + 0i
k[3, 0]: 8 + 0i
k[4, 0]: 4 + 0i
Output modes after IDFT -> DFT:
k[ 1, 0]: 16 + 0i
k[ 2, 0]: 8 + 0i
k[ 3, 0]: 4 + 0i
k[ 4, 0]: 2 + 0i
k[12, 0]: 2 + 0i
k[13, 0]: 4 + 0i
k[14, 0]: 8 + 0i
k[15, 0]: 16 + 0i
My question is, why are the modes in the output of the DFT not the same as the initial input to the IDFT?
For some extra context, the problem I am having with this is that I am using this data to "solve" the heat equation, and higher frequency signals get scaled down very quickly. So the k[12, 0] to k[15, 0] modes don't actually contribute much after a few time steps.
Code to reproduce problem:
int N = 16; // Dimensions of the data
int logical_width = (N / 2) + 1; // Logical width of the frequency domain
double* real = new double[N * N];
fftw_complex* complex = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N * logical_width);
fftw_plan plan = fftw_plan_dft_r2c_2d(N, N, real, complex, FFTW_ESTIMATE);
fftw_plan iplan = fftw_plan_dft_c2r_2d(N, N, complex, real, FFTW_ESTIMATE);
// Initialize all real data to 0
for (int i = 0; i < N * N; i++) {
real[i] = 0.0;
}
// Initialize all complex data to 0
for (int i = 0; i < N * logical_width; i++) {
complex[i][REAL] = 0.0;
complex[i][IMAG] = 0.0;
}
// Set first 4 vertical modes
complex[1 * logical_width][REAL] = 32;
complex[2 * logical_width][REAL] = 16;
complex[3 * logical_width][REAL] = 8;
complex[4 * logical_width][REAL] = 4;
// Print before IDFT -> DFT
printComplex(complex, N);
// IDFT
fftw_execute(iplan);
// DFT back
fftw_execute(plan);
// Print after IDFT -> DFT
printComplex(complex, N, true); // Pass true to divide amplitudes by N*N
// Clean up
fftw_destroy_plan(plan);
fftw_destroy_plan(iplan);
delete[] real;
fftw_free(complex);
The output of the two printComplex(...)
calls can be seen in the question above.
回答1:
You need to read up on the Discrete Fourier Transform.
For a real-valued time domain signal, the DFT has a conjugate symmetry:
F(k) = conj(F(N-k)),
with N the number of samples. By inverse transforming a non-symmetric frequency-domain signal, you obtain a complex-valued time-domain signal, but because you use a complex-to-real transform, only the real part of this result is actually computed. You’re throwing away half the data here. The forward transform then returns the DFT of this transformed signal. Because your time-domain signal is now real-valued, your frequency-domain result has conjugate symmetry.
来源:https://stackoverflow.com/questions/63936984/why-is-my-data-in-the-frequency-domain-mirrored-when-performing-2d-idft-into