2D FFT using 1D FFT with mpi - fortran

I'm trying to use a complex matrix with the dimensions (n x n) with the fftw_mpi subroutines (version 3.3.2): A 1D FFT (complex to complex) on all the rows and after a 1D FFT (complex to complex) for all columns. First I have made a serial code in Fortran, and everything is working properly, but when I'm trying the fftw subroutines with mpi the results are not as I expected. Is something wrong in how is created the plan for the 1D FFT transform? Below it is an example (only the first 1D FFT on the rows):
! get local data size and allocate (dimension reversal)
alloc_local = fftw_mpi_local_size_2d(M, L, MPI_COMM_WORLD, &
local_M, local_j_offset)
cdata = fftw_alloc_complex(alloc_local)
call c_f_pointer(cdata, ldata, [L,local_M])
call c_f_pointer(cdata, data, [L,local_M])
! create MPI plan
plan = fftw_mpi_plan_many_dft(1, L*local_M, local_M, FFTW_MPI_DEFAULT_BLOCK, &
FFTW_MPI_DEFAULT_BLOCK, ldata, data, MPI_COMM_WORLD, FFTW_FORWARD, FFTW_ESTIMATE)
do j = 1, local_M
do i = 1, L
ldata(i,j)= my_function
enddo
enddo
! compute transform
call fftw_mpi_execute_dft(plan, ldata, data)
call fftw_destroy_plan(plan)
call fftw_free(cdata)
call MPI_FINALIZE(mpi_err)

Related

Infinite do loop issue

Just to preface this question, I am a couple weeks new to Fortran and I have run into an infinite do loop error when running the actual program.
I am 99% sure that the infinite sequence is coming from the do loop, but I thought I should ask just to be sure. I am not sure what part of the do loop is causing the infinite do loop but any help would be greatly appreciated!
Here is the code:
implicit none
! Declare variables - Add variables as necessary (integer only!)
! M will store the encoding matrix, MInv will store its inverse
! Decoded_message will store the decoded message
integer :: M(2,2), MInv(2,2), Determinant, a, b, c, d, detM, i, v(:,:), ascIIcode(:,:)
allocatable :: v, ascIIcode
character*32 :: Decoded_Message
! open data file and read in the encoding matrix
open(42,file='Data3.txt')
read(42,*) M(1,1), M(1,2)
read(42,*) M(2,1), M(2,2)
! Invert the encoding matrix and store it in MInv
detM = determinant(M)
MInv(1,1) = +detM *M(2,2)
MInv(1,2) = -detM *M(2,1)
MInv(2,1) = -detM *M(1,2)
MInv(2,2) = +detM *M(1,1)
! Processing steps required:
! Read from the file in 2 numbers at a time and store in a vector array
do i = 2, 31
allocate (v(2,1), ascIIcode(2,1))
read(42,*) v(1,1)
read(42,*) v(2,1)
! decode the 2 numbers read in (1) by multiplying Minv by the vector array from (1)
ascIIcode(1,1) = ((MInv(1,1)*v(1,1))+(MInv(1,2)*v(2,1)))
ascIIcode(2,1) = ((MInv(2,1)*v(1,1))+(MInv(2,2)*v(2,1)))
! Insert the result from (2) into the character string Decoded_Message. To concatinate
Decoded_Message = char(ascIIcode(1,1))//char(ascIIcode(2,1))
! Use a loop that advances in steps of 2 and goes to 31
deallocate (v)
deallocate (ascIIcode)
end do
! print results.
print*, Decoded_Message
! close files
close(42)
end program Decode
integer function Determinant(M)
! This function computes the determinant of matices of size 2 or 3
! M is the matrix for which the determinant is calculated (square matrix only)
! n is the number of rows or columns in M
implicit none
integer :: M(2,2), a, b, c, d, e, f, g, h, i, Det
do
a = M(1,1)
b = M(1,2)
c = M(2,1)
d = M(2,2)
Det = (a*d)-(b*c)
end do
end function Determinant

