为什么在使用 FFTW 将 (2d) IDFT 转换为 DFT 时,我的数据在频域 "mirrored" 中?
Why is my data in the frequency domain "mirrored" when performing (2d) IDFT into DFT using FFTW?
我通过在 16x16 数据集中设置某些模式的实部来手动初始化 2d 频域中的状态。然后我执行 2d IDFT 以获取真实域数据。这一切都按预期工作。
然后我对实际域数据执行 DFT 以返回(应该是)与我手动初始化的频率模式相同的频率模式。然而,它们返回时振幅减半,垂直频率“镜像”。举例说明:
输入模式:
k[1, 0]: 32 + 0i
k[2, 0]: 16 + 0i
k[3, 0]: 8 + 0i
k[4, 0]: 4 + 0i
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
我的问题是,为什么 DFT 的输出模式与 IDFT 的初始输入模式不同?
对于一些额外的上下文,我遇到的问题是我正在使用这些数据来“求解”热方程,并且更高频率的信号很快就会按比例缩小。所以 k[12, 0] 到 k[15, 0] 模式在几个时间步之后实际上并没有太大贡献。
重现问题的代码:
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);
两个printComplex(...)
调用的输出可以在上面的问题中看到。
您需要阅读离散傅立叶变换。
对于real-valued时域信号,DFT具有共轭对称性:
F(k) = conj(F(N-k)),
样本数为N。通过对 non-symmetric frequency-domain 信号进行逆变换,您可以获得 complex-valued time-domain 信号,但是因为您使用了 complex-to-real 变换,所以只有该结果的实部实际上是计算出来的。您在这里丢弃了一半的数据。然后正向变换 returns 这个变换信号的 DFT。因为您的 time-domain 信号现在是 real-valued,您的 frequency-domain 结果具有共轭对称性。
我通过在 16x16 数据集中设置某些模式的实部来手动初始化 2d 频域中的状态。然后我执行 2d IDFT 以获取真实域数据。这一切都按预期工作。
然后我对实际域数据执行 DFT 以返回(应该是)与我手动初始化的频率模式相同的频率模式。然而,它们返回时振幅减半,垂直频率“镜像”。举例说明:
输入模式:
k[1, 0]: 32 + 0i
k[2, 0]: 16 + 0i
k[3, 0]: 8 + 0i
k[4, 0]: 4 + 0i
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
我的问题是,为什么 DFT 的输出模式与 IDFT 的初始输入模式不同?
对于一些额外的上下文,我遇到的问题是我正在使用这些数据来“求解”热方程,并且更高频率的信号很快就会按比例缩小。所以 k[12, 0] 到 k[15, 0] 模式在几个时间步之后实际上并没有太大贡献。
重现问题的代码:
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);
两个printComplex(...)
调用的输出可以在上面的问题中看到。
您需要阅读离散傅立叶变换。
对于real-valued时域信号,DFT具有共轭对称性:
F(k) = conj(F(N-k)),
样本数为N。通过对 non-symmetric frequency-domain 信号进行逆变换,您可以获得 complex-valued time-domain 信号,但是因为您使用了 complex-to-real 变换,所以只有该结果的实部实际上是计算出来的。您在这里丢弃了一半的数据。然后正向变换 returns 这个变换信号的 DFT。因为您的 time-domain 信号现在是 real-valued,您的 frequency-domain 结果具有共轭对称性。