MODULE fourier USE prec_const USE grid USE basic use, intrinsic :: iso_c_binding implicit none ! INCLUDE 'fftw3.f03' INCLUDE 'fftw3-mpi.f03' PRIVATE PUBLIC :: init_grid_distr_and_plans, convolve_2D_F2F, finalize_plans real(C_DOUBLE), pointer :: real_data_f(:,:), real_data_g(:,:), real_data_c(:,:) complex(C_DOUBLE_complex), pointer :: cmpx_data_f(:,:), cmpx_data_g(:,:), cmpx_data_c(:,:) type(C_PTR) :: cdatar_f, cdatar_g, cdatar_c type(C_PTR) :: cdatac_f, cdatac_g, cdatac_c type(C_PTR) :: planf, planb integer(C_INTPTR_T) :: i, ix, iy, alloc_local_1, alloc_local_2 integer(C_INTPTR_T) :: NR_, NZ_ CONTAINS SUBROUTINE init_grid_distr_and_plans(Nr,Nz) IMPLICIT NONE INTEGER, INTENT(IN) :: Nr,Nz NR_ = Nr; NZ_ = Nz ! Compute the room to allocate alloc_local_1 = fftw_mpi_local_size_2d(NR_/2 + 1, NZ_, MPI_COMM_WORLD, local_nkr, local_nkr_offset) ! Initalize pointers to this room cdatac_f = fftw_alloc_complex(alloc_local_1) cdatac_g = fftw_alloc_complex(alloc_local_1) cdatac_c = fftw_alloc_complex(alloc_local_1) ! Initalize the arrays with the rooms pointed call c_f_pointer(cdatac_f, cmpx_data_f, [NZ_ ,local_nkr]) call c_f_pointer(cdatac_g, cmpx_data_g, [NZ_ ,local_nkr]) call c_f_pointer(cdatac_c, cmpx_data_c, [NZ_ ,local_nkr]) alloc_local_2 = fftw_mpi_local_size_2d(NZ_, NR_/2 + 1, MPI_COMM_WORLD, local_nz, local_nz_offset) cdatar_f = fftw_alloc_real(2*alloc_local_2) cdatar_g = fftw_alloc_real(2*alloc_local_2) cdatar_c = fftw_alloc_real(2*alloc_local_2) call c_f_pointer(cdatar_f, real_data_f, [2*(NR_/2 + 1),local_nz]) call c_f_pointer(cdatar_g, real_data_g, [2*(NR_/2 + 1),local_nz]) call c_f_pointer(cdatar_c, real_data_c, [2*(NR_/2 + 1),local_nz]) ! Plan Creation (out-of-place forward and backward FFT) planf = fftw_mpi_plan_dft_r2c_2d(NZ_, NR_, real_data_f, cmpx_data_f, MPI_COMM_WORLD, ior(FFTW_MEASURE, FFTW_MPI_TRANSPOSED_OUT)) planb = fftw_mpi_plan_dft_c2r_2d(NZ_, NR_, cmpx_data_f, real_data_f, MPI_COMM_WORLD, ior(FFTW_MEASURE, FFTW_MPI_TRANSPOSED_IN)) if ((.not. c_associated(planf)) .OR. (.not. c_associated(planb))) then write(*,*) "plan creation error!!" stop end if DO ix = 0,num_procs-1 CALL mpi_barrier(MPI_COMM_WORLD, ierr) IF (my_id .EQ. ix) print *, my_id,': alloc_local = ', alloc_local_1+alloc_local_2 CALL mpi_barrier(MPI_COMM_WORLD, ierr) ! IF (my_id .EQ. 0) print *, my_id,': local_nz = ', local_nz, ' loc_nz_of. = ', local_nz_offset ! CALL mpi_barrier(MPI_COMM_WORLD, ierr) ENDDO END SUBROUTINE init_grid_distr_and_plans !!! Convolution 2D Fourier to Fourier ! - Compute the convolution using the convolution theorem and MKL SUBROUTINE convolve_2D_F2F( F_2D, G_2D, C_2D ) IMPLICIT NONE COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(ikrs:ikre,ikzs:ikze), INTENT(IN) :: F_2D, G_2D ! input fields COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(ikrs:ikre,ikzs:ikze), INTENT(OUT) :: C_2D ! output convolutioned field do ikr = ikrs, ikre do ikz = ikzs, ikze cmpx_data_f(ikz,ikr-local_nkr_offset) = F_2D(ikr,ikz) cmpx_data_g(ikz,ikr-local_nkr_offset) = G_2D(ikr,ikz) end do end do call fftw_mpi_execute_dft_c2r(planb, cmpx_data_f, real_data_f) call fftw_mpi_execute_dft_c2r(planb, cmpx_data_g, real_data_g) real_data_c = real_data_f/NZ_/NR_ * real_data_g/NZ_/NR_ call fftw_mpi_execute_dft_r2c(planf, real_data_c, cmpx_data_c) ! Retrieve convolution in input format do ikr = ikrs, ikre do ikz = ikzs, ikze C_2D(ikr,ikz) = cmpx_data_c(ikz,ikr-local_nkr_offset)*AA_r(ikr)*AA_z(ikz) end do end do END SUBROUTINE convolve_2D_F2F SUBROUTINE finalize_plans IMPLICIT NONE IF (my_id .EQ. 0) write(*,*) '..plan Destruction.' call fftw_destroy_plan(planb) call fftw_destroy_plan(planf) call fftw_mpi_cleanup() call fftw_free(cdatar_f) call fftw_free(cdatar_g) call fftw_free(cdatar_c) call fftw_free(cdatac_f) call fftw_free(cdatac_g) call fftw_free(cdatac_c) END SUBROUTINE finalize_plans END MODULE fourier