Evaluating the fast Fourier transform of Gaussian function in FORTRAN using FFTW3 library

I am trying to write a FORTRAN code to evaluate the fast Fourier transform of the Gaussian function f(r)=exp(-(r^2)) using FFTW3 library. As everyone knows, the Fourier transform of the Gaussian function is another Gaussian function.
I consider evaluating the Fourier-transform integral of the Gaussian function in the spherical coordinate.
Hence the resulting integral can be simplified to be integral of [r*exp(-(r^2))*sin(kr)]dr.
I wrote the following FORTRAN code to evaluate the discrete SINE transform DST which is the discrete Fourier transform DFT using a PURELY real input array. DST is performed by C_FFTW_RODFT00 existing in FFTW3, taking into account that the discrete values in position space are r=i*delta (i=1,2,...,1024), and the input array for DST is the function r*exp(-(r^2)) NOT the Gaussian. The sine function in the integral of [r*exp(-(r^2))*sin(kr)]dr resulting from the INTEGRATION over the SPHERICAL coordinates, and it is NOT the imaginary part of exp(ik.r) that appears when taking the analytic Fourier transform in general.
However, the result is not a Gaussian function in the momentum space.
Module FFTW3
use, intrinsic :: iso_c_binding
include 'fftw3.f03'
end module
program sine_FFT_transform
use FFTW3
implicit none
integer, parameter :: dp=selected_real_kind(8)
real(kind=dp), parameter :: pi=acos(-1.0_dp)
integer, parameter :: n=1024
real(kind=dp) :: delta, k
real(kind=dp) :: numerical_F_transform
integer :: i
type(C_PTR) :: my_plan
real(C_DOUBLE), dimension(1024) :: y
real(C_DOUBLE), dimension(1024) :: yy, yk
integer(C_FFTW_R2R_KIND) :: C_FFTW_RODFT00
my_plan= fftw_plan_r2r_1d(1024,y,yy,FFTW_FORWARD, FFTW_ESTIMATE)
delta=0.0125_dp
do i=1, n !inserting the input one-dimension position function
y(i)= 2*(delta)*(i-1)*exp(-((i-1)*delta)**2)
! I multiplied by 2 due to the definition of C_FFTW_RODFT00 in FFTW3
end do
call fftw_execute_r2r(my_plan, y,yy)
do i=2, n
k = (i-1)*pi/n/delta
yk(i) = 4*pi*delta*yy(i)/2 !I divide by 2 due to the definition of
!C_FFTW_RODFT00
numerical_F_transform=yk(i)/k
write(11,*) i,k,numerical_F_transform
end do
call fftw_destroy_plan(my_plan)
end program
Executing the previous code gives the following plot which is not for Gaussian function.
Can anyone help me understand what the problem is? I guess the problem is mainly due to FFTW3. Maybe I did not use it properly especially concerning the boundary conditions.
Looking at the related pages in the FFTW site (Real-to-Real Transforms, transform kinds, Real-odd DFT (DST)) and the header file for Fortran, it seems that FFTW expects FFTW_RODFT00 etc rather than FFTW_FORWARD for specifying the kind of
real-to-real transform. For example,
! my_plan= fftw_plan_r2r_1d( n, y, yy, FFTW_FORWARD, FFTW_ESTIMATE )
my_plan= fftw_plan_r2r_1d( n, y, yy, FFTW_RODFT00, FFTW_ESTIMATE )
performs the "type-I" discrete sine transform (DST-I) shown in the above page. This modification seems to fix the problem (i.e., makes the Fourier transform a Gaussian with positive values).
The following is a slightly modified version of OP's code to experiment the above modification:
! ... only the modified part is shown...
real(dp) :: delta, k, r, fftw, num, ana
integer :: i, j, n
type(C_PTR) :: my_plan
real(C_DOUBLE), allocatable :: y(:), yy(:)
delta = 0.0125_dp ; n = 1024 ! rmax = 12.8
! delta = 0.1_dp ; n = 128 ! rmax = 12.8
! delta = 0.2_dp ; n = 64 ! rmax = 12.8
! delta = 0.4_dp ; n = 32 ! rmax = 12.8
allocate( y( n ), yy( n ) )
! my_plan= fftw_plan_r2r_1d( n, y, yy, FFTW_FORWARD, FFTW_ESTIMATE )
my_plan= fftw_plan_r2r_1d( n, y, yy, FFTW_RODFT00, FFTW_ESTIMATE )
! Loop over r-grid
do i = 1, n
r = i * delta ! (2-a)
y( i )= r * exp( -r**2 )
end do
call fftw_execute_r2r( my_plan, y, yy )
! Loop over k-grid
do i = 1, n
! Result of FFTW
k = i * pi / ((n + 1) * delta) ! (2-b)
fftw = 4 * pi * delta * yy( i ) / k / 2 ! the last 2 due to RODFT00
! Numerical result via quadrature
num = 0
do j = 1, n
r = j * delta
num = num + r * exp( -r**2 ) * sin( k * r )
enddo
num = num * 4 * pi * delta / k
! Analytical result
ana = sqrt( pi )**3 * exp( -k**2 / 4 )
! Output
write(10,*) k, fftw
write(20,*) k, num
write(30,*) k, ana
end do
Compile (with gfortran-8.2 + FFTW3.3.8 + OSX10.11):
$ gfortran -fcheck=all -Wall sine.f90 -I/usr/local/Cellar/fftw/3.3.8/include -L/usr/local/Cellar/fftw/3.3.8/lib -lfftw3
If we use FFTW_FORWARD as in the original code, we get
which has a negative lobe (where fort.10, fort.20, and fort.30 correspond to FFTW, quadrature, and analytical results). Modifying the code to use FFTW_RODFT00 changes the result as below, so the modification seems to be working (but please see below for the grid definition).
Additional notes
I have slightly modified the grid definition for r and k in my code (Lines (2-a) and (2-b)), which is found to improve the accuracy. But I'm still not sure whether the above definition matches the definition used by FFTW, so please read the manual for details...
The fftw3.f03 header file gives the interface for fftw_plan_r2r_1d
type(C_PTR) function fftw_plan_r2r_1d(n,in,out,kind,flags) bind(C, name='fftw_plan_r2r_1d')
import
integer(C_INT), value :: n
real(C_DOUBLE), dimension(*), intent(out) :: in
real(C_DOUBLE), dimension(*), intent(out) :: out
integer(C_FFTW_R2R_KIND), value :: kind
integer(C_INT), value :: flags
end function fftw_plan_r2r_1d
(Because of no Tex support, this part is very ugly...) The integral of 4 pi r^2 * exp(-r^2) * sin(kr)/(kr) for r = 0 -> infinite is pi^(3/2) * exp(-k^2 / 4) (obtained from Wolfram Alpha or by noting that this is actually a 3-D Fourier transform of exp(-(x^2 + y^2 + z^2)) by exp(-i*(k1 x + k2 y + k3 z)) with k =(k1,k2,k3)). So, although a bit counter-intuitive, the result becomes a positive Gaussian.
I guess the r-grid can be chosen much coarser (e.g. delta up to 0.4), which gives almost the same accuracy as long as it covers the frequency domain of the transformed function (here exp(-r^2)).
Of course there are negative components of the real part to the FFT of a limited Gaussian spectrum. You are just using the real part of the transform. So your plot is absolutely correct.
You seem to be mistaking the real part with the magnitude, which of course would not be negative. For that you would need to fftw_plan_dft_r2c_1d and then calculate the absolute values of the complex coefficients. Or you might be mistaking the Fourier transform with a limited DFT.
You might want to check here to convince yourself of the correctness of you calculation above:
http://docs.mantidproject.org/nightly/algorithms/FFT-v1.html
Please do keep in mind that the plots on the above page are shifted, so that the 0 frequency is in the middle of the spectrum.
Citing yourself, the nummeric integration of [r*exp(-(r^2))*sin(kr)]dr would have negative components for all k>1 if normalised to 0 for highest frequency.
TLDR: Your plot is absolute state of the art and inline with discrete and limited functional analysis.

