我正在尝试使用 FFTW 库在 3D 中求解所有诺伊曼边界条件下的泊松方程。方程如下 d^STR/dx^2+d^STR/dy^2+d^2STR/dz^2=-VORTG。在我看来,计算 out2 的步骤是正确的。但是,我不确定计算 STR 的步骤。你能给我一些建议吗?非常感谢。
void poisson3d(vector<vector<vector<double> > > &STR, vector<vector<vector<double> > > &VORTG)
{
double pi = 3.141592653589793;
double XMIN=-2.0;
double XMAX=2.0;
double YMIN=-2.0;
double YMAX=2.0;
double ZMIN=-2.0;
double ZMAX=2.0;
double dd=(XMAX-XMIN)*(YMAX-YMIN)*(ZMAX-ZMIN)/pi/pi/pi;
std::vector<double> in1(N*N*N,0.0);
std::vector<double> in2(N*N*N,0.0);
std::vector<double> out1(N*N*N,0.0);
std::vector<double> out2(N*N*N,0.0);
fftw_plan p, q;
int i,j,k;
p = fftw_plan_r2r_3d(N, N, N, in1.data(), out1.data(), FFTW_REDFT00 ,FFTW_REDFT00, FFTW_REDFT00, FFTW_ESTIMATE);
q = fftw_plan_r2r_3d(N, N, N, in2.data(), out2.data(), FFTW_REDFT00 ,FFTW_REDFT00, FFTW_REDFT00, FFTW_ESTIMATE);
int l=-1;double max=0;
for (i = 0;i <N;i++)
for (j = 0;j<N;j++)
for (k=0;k<N;k++){
l=l+1;
in1[l]= VORTG[i][j][k];
}
fftw_execute(p);
l=-1;
for ( i = 0; i < N; i++){ // f = g / ( kx² + ky² )
for( j = 0; j < N; j++){
for (k=0; k<N; k++){
l=l+1;
double fact=0;
in2[l]=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(2*k<N){
fact+=((double)k*k);
}else{
fact+=((double)(N-k)*(N-k));
}
if(fact!=0){
in2[l] = out1[l]/fact;
}else{
in2[l] = 0.0;
}
}
}
}
fftw_execute(q);
for ( i = 0; i < N; i++) {
for( j = 0; j < N; j++){
for (k=0;k<N;k++){
STR[i][j][k]= dd*out2[l]/((double)2.0*(N-1))/((double)2.0*(N-1))/((double)2.0*(N-1));
}
}
}
fftw_destroy_plan(p); fftw_destroy_plan(q); fftw_cleanup();
}
物理和数学上都相当复杂,但仍然有许多常用的C++调试技术仍然有效。
对于初学者来说,有许多简单的边界条件允许精确解(全零VORTG
必须产生常STR
)。您是否检查过所有中间值是否都具有此类简单输入的预期值?对于稍微复杂的边界条件,您可能无法为各种中间体提供确切的值,但您仍然可以检查符号是否正确。最后,您可能不知道某些边界条件的确切解,但您也许能够验证是否遵守了物理对称性。如果可以镜像边界条件,则结果也应镜像。是吗?