Confusion about FFTW3 guru interface: 3 simultaneous complex FFTs

☆樱花仙子☆ 提交于 2019-12-11 07:13:19

问题


I am trying to use the FFTW3 guru interface. However, the description in the documentation causes me more confusion that clarity. I want to create a plan for 3 scalar complex FFTs, each of length n, which should be aligned in memory one after the other (interleaved arrays). I do not understand whether this implies rank == 3 or howmany_rank == 3. I also don't know, which values the arrays fftw_iodim *dims and const fftw_iodim *howmany_dims need to have.

While this stackexchange post seems to have a good answer, it uses the same terminology of the documentation and does not "create an image in my head" of how the FFTs will be aligned in memory for different ranks and different howmany_ranks. That is, the answer does not help with what I am looking for.

For reference, this is the definition of the plan allocation function:

fftw_plan fftw_plan_guru_dft(
      int rank, const fftw_iodim *dims,
      int howmany_rank, const fftw_iodim *howmany_dims,
      fftw_complex *in, fftw_complex *out,
      int sign, unsigned flags);

Note that using the "standard interface" is not possible since I have to switch to the guru64 (64 bit) interface later.


回答1:


fftw_plan fftw_plan_guru_dft() allows to define 1D-2D-3D-4D... DFT (rank=1,2,3,4... ) applied multiple times using starting points located on a 1D, 2D, 3D, 4D... grid (howmany_rank=1,2,3,4....

The argument rank specifies the number of dimensions on which the DFT is applied. The extends and layout of these dimensions are specified by argument *dims. After the DFT transform is executed, indexes of these dimensions correspond to frequencies. These arguments defines a multidimensional DFT to be applied.

Argument howmany_rank and howmany_dims specifies starting points to apply multiple times the multidimensionnal transform defined above. Starting points can be located on a multidimensionnal array described by extends and strides. Argument howmany_rank describe the number of dimensions of the array of starting points.

Let's consider a field featuring 3 scalar components u, v, w sampled on a line at regularly spaced point of abscisse x_i=iL/N. The field is stored in memory as an interleaved contiguous 2D array of dimension (N,3):

u(x_0) v(x_0) w(x_0) u(x_1) v(x_1) w(x_1) u(x_2) v(x_2) w(x_2)... u(x_N-1) v(x_N-1) w(x_N-1) 

A 1D DFT is to be performed on the space coordinate x. Hence, rank equals 1. Each 1D DFT is of length N, and the spacing (or stride) between two consecutive items (u_(x_0) and u(x_1)) is 3. Hence, dims[0].n=N, dims[0].is=3 and dims[0].os=3 . is is for input stride and os is for output stride.

The 1D DFT is to be performed multiple times, once for each component. Since the starting points of these DFTs u(x_0), v(x_0) and w(x_0) are regularly spaced, the positions of these starting points define an array of dimension 1. Hence howmany_rank=1. Moreover, since there are 3 contiguous starting points, the layout of the array of starting points is defined as howmany_dims[0].n=3, howmany_dims[0].is=1 and howmany_dims[0].os=1.

The sample code provided in my answer to How to use fftw Guru interface (sorry that it did not help you!) can easily be adapted as:

#include<stdlib.h>
#include<complex.h>
#include<math.h>
#include<fftw3.h>

int main(void){

    fftw_plan p;
    unsigned long int N = 10;
    unsigned long int DOF = 3;
    fftw_complex *in=fftw_malloc(N*DOF*sizeof(fftw_complex));
    if(in==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    fftw_complex *out=fftw_malloc(N*DOF*sizeof(fftw_complex));
    if(out==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    unsigned int i;

    int rank=1;
    fftw_iodim64 *dims=malloc(rank*sizeof(fftw_iodim64));
    if(dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    dims[0].n=N;
    dims[0].is=DOF;
    dims[0].os=DOF;

    int howmany_rank=1;
    fftw_iodim64 *howmany_dims=malloc(howmany_rank*sizeof(fftw_iodim64));
    if(howmany_dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
    howmany_dims[0].n=DOF;
    howmany_dims[0].is=1;
    howmany_dims[0].os=1;

    printf("sizeof fftw complex %ld\n",sizeof(fftw_complex));
    printf("sizeof fftw_iodim64 %ld\n",sizeof(fftw_iodim64));
    printf("creating the plan\n");
    p=fftw_plan_guru64_dft(rank, dims,howmany_rank, howmany_dims,in, out,FFTW_FORWARD, FFTW_ESTIMATE);
    if (p==NULL){fprintf(stderr,"plan creation failed\n");exit(1);}
    printf("created the plan\n");

    for(i=0;i<N;i++){
                in[i*DOF]=30.+12.*sin(2*3.1415926535*i/((double)N));
                in[i*DOF+1]=42.0;
                in[i*DOF+2]=1.0;
    }

    fftw_execute(p);

    for (i = 0; i < N; i++){
        printf("result: %d || %g %gI | %g %gI | %g %gI\n", i, creal(out[i*DOF]), cimag(out[i*DOF]),creal(out[i*DOF+1]), cimag(out[i*DOF+1]),creal(out[i*DOF+2]), cimag(out[i*DOF+2]));
    }


    fftw_destroy_plan(p);
    fftw_free(in);
    fftw_free(out);

    free(dims);
    free(howmany_dims);

    return(0);
}

And compiled by gcc main.c -o main -lfftw3 -lm -Wall.



来源:https://stackoverflow.com/questions/58513592/confusion-about-fftw3-guru-interface-3-simultaneous-complex-ffts

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!