我无法解释/理解以下现象:
为了测试 fftw3,我使用 2d 泊松测试用例:
laplacian(f(x,y)) = - g(x,y) 具有周期性边界条件。
对方程进行傅里叶变换后,我们得到: F(kx,ky) = G(kx,ky) /(kx² + ky²) (1)
如果我取 g(x,y) = sin (x) + sin(y) , (x,y) \in [0,2 \pi] 我立即有 f(x,y) = g(x,y)
这就是我试图通过 fft 获得的:
我通过前向傅立叶变换从 g 计算 G
由此我可以用(1)计算 f 的傅立叶变换。
最后,我使用后向傅立叶变换计算 f(不要忘记按 1/(nx*ny) 进行归一化)。
实际上,结果很糟糕?
(例如,N = 256 时的振幅是 N = 512 时获得的振幅的两倍)
更糟糕的是,如果我尝试 g(x,y) = sin(x)*sin(y) ,曲线甚至没有相同形式的解。
(请注意,我必须更改方程;在这种情况下,我将拉普拉斯算子除以二:(1) 变为 F(kx,ky) = 2*G(kx,ky)/(kx²+ky²)
这是代码:
/*
* fftw test -- double precision
*/
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fftw3.h>
using namespace std;
int main()
{
int N = 128;
int i, j ;
double pi = 3.14159265359;
double *X, *Y ;
X = (double*) malloc(N*sizeof(double));
Y = (double*) malloc(N*sizeof(double));
fftw_complex *out1, *in2, *out2, *in1;
fftw_plan p1, p2;
double L = 2.*pi;
double dx = L/(N - 1);
in1 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*(N*N) );
out2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*(N*N) );
out1 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*(N*N) );
in2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*(N*N) );
p1 = fftw_plan_dft_2d(N, N, in1, out1, FFTW_FORWARD,FFTW_MEASURE );
p2 = fftw_plan_dft_2d(N, N, in2, out2, FFTW_BACKWARD,FFTW_MEASURE);
for(i = 0; i < N; i++){
X[i] = -pi + i*dx ;
for(j = 0; j < N; j++){
Y[j] = -pi + j*dx ;
in1[i*N + j][0] = sin(X[i]) + sin(Y[j]) ; // row major ordering
//in1[i*N + j][0] = sin(X[i]) * sin(Y[j]) ; // 2nd test case
in1[i*N + j][1] = 0 ;
}
}
fftw_execute(p1); // FFT forward
for ( i = 0; i < N; i++){ // f = g / ( kx² + ky² )
for( j = 0; j < N; j++){
in2[i*N + j][0] = out1[i*N + j][0]/ (i*i+j*j+1e-16);
in2[i*N + j][1] = out1[i*N + j][1]/ (i*i+j*j+1e-16);
//in2[i*N + j][0] = 2*out1[i*N + j][0]/ (i*i+j*j+1e-16); // 2nd test case
//in2[i*N + j][1] = 2*out1[i*N + j][1]/ (i*i+j*j+1e-16);
}
}
fftw_execute(p2); //FFT backward
// checking the results computed
double erl1 = 0.;
for ( i = 0; i < N; i++) {
for( j = 0; j < N; j++){
erl1 += fabs( in1[i*N + j][0] - out2[i*N + j][0]/N/N )*dx*dx;
cout<< i <<" "<< j<<" "<< sin(X[i])+sin(Y[j])<<" "<< out2[i*N+j][0]/N/N <<" "<< endl; // > output
}
}
cout<< erl1 << endl ; // L1 error
fftw_destroy_plan(p1);
fftw_destroy_plan(p2);
fftw_free(out1);
fftw_free(out2);
fftw_free(in1);
fftw_free(in2);
return 0;
}
我在我的代码中找不到任何(更多)错误(我上周安装了 fftw3 库),我也没有看到数学问题,但我不认为这是 fft 的错。因此我的困境。我已经没有想法了,也没有谷歌了。
任何帮助解决这个难题的帮助将不胜感激。
note :
编译:g++ test.cpp -lfftw3 -lm
执行:./a.out > 输出
我使用 gnuplot 来绘制曲线:
(在 gnuplot 中) splot "output" u 1:2:4 (用于计算的解决方案)