我有一个关于使用FFTW来解决泊松方程的问题。我试图解决的等式如下:
问题在于我得到的解决方案不再是径向对称的,特别是从输出图中可以看到沿轴的对称性丢失:
以下是代码:
double dx = 25. / ( N*1. ), dy = 25. / ( N*1. ), dkx = 2*pi/(N*dx), dky = 2*pi/(N*dy);//define steps in real and Fourier space
double Lx = N*dx, Ly = N*dy, Lkx = N*dkx, Lky = N*dky;//define box sides in real and Fourier space
int i, j, Nh = N/2 + 1;
double *inr, *in2r, *in2d;
fftw_complex *outr;
fftw_complex *outd;
fftw_plan rplan_forward;
fftw_plan dplan_backward;
fftw_plan rplan_backward;
for ( i = 0; i < N; i++ )
{
x[i] = dx*i - Lx/2.;
kx[i] = dkx*i - Lkx/2.;
y[i] = dy*i - Ly/2.;
ky[i] = dky*i - Lky/2.;
}
outd = (fftw_complex*)fftw_malloc ( sizeof ( fftw_complex ) * N * Nh );
inr = ( double * ) malloc ( sizeof ( double ) * N * N );
for ( i = 0; i < N; i++ ) //Initialize ine to rho
{
for ( j = 0; j < N; j++ )
{
inr[i*N+j] = rho[i*N+j] * pow( -1, i + j );
}
}
outr = (fftw_complex*)fftw_malloc ( sizeof ( fftw_complex ) * N * Nh );
rplan_forward = fftw_plan_dft_r2c_2d ( N, N, inr, outr, FFTW_ESTIMATE );
fftw_execute ( rplan_forward ); //fft rho
for ( i = 0; i < N; i++ ) //Evaluate d in Fourier Space according to Poisson eq
{
for ( j = 0; j < Nh; j++ )
{
outd[i*Nh+j][0] = g * outr[i*Nh+j][0] / ( kx[i]*kx[i] + ky[j]*ky[j] );
outd[i*Nh+j][1] = g * outr[i*Nh+j][1] / ( kx[i]*kx[i] + ky[j]*ky[j] );
}
}
outd[Nh*N/2+N/2][0] = 0.; //Avoid singularity at k = 0
outd[Nh*N/2+N/2][1] = 0.;
in2d = ( double * ) malloc ( sizeof ( double ) * N * N );
dplan_backward = fftw_plan_dft_c2r_2d ( N, N, outd, in2d, FFTW_ESTIMATE );
fftw_execute ( dplan_backward ); //Antitrasform d
in2r = ( double * ) malloc ( sizeof ( double ) * N * N );
rplan_backward = fftw_plan_dft_c2r_2d ( N, N, outr, in2r, FFTW_ESTIMATE );
fftw_execute ( rplan_backward ); //Antitrasform rho
for( i = 0; i < N; i++ )
{
for ( j = 0; j < N; j++ )
{
printf( " %le %le %le \n", x[i], y[j], in2d[i*N+j] * pow( -1, i + j ) / ( N*N*1. ) - in2d[0] / ( N*N*1. ) ); //print d in such a way that it is zero at the boundaries
}
}
fftw_destroy_plan ( rplan_forward );
fftw_destroy_plan ( dplan_backward );
fftw_destroy_plan ( rplan_backward );
fftw_free ( outd );
fftw_free ( inr );
fftw_free ( outr );
fftw_free ( in2d );
fftw_free ( in2r);
fftw_cleanup();
请注意,我希望有一个在边界处为零的解决方案。
你能告诉我问题在哪里吗?我怀疑它只是一个数字问题,但我不确定。这是边界的缩放(特别是在-12.5&lt; y&lt; -11.5的区域)。
答案 0 :(得分:2)
径向对称性的损失与域的形状有关:它是一个正方形,而不是一个圆。此外,由于应用了dicrete傅里叶变换,所研究的问题是使用周期性边界条件的方形域上的泊松方程。因此,边界附近的温度可能不会降低到零。
这就是为什么不使用零频率(即源项的平均值)的原因。如果不是这样,则无法解决常温热方程。实际上,由于周期性的边界条件,一侧出来的热通量正在相反的一侧进入。当域完全绝缘时,温度会升高,永远不会达到常规解决方案。
要应用零Dirichlet边界解,必须使用正弦变换之一来代替傅立叶变换。 例如,见:
http://www.ds.ewi.tudelft.nl/vakken/in4049TU/sheets/lecture10.pdf
这是一个答案(我的!),其中包含一段代码,通过FFTW的正弦变换求解二维泊松方程,零Dirichlet边界条件。 这是c ++,但将其翻译为c很简单。
fftw3 for poisson with dirichlet boundary condition for all side of computational domain
要恢复接近径向对称的东西,源的支持必须远离域的边缘。如果您知道域,边界条件和源项与径向对称性相关,那么最好的解决方案可能是切换到一维径向方程。
答案 1 :(得分:1)
我认为有一个问题在这里:
outd[Nh*N/2+N/2][0] = 0.; //Avoid singularity at k = 0
k=0
位于(0,0)
,而不是(N/2,N/2)
。这就是DFT的定义方式。 k
从0到N-1
。 您正在空间域中引入相移。我不知道这会对你以后的计算产生什么影响。你试图通过将输入乘以pow(-1,i)
来使频谱居中。对于偶数N
,此技巧仅 。
如果能更好地正确计算kx
和ky
:
for ( i = 0; i < N; i++ ) {
kx[i] = ( i > N/2 ? i-N : i ) * 2*pi/N;
}
这适用于任何N
。另请注意,我上面对k
的定义对应于径向频率(ω),而不是DFT的整数 k 。它也与你的不同,我认为(如果是这样,你的不正确!)。
另一个问题是DFT不是FT。 DFT是在有界空间域上计算的,该空间域被假定为周期性的。这个域名是一个正方形。在方形网格上很难做出旋转对称的东西。与轴相比,奈奎斯特频率(最大可能频率)沿对角线高sqrt(2)
倍。并且沿着对角线,模式的周期也是sqrt(2)
倍。因此,沿着轴获得更多的锯齿,并且您的图案更可能沿着轴重叠。
如果上述情况导致您看到的效果,请尝试增加空间域的大小和/或采样密度。