How can I transfer a complex matrix from Matlab R2018a to Eigen

I am currently importing the real and imaginary parts of a matrix separately from Matlab to C++. I then also map the real and imaginary parts to Eigen separately. I also perform the calculation and map the final result separately, as shown below:
//import real and imaginary parts from matlab
mwSize M = mxGetM (prhs[1]);
mwSize N = mxGetN (prhs[1]);
double * PR = mxGetPr (prhs[1]);
double * PI = mxGetPi (prhs[1]);
//map real and imaginary parts to Eigen
Map<Matrix<double,Dynamic,Dynamic,ColMajor> > Br (PR, M, N );
Map<Matrix<double,Dynamic,Dynamic,ColMajor> > Bi (PI, M, N );
//map real and imaginary parts of result
plhs[0] = mxCreateDoubleMatrix(M, N, mxCOMPLEX);
Map<Matrix<double,Dynamic,Dynamic,ColMajor> > resultr (mxGetPr(plhs[0]), M, N);
Map<Matrix<double,Dynamic,Dynamic,ColMajor> > resulti (mxGetPi(plhs[0]), M, N);
//calculate real and imaginary parts of A*B separately
resultr=A*Br;
resulti=A*Bi;
However, as of R2018a, Matlab allows importing the real and imaginary parts together.
How can I do this? I tried the following:
//import complex matrix from matlab
mwSize N = mxGetN (prhs[1]);
mxComplexDouble * PR = mxGetComplexDoubles (prhs[1]);
//map complex matrix to eigen
Map<Matrix<mxComplexDouble,Dynamic,Dynamic,ColMajor> > B (PR, M, N );
//map complex result
plhs[0] = mxCreateDoubleMatrix(M, N, mxCOMPLEX);
Map<Matrix<mxComplexDouble,Dynamic,Dynamic,ColMajor> > result (mxGetDoubles(plhs[0]), M, N);
//calculate real and imaginary parts together
result=A*B;
But it does not compile because Eigen does not like the mxComplexDouble type.
If I understood correctly, mxComplexDouble has the same layout as std::complex<double>, so you should be able to simply cast:
auto* PR = reinterpret_cast<std::complex<double>*>(mxGetComplexDoubles(prhs[1]));
Reference:
In the -R2018a API, the mxGetElementSize function returns sizeof(std::complex<T>) for a complex mxArray with data type T. This value is twice the value returned by the function in the -R2017b API.
From MATLAB documentation page "Upgrade MEX Files to Use Interleaved Complex API"

