从FFTW获得的实际数据的第1,第2,第3和第4偏导数不正确

时间:2017-07-06 10:32:46

标签: c#

我通过使用fftw,傅里叶变换它,乘以适当的并采用逆傅立叶变换计算了sin的第一,第二和第三导数(2.0 * pi * j / lambda)(j从0变化到255)。使用的计划不合适,具有虚拟输入和输出阵列。结果数组的实部是分析结果的一半。我通过选择适当的kx / ky值来处理衍生物时处理混叠。只需取fftw和逆fftw就可以正确地返回原始数组。

fftw返回的值是所有衍生物的分析值的一半。

如果我在x方向上做同样的事情(i而不是j),获得的值仅对于x的一阶导数是正确的,y导数是非零的(因为变化只是零在x)和laplacian和biharmonic(第四导数wrt x和y)是错误的。

在这两种情况下,导数的虚部都是非零和大的。

我使用r2c和c2r尝试了不同的计划,但这也给出了错误的值。

任何建议都会有所帮助!

    void psiderivcalc(double *psi, double *dx, double *dy, double *del2, double *dxdel2, double *dydel2, double *del4)

{     int i,j,ir,ir1,k;

fftw_complex *fdx, *fdy, *fdxdel2, *fdydel2, *fdel2, *fdel4, *out, *bt, *in;
fftw_plan p, q; 

out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) *N);
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) *N);
bt = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) *N);
fdx = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
fdy = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
fdxdel2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) *N);
fdydel2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) *N);
fdel2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) *N);
fdel4 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);

p = fftw_plan_dft_2d(lx, ly, in, bt, FFTW_FORWARD,FFTW_MEASURE);
q = fftw_plan_dft_2d(lx, ly, bt, out, FFTW_BACKWARD,FFTW_MEASURE);

for(i = 0; i < lx; i++)
{ 
    for(j = 0; j < ly; j++)
    { 
        ir = j*lx + i; 
        in[ir] = psi[ir] + 0.0*I; 
    }
} 

fftw_execute(p); 

double kx, ky, pref; 
int y1, x1, y2, x2; 
kx = 2.0*pi/lx; 
ky = 2.0*pi/ly;
for(i=0;i<lx;i++)
{
    for(j = 0; j < ly; j++)
    {
        ir = j*lx + i;
        if(i<lx/2) 
        {
            x1 = i; 
            x2 = i;
        } 
        else if(i==lx/2.0)
        {
            x1 = 0; 
            x2 = i;
        } 
        else
        { 
            x1 = i - lx; 
            x2 = x1;
        }  
        if(j<ly/2) 
        {
            y1 = i; 
            y2 = i;
        } 
        else if(j==ly/2) 
        {
            y1 = 0; 
            y2 = j;
        } 
        else
        { 
            y1 = j - ly; 
            y2 = y1;
        }
        pref = -1.0*(pow((kx*x2),2.0) + pow((ky*y2),2.0));
        fdx[ir] = -1.0*kx*x1*I*bt[ir]; 
        fdy[ir] = -1.0*ky*y1*I*bt[ir]; 
        fdel2[ir] = pref*bt[ir]; 
        fdxdel2[ir] = -1.0*kx*I*x1*pref*bt[ir]; 
        fdydel2[ir] = -1.0*ky*I*y1*pref*bt[ir]; 
        fdel4[ir] = pref*pref*bt[ir];
    }
}

for(i = 0;i < lx; i++)
{ 
    for(j = 0;j < ly; j++)
    { 
        ir = j*lx + i; 
        bt[ir] = fdx[ir]; 
    }
}

fftw_execute(q); 

for(i = 0;i < lx; i++)
{ 
    for(j = 0;j < ly; j++)
    { 
        ir = j*lx + i; 
        dx[ir] = creal(out[ir]) / (double)N; 
    }
}

我通过在执行计划q之前每次更改bt [ir]并在执行之后输出[ir],找到与dx [ir](一阶导数wrt x)相同的其他导数。 del2是laplacian,dxdel2是laplacian wrt x的衍生物,del4是biharmonic。

psi [ir]在将其传递给函数之前已正确初始化为j中的正弦函数。

    for(i = 0; i < lx; i++)
    { 
        for(j = 0; j < ly; j++)
        {
            ir = j*lx + i; 
            psi[ir] = sin(2.0*pi*j/lambda); 
        }
    }  

这是del2(fftw),del2a(分析),dx,dxa和ir(索引)的输出示例。 lambda = 8,lx = 16,ly = 16,N = lx * ly,因此sin函数在该域中是周期性的。

    0.308425    -0.616850   0.000000    0.000000    175
    -0.218090   -0.436179   0.000000    0.000000    191
    -0.000000   -0.000000   0.000000    0.000000    207
    0.218090    0.436179    0.000000    0.000000    223
    0.308425    0.616850    0.000000    0.000000    239
    0.218090    0.436179    0.000000    0.000000    255

1 个答案:

答案 0 :(得分:0)

麻烦来自以下几行:

    if(j<ly/2) 
    {
        y1 = i; // should be j !!!
        y2 = i; // should be j !!!
    } 

另外,请注意衍生品的标志:

    fdx[ir] = -1.0*kx*x1*I*bt[ir]; // should be a + !
    fdy[ir] = -1.0*ky*y1*I*bt[ir]; // should be a + !