C++ 混淆测试fftw3-泊松方程2d测试
我无法解释/理解以下现象: 为了测试fftw3,我使用2d泊松测试用例: 具有周期边界条件的拉普拉斯(f(x,y))=-g(x,y) 对方程应用傅里叶变换后,我们得到:F(kx,ky)=G(kx,ky)/(kx²+ky²)(1) 如果我在[0,2\pi]中取g(x,y)=sin(x)+sin(y),(x,y),我立即得到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),曲线甚至没有相同形式的解 (注意,我必须改变方程;在这种情况下,我除以2拉普拉斯函数:(1)变成F(kx,ky)=2*G(kx,ky)/(kx²+ky²) 代码如下:C++ 混淆测试fftw3-泊松方程2d测试,c++,fftw,C++,Fftw,我无法解释/理解以下现象: 为了测试fftw3,我使用2d泊松测试用例: 具有周期边界条件的拉普拉斯(f(x,y))=-g(x,y) 对方程应用傅里叶变换后,我们得到:F(kx,ky)=G(kx,ky)/(kx²+ky²)(1) 如果我在[0,2\pi]中取g(x,y)=sin(x)+sin(y),(x,y),我立即得到f(x,y)=g(x,y) 这就是我试图通过fft得到的结果: 我用前向傅里叶变换从G计算G 由此,我可以用(1)计算f的傅里叶变换 最后,我用后向傅里叶变换计算f(不忘用1/(
/*
* 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;
}
/*
*fftw试验——双精度
*/
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
int N=128;
int i,j;
双pi=3.14159265359;
双*X,*Y;
X=(双*)malloc(N*sizeof(双));
Y=(双*)malloc(N*sizeof(双));
fftw_复合体*out1、*in2、*out2、*in1;
fftw_计划p1、p2;
双L=2.*π;
双dx=L/(N-1);
in1=(fftw_复合体*)fftw_malloc(sizeof(fftw_复合体)*(N*N));
out2=(fftw_复合体*)fftw_malloc(sizeof(fftw_复合体)*(N*N));
out1=(fftw_复合体*)fftw_malloc(sizeof(fftw_复合体)*(N*N));
in2=(fftw_复合体*)fftw_-malloc(sizeof(fftw_复合体)*(N*N));
p1=fftw_平面图_dft_2d(N,N,in1,out1,fftw_正向,fftw_度量);
p2=fftw_平面图_dft_2d(N,N,in2,out2,fftw_向后,fftw_度量);
对于(i=0;i cout以下是一些需要修改的要点:
- 您需要考虑所有小频率,包括负频率!索引
i
对应于频率2PI/N
,但也对应于频率2PI(i-N)/N
。在傅立叶空间中,数组的结尾和开头一样重要!在我们的例子中,我们保持最小的频率:数组的前半部分是2PI i/N
,下半部分是2PI(i-N)/N
- 当然,正如保罗所说,
N-1
应该是N
在double dx=L/(N-1);
=>double dx=L/(N);
N-1
不对应于连续的周期信号。很难将其用作测试用例
- 缩放…我是凭经验做的
对于这两种情况,我得到的结果更接近预期结果。以下是代码:
/*
* 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 );
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++){
double fact=0;
in2[i*N + j][0]=0;
in2[i*N + j][1]=0;
if(2*i<N){
fact=((double)i*i);
}else{
fact=((double)(N-i)*(N-i));
}
if(2*j<N){
fact+=((double)j*j);
}else{
fact+=((double)(N-j)*(N-j));
}
if(fact!=0){
in2[i*N + j][0] = out1[i*N + j][0]/fact;
in2[i*N + j][1] = out1[i*N + j][1]/fact;
}else{
in2[i*N + j][0] = 0;
in2[i*N + j][1] = 0;
}
//in2[i*N + j][0] = out1[i*N + j][0];
//in2[i*N + j][1] = out1[i*N + j][1];
// in2[i*N + j][0] = out1[i*N + j][0]*(1.0/(i*i+1e-16)+1.0/(j*j+1e-16)+1.0/((N-i)*(N-i)+1e-16)+1.0/((N-j)*(N-j)+1e-16))*N*N;
// in2[i*N + j][1] = out1[i*N + j][1]*(1.0/(i*i+1e-16)+1.0/(j*j+1e-16)+1.0/((N-i)*(N-i)+1e-16)+1.0/((N-j)*(N-j)+1e-16))*N*N;
//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<< 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;
}
/*
*fftw试验——双精度
*/
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
int N=128;
int i,j;
双pi=3.14159265359;
双*X,*Y;
X=(双*)malloc(N*sizeof(双));
Y=(双*)malloc(N*sizeof(双));
fftw_复合体*out1、*in2、*out2、*in1;
fftw_计划p1、p2;
双L=2.*π;
双dx=L/(N);
in1=(fftw_复合体*)fftw_malloc(sizeof(fftw_复合体)*(N*N));
out2=(fftw_复合体*)fftw_malloc(sizeof(fftw_复合体)*(N*N));
out1=(fftw_复合体*)fftw_malloc(sizeof(fftw_复合体)*(N*N));
in2=(fftw_复合体*)fftw_-malloc(sizeof(fftw_复合体)*(N*N));
p1=fftw_平面图_dft_2d(N,N,in1,out1,fftw_正向,fftw_度量);
p2=fftw_平面图_dft_2d(N,N,in2,out2,fftw_向后,fftw_度量);
对于(i=0;i 如果(2*i认为你的N-1
术语实际上应该是N
?如果我是“for(i=0;i