-
Antoine Cyril David Hoffmann authoredAntoine Cyril David Hoffmann authored
fourier_mod.F90 5.13 KiB
MODULE fourier
USE prec_const
USE grid
use, intrinsic :: iso_c_binding
implicit none
! INCLUDE 'fftw3.f03'
INCLUDE 'fftw3-mpi.f03'
PRIVATE
PUBLIC :: fft_r2cc
PUBLIC :: ifft_cc2r
PUBLIC :: fft2_r2cc
PUBLIC :: ifft2_cc2r
PUBLIC :: convolve_2D_F2F
CONTAINS
SUBROUTINE fft_r2cc(fx_in, Fk_out)
IMPLICIT NONE
REAL(dp), DIMENSION(Nr), INTENT(IN) :: fx_in
COMPLEX(dp), DIMENSION(Nkr), INTENT(OUT):: Fk_out
integer*8 plan
CALL dfftw_plan_dft_r2c_1d(plan,Nr,fx_in,Fk_out,FFTW_FORWARD,FFTW_ESTIMATE)
CALL dfftw_execute_dft_r2c(plan, fx_in, Fk_out)
CALL dfftw_destroy_plan(plan)
END SUBROUTINE fft_r2cc
SUBROUTINE ifft_cc2r(Fk_in, fx_out)
IMPLICIT NONE
COMPLEX(dp), DIMENSION(Nkr), INTENT(IN) :: Fk_in
REAL(dp), DIMENSION(Nr), INTENT(OUT):: fx_out
integer*8 plan
CALL dfftw_plan_dft_c2r_1d(plan,Nr,Fk_in,fx_out,FFTW_BACKWARD,FFTW_ESTIMATE)
CALL dfftw_execute_dft_c2r(plan, Fk_in, fx_out)
CALL dfftw_destroy_plan(plan)
fx_out = fx_out/Nr
END SUBROUTINE ifft_cc2r
SUBROUTINE fft2_r2cc( ffx_in, FFk_out )
IMPLICIT NONE
REAL(dp), DIMENSION(Nr,Nz), INTENT(IN) :: ffx_in
COMPLEX(dp), DIMENSION(Nkr,Nkz), INTENT(OUT):: FFk_out
integer*8 plan
!!! 2D Forward FFT ________________________!
CALL dfftw_plan_dft_r2c_2d(plan,Nr,Nz,ffx_in,FFk_out,FFTW_FORWARD,FFTW_ESTIMATE)
CALL dfftw_execute_dft_r2c(plan,ffx_in,FFk_out)
CALL dfftw_destroy_plan(plan)
END SUBROUTINE fft2_r2cc
SUBROUTINE ifft2_cc2r( FFk_in, ffx_out )
IMPLICIT NONE
COMPLEX(dp), DIMENSION(Nkr,Nkz), INTENT(IN) :: FFk_in
REAL(dp), DIMENSION(Nr,Nz), INTENT(OUT) :: ffx_out
COMPLEX(dp), DIMENSION(Nkr,Nkz) :: tmp_c
integer*8 plan
tmp_c = FFk_in
!!! 2D Backward FFT ________________________!
CALL dfftw_plan_dft_c2r_2d(plan,Nr,Nz,tmp_c,ffx_out,FFTW_BACKWARD,FFTW_ESTIMATE)
CALL dfftw_execute_dft_c2r(plan,tmp_c,ffx_out)
CALL dfftw_destroy_plan(plan)
ffx_out = ffx_out/Nr/Nz
END SUBROUTINE ifft2_cc2r
!!! Convolution 2D Fourier to Fourier
! - Compute the convolution using the convolution theorem and MKL
SUBROUTINE convolve_2D_F2F( F_2D, G_2D, C_2D )
USE basic
USE grid, ONLY : AA_r, AA_z, Lr, Lz
IMPLICIT NONE
COMPLEX(dp), DIMENSION(Nkr,Nkz), INTENT(IN) :: F_2D, G_2D ! input fields
COMPLEX(dp), DIMENSION(Nkr,Nkz), INTENT(OUT) :: C_2D ! output convolutioned field
REAL(dp), DIMENSION(Nr,Nz) :: ff, gg ! iFFT of input fields
REAL(dp), DIMENSION(Nr,Nz) :: ffgg ! will receive the product of f*g in Real
INTEGER :: ikr, ikz
REAL :: a_r
! 2D inverse Fourier transform
IF ( num_procs .EQ. 1 ) THEN
CALL ifft2_cc2r(F_2D,ff)
CALL ifft2_cc2r(G_2D,gg)
ELSE
CALL ifft2_cc2r_mpi(F_2D,ff)
CALL ifft2_cc2r_mpi(G_2D,gg)
ENDIF
! Product in physical space
ffgg = ff * gg;
! 2D Fourier tranform
IF ( num_procs .EQ. 1 ) THEN
CALL fft2_r2cc(ffgg,C_2D)
ELSE
CALL fft2_r2cc_mpi(ffgg,C_2D)
ENDIF
! Anti aliasing (2/3 rule)
DO ikr = ikrs,ikre
a_r = AA_r(ikr)
DO ikz = ikzs,ikze
C_2D(ikr,ikz) = C_2D(ikr,ikz) * a_r * AA_z(ikz)
ENDDO
ENDDO
END SUBROUTINE convolve_2D_F2F
!! MPI routines
SUBROUTINE fft2_r2cc_mpi( ffx_in, FFk_out )
IMPLICIT NONE
REAL(dp), DIMENSION(Nr,Nz), INTENT(IN) :: ffx_in
COMPLEX(dp), DIMENSION(Nkr,Nkz), INTENT(OUT):: FFk_out
REAL(dp), DIMENSION(Nkr,Nkz) :: tmp_r
type(C_PTR) :: plan
integer(C_INTPTR_T) :: L
integer(C_INTPTR_T) :: M
! L = Nr; M = Nz
!
! tmp_r = ffx_in
! !!! 2D Forward FFT ________________________!
! plan = fftw_mpi_plan_dft_r2c_2d(L, M, tmp_r, FFk_out, MPI_COMM_WORLD, FFTW_ESTIMATE)
!
! if ((.not. c_associated(plan))) then
! write(*,*) "plan creation error!!"
! stop
! end if
!
! CALL fftw_mpi_execute_dft_r2c(plan,tmp_r,FFk_out)
! CALL fftw_destroy_plan(plan)
END SUBROUTINE fft2_r2cc_mpi
SUBROUTINE ifft2_cc2r_mpi( FFk_in, ffx_out )
IMPLICIT NONE
COMPLEX(dp), DIMENSION(Nkr,Nkz), INTENT(IN) :: FFk_in
REAL(dp), DIMENSION(Nr,Nz), INTENT(OUT) :: ffx_out
COMPLEX(dp), DIMENSION(Nkr,Nkz) :: tmp_c
type(C_PTR) :: plan
integer(C_INTPTR_T) :: L
integer(C_INTPTR_T) :: M
! L = Nr; M = Nz
!
! tmp_c = FFk_in
! !!! 2D Backward FFT ________________________!
! plan = fftw_mpi_plan_dft_c2r_2d(L, M, tmp_c, ffx_out, MPI_COMM_WORLD, FFTW_ESTIMATE)
!
! if ((.not. c_associated(plan))) then
! write(*,*) "plan creation error!!"
! stop
! end if
!
! CALL fftw_mpi_execute_dft_c2r(plan,tmp_c,ffx_out)
! CALL fftw_destroy_plan(plan)
!
! ffx_out = ffx_out/Nr/Nz
END SUBROUTINE ifft2_cc2r_mpi
! Empty set/free routines to switch easily with MKL DFTI
SUBROUTINE set_descriptors
END SUBROUTINE set_descriptors
SUBROUTINE free_descriptors
END SUBROUTINE free_descriptors
END MODULE fourier