Я вручную инициализирую состояние в частотной области 2d, устанавливая реальные компоненты определенных режимов в наборе данных 16x16. Затем я выполняю 2d IDFT для получения реальных данных домена. Все работает так, как ожидалось.

Затем я выполняю ДПФ для данных реального домена, чтобы вернуть (какими должны быть) режимы частоты, идентичные тем, которые я инициализировал вручную. Однако они возвращаются с половинными амплитудами и "зеркальными" вертикальными частотами. Проиллюстрировать:

Режимы ввода:
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

Мой вопрос: почему режимы на выходе ДПФ не такие же, как на исходном входе в 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(...) можно увидеть в вопросе выше.

1
Naemesis 17 Сен 2020 в 14:23

1 ответ

Лучший ответ

Вам нужно прочитать о дискретном преобразовании Фурье.

Для сигнала с действительным знаком во временной области ДПФ имеет сопряженную симметрию:

F (k) = конъюнктура (F (N-k)),

Где N - количество образцов. Путем обратного преобразования несимметричного сигнала в частотной области вы получаете комплексный сигнал во временной области, но поскольку вы используете преобразование комплексного значения в действительное, фактически вычисляется только действительная часть этого результата. Вы выбрасываете здесь половину данных. Затем прямое преобразование возвращает ДПФ этого преобразованного сигнала. Поскольку ваш сигнал во временной области теперь имеет действительное значение, ваш результат в частотной области имеет сопряженную симметрию.

2
Cris Luengo 21 Сен 2020 в 13:51