FFTW: Inverse transform of forward transform of 1/cosh function is wrong

I'm attempting to take the inverse transform of a complex 1D arrays forward transform in Fortran 90 and fftw. However, the output I receive from the inverse transform is at times completely different from the original input, whereas some values possess an incorrect real section but a correct imaginary part and a few match the original values perfectly.
I've noticed that this issue disappears if dx (the spacing between x values) is reduced to 0.01. Increasing n to compensate for this reduction in x's range then results in the issue resurfacing.
At this point, I believe the issue lies in the 1/cosh segment of the input array as I've been able to replace this with other complex inputs with no issues.
This code is adapted from a MATLAB file in which the form of the input only differs due to MATLAB using sech instead of 1/cosh.
Fortran isn't my 'go to' language so I'm wondering if I've made some normally obvious mistake due to my familiarity with python/matlab .
As for more specifics on the outputs,
The matlab version of this code produces the same values for the in array but the operation of the forward transform and the inverse transform produce different results,
Matlab
out2(2) = 5.5511e-17 + 6.9389e-18i
out2(3) = 5.5511e-17 - 1.3878e-17i
out2(4) = 5.5511e-17 + 2.7756e-17i
out2(1024) = 0.9938 + 0.0994i
out2(2048) = 0 - 1.3878e-17i
Fortran
out2(2) = -5.5511151231257827E-017 - 6.9388939039072284E-018i
out2(3) = 0.0000000000000000 + 1.3877787807814457E-017i
out2(4) = 0.0000000000000000 + 0.0000000000000000i
out(1024) = 0.99380163159683255 + 9.9410098890158616E-002i
out2(2048) = -5.5511151231257827E-017 - 6.9388939039072284E-018i
PROGRAM FFTEXAMPLE
implicit none
include 'fftw3.f'
INTEGER :: n, j, nindex, i
REAL :: dx
DOUBLE COMPLEX, ALLOCATABLE :: in(:), out(:), in2(:), out2(:)
REAL(kind = 8), ALLOCATABLE :: x(:)
INTEGER*8 :: plan, plan2
nindex = 11
n = 2 ** nindex
dx = 0.05 ! Spacing between x array values
allocate( in(n), out(n), x(n), in2(n), out2(n) )
CALL dfftw_plan_dft_1d( plan, n, in, out, FFTW_FORWARD, FFTW_ESTIMATE )
CALL dfftw_plan_dft_1d( plan2, n, in2, out2, FFTW_BACKWARD, FFTW_ESTIMATE )
x = (/ (-dx*n/2 + (i-1)*dx, i=1, n) /) ! Seeds x array from -51.2 to 51.15
! Create values for the input array
DO j = 1, n, 1
in(j) = 1/cosh ( x(j)/1.0040 ) * exp( (0.0, -1.0) * 1.9940 * x(j) )
END DO
CALL dfftw_execute_dft( plan, in, out ) ! FWD transform
!DO j = 1, n, 1
! in2(j) = cmplx(REAL(out(j)), AIMAG(out(j)))
!END DO
in2 = out
CALL dfftw_execute_dft( plan2, in2, out2 ) ! Inverse transform
out2 = out2/n ! Divide output by n to normalise
CALL dfftw_destroy_plan( plan )
CALL dfftw_destroy_plan( plan2 )
END PROGRAM

