c中fftw的拉普拉斯计算

c中fftw的拉普拉斯计算,c,fft,fftw,derivative,C,Fft,Fftw,Derivative,我试图用fftw软件包计算指数函数的傅里叶变换(向前和向后),在C中实现拉普拉斯算子,但是在用拉普拉斯算子的分析版本测试结果之后,我得到了非常不同的结果。代码如下: #include <stdlib.h> #include <stddef.h> #include <stdio.h> #include <math.h> #ifndef M_PI #define M_PI 3.14159265358979323846 #endif // See

我试图用fftw软件包计算指数函数的傅里叶变换(向前和向后),在C中实现拉普拉斯算子,但是在用拉普拉斯算子的分析版本测试结果之后,我得到了非常不同的结果。代码如下:


#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif 

// See for reference:
// https://en.cppreference.com/w/c/numeric/complex
#include <complex.h>

// See for reference:
// http://www.fftw.org/fftw3_doc/
#include <fftw3.h>


/**
 * Test function
 * */
double function_xy(double x, double y)
{
    #define A -0.03
    #define B -0.01
    #define C -0.005 
    return exp(A*x*x + B*y*y + C*x*y);
}

/**
 * Analytical result
 * Use it for checking correctness!
 * */
double laplace_function_xy(double x, double y)
{
    double rdf2d_dx = function_xy(x,y)*(2.*A*x + C*y); // d/dx
    double rdf2d_dy = function_xy(x,y)*(2.*B*y + C*x); // d/dy

    double rlaplacef2d = rdf2d_dx*(2.*A*x + C*y)+function_xy(x,y)*(2.*A)  +  rdf2d_dy*(2.*B*y + C*x)+function_xy(x,y)*(2.*B); // laplace

    return rlaplacef2d;

    #undef A
    #undef B
    #undef C
}


/**
 * You can use this function to check diff between two arrays
 * */
void test_array_diff(int N, double *a, double *b)
{
    int ixyz=0;

    double d,d2;
    double maxd2 = 0.0;
    double sumd2 = 0.0;
    for(ixyz=0; ixyz<N; ixyz++)
    {
        d = a[ixyz]-b[ixyz];

        d2=d*d;
        sumd2+=d2;
        if(d2>maxd2) maxd2=d2;
    }

    printf("#    COMPARISON RESULTS:\n");
    printf("#           |max[a-b]| : %16.8g\n", sqrt(maxd2));
    printf("#         SUM[(a-b)^2] : %16.8g\n", sumd2);
    printf("# SQRT(SUM[(a-b)^2])/N : %16.8g\n", sqrt(sumd2)/N);
}


