ydluo / qdyn

A Quasi-DYNamic earthquake simulator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

FFT of vector of arbitrary size

martijnende opened this issue · comments

As @gpercy and @jpampuero mentioned to me, the current FFT routine requires a vector of size 2^N, though there are no internal checks for this requirement, possibly resulting in corrupt/inaccurate data. Possible workarounds:

  1. Add a sanity check while the input file is being read, to make sure that the mesh size is a power of 2
  2. Allow for arbitrary mesh sizes, but pad the data vector with zeros

The latter is more user-friendly, while the former is computationally more efficient.

I implemented option 1 in the matlab wrapper, only for MESHDIM=1.
For MESHDIM=2, this needs to be done in the fortran code.
I also modified the user's manual (the google doc) accordingly.

I implemented option 1 also in the fortran code.
Option 2 does not work with our periodic kernels expressed analytically in spectral domain (wavenumber). Hence we can close this issue.

Thanks Pablo. I've had a look at the error check you implemented in fftsg.f90, and I have a few remarks:

  1. This check is performed every time my_rdft is called. Although this is by far the safest way to go, I propose to take a little more risk in favour of performance and do the sanity check only once at the initiation stage (i.e. during/after reading the input file).
  2. We don't actually need to know the next power of 2, we just need to know if a given integer is a power of 2. This can be computed much more efficiently as (n .AND. (n-1)) == 0 (an equivalent expression works in C++ and Python, never tried it in Fortran). This expression only requires 2 clock cycles or so, as opposed to several tens of cycles required to calculate the next power of 2.

Have you tested your code changes before you pushed them to master?

  1. I modified the code to execute the power-of-2 test only when fft is (re)initialized. Usually this happens only once during a run. Keeping the test in the fft module satisfies the encapsulation principle, but feel free to implement an additional test in the initiation stage.
  2. The is-a-power-of-2 test can be implemented in one line using a bit manipulation trick with intrinsic functions in Fortran 2008 as n>1 .and. popcnt(n)==1. I implemented that too, but commented it out in case some users don't have a Fortran 2008 compiler (I have seen that happen in another software project).

I didn't test the code. I am editing in a browser. No compiler at hand.

I would avoid using bit manipulation, the 2^n check is called only once each model run thus not a big burden for computation

All right, I think Pablo's implementation is satisfactory, so I'll close this issue now.