MPI FFTW in Fortran for a 3D complex array

I need to make a FFT of a 3D array in Fortran using MPI. I've been looking at the FFTW website and I also tried to look for examples online but I could find only this code:
use, intrinsic :: iso_c_binding
include 'fftw3-mpi.f03'
integer(C_INTPTR_T), parameter :: L = ...
integer(C_INTPTR_T), parameter :: M = ...
type(C_PTR) :: plan, cdata
complex(C_DOUBLE_COMPLEX), pointer :: data(:,:)
integer(C_INTPTR_T) :: i, j, alloc_local, local_M, local_j_offset
! get local data size and allocate (note dimension reversal)
alloc_local = fftw_mpi_local_size_2d(M, L, MPI_COMM_WORLD, &
local_M, local_j_offset)
cdata = fftw_alloc_complex(alloc_local)
call c_f_pointer(cdata, data, [L,local_M])
! create MPI plan for in-place forward DFT (note dimension reversal)
plan = fftw_mpi_plan_dft_2d(M, L, data, data, MPI_COMM_WORLD, &
FFTW_FORWARD, FFTW_MEASURE)
! initialize data to some function my_function(i,j)
do j = 1, local_M
do i = 1, L
data(i, j) = my_function(i, j + local_j_offset)
end do
end do
! compute transform (as many times as desired)
call fftw_mpi_execute_dft(plan, data, data)
call fftw_destroy_plan(plan)
call fftw_free(cdata)
This code computes the FFT transform of a 2d array. My question is: how can I use this code to compute a FFT transform of a 3d array?
Regarding fftw_mpi_plan_dft_2d have a look at:
http://www.fftw.org/doc/MPI-Plan-Creation.html
It is quite obvious that there must be a fftw_mpi_plan_dft_3d function as well. The same of course for fftw_mpi_local_size_2d. The arguments will change slightly but the documentation will help you on this.