int main()
{

    // Settings
    int nx = 100; // number of points in x-direction
    int ny = 100; // number of points in y-direction

    int nthreads = 2;

    double Lx = 100.0; // width in x-direction
    double Ly = 100.0; // width in y-direction

    double x0 = -Lx/2;
    double y0 = -Ly/2;

    double dx = Lx/nx;
    double dy = Ly/ny;

    double *fxy; // function
    double *test_laplacefxy; // array with results computed according formula
    fxy = (double *) malloc(nx*ny*sizeof(double)); 
    if(fxy==NULL) { printf("Cannot allocate array fx!\n"); return 0;}

    test_laplacefxy = (double *) malloc(nx*ny*sizeof(double)); 
    if(test_laplacefxy==NULL) { printf("Cannot allocate array fx!\n"); return 0;}

    int ix, iy, ixy;

    ixy=0;
    for(ix=0; ix<nx; ix++) for(iy=0; iy<ny; iy++) 
    {
        // function
        fxy[ixy] = function_xy(x0 + dx*ix, y0 + dy*iy);

        // result for comparion
        test_laplacefxy[ixy] = laplace_function_xy(x0 + dx*ix, y0 + dy*iy);
        ixy++;
    }

    printf("Value of fxy, %2f\n", fxy[40]);


    double kx, ky;
    double *laplacefxy; // pointer to array with laplace

    double complex *fk; // its fourier transform
    fk = (double complex *) malloc(nx*ny*sizeof(double complex)); 
    if(fk==NULL) { printf("Cannot allocate array fk!\n"); return 0;}
    laplacefxy = (double *) malloc(nx*ny*sizeof(double)); 
    if(laplacefxy==NULL) { printf("Cannot allocate array fx!\n"); return 0;}

    // Create fftw plan

    fftw_plan plan_f = fftw_plan_dft_r2c_2d(nx, ny, fxy, fk, FFTW_ESTIMATE);

    // execute the plan

    fftw_execute(plan_f);

    ixy=0;
    for(ix=0; ix<nx; ix++) for(iy=0; iy<ny; iy++) 
    {
        if(ix<nx/2) kx=2.*M_PI/(dx*nx)*(ix   );
        else        kx=2.*M_PI/(dx*nx)*(ix-nx);

        if(iy<ny/2) ky=2.*M_PI/(dy*ny)*(iy   );
        else        ky=2.*M_PI/(dy*ny)*(iy-ny);

        fk[ixy] = (-(kx * kx) - (ky * ky)) * fk[ixy] / (nx * ny);
        ++ixy;
    }

    printf("Value of fk, %2f, fk imag %2f\n", creal(fk[4]), cimag(fk[4]));

     // Create fftw plan
     // execute the plan
    fftw_plan plan_f_backward = fftw_plan_dft_c2r_2d(nx, ny, fk, laplacefxy, FFTW_FORWARD);
    fftw_execute(plan_f_backward);

    // Uncomment to print results

    // for(ix=0; ix<nx; ix++) for(iy=0; iy<ny; iy++) 
    // {
    //     printf("%16.8f %16.8g %16.8g\n", kx, laplacefxy[ixy], laplace_function_xy(x0 + dx*ix, y0 + dy*iy));
    // }


    // Check correctness of computation
    test_array_diff(nx*ny, laplacefxy, test_laplacefxy);

    return 1;
}


#包括
#包括
#包括
#包括
#伊夫德夫·穆皮
#定义M_PI 3.14159265358979323846
#恩迪夫
//请参阅以供参考:
// https://en.cppreference.com/w/c/numeric/complex
#包括
//请参阅以供参考:
// http://www.fftw.org/fftw3_doc/
#包括
/**
*测试功能
* */
双功能_xy(双x,双y)
{
#定义-0.03
#定义B-0.01
#定义C-0.005
返回exp(A*x*x+B*y*y+C*x*y);
}
/**
*分析结果
*用它来检查正确性!
* */
双拉普拉斯函数(双x,双y)
{
双rdf2d_dx=函数_xy(x,y)*(2.*A*x+C*y);/d/dx
double rdf2d_dy=函数_xy(x,y)*(2.*B*y+C*x);/d/dy
双rlaplacef2d=rdf2d_dx*(2.*A*x+C*y)+函数_xy(x,y)*(2.*A)+rdf2d_dy*(2.*B*y+C*x)+函数_xy(x,y)*(2.*B);//拉普拉斯
返回rlaplacef2d;
#取消定义A
#未定义B
#未定义C
}
/**
*您可以使用此函数检查两个阵列之间的差异
* */
无效测试数组差异(整数N,双*a,双*b)
{
int-ixyz=0;
双d,d2;
双maxd2=0.0;
双槽d2=0.0;
对于(ixyz=0;ixyzmaxd2)maxd2=d2;
}
printf(“比较结果:\n”);
printf(“#|max[a-b]|::%16.8g\n”,sqrt(maxd2));
printf(“总和[(a-b)^2]:%16.8g\n”,总和2);
printf(“#SQRT(SUM[(a-b)^2])/N:%16.8g\N”,SQRT(sumd2)/N);
}
int main()
{
//背景
int nx=100;//x方向上的点数
int ny=100;//y方向上的点数
int=2;
双Lx=100.0;//x方向的宽度
双y=100.0;//y方向的宽度
双x0=-Lx/2;
双y0=-Ly/2;
双dx=Lx/nx;
双dy=Ly/ny;
double*fxy;//函数
double*test_laplacefxy;//根据公式计算结果的数组
fxy=(双*)malloc(nx*ny*sizeof(双));
如果(fxy==NULL){printf(“无法分配数组fx!\n”);返回0;}
test_laplacefxy=(双*)malloc(nx*ny*sizeof(双));
如果(test_laplacefxy==NULL){printf(“无法分配数组fx!\n”);返回0;}
int ix,iy,ixy;
ixy=0;
对于(ix=0;ix