我正在尝试计算实际随机数据的FFT,然后使用Fortran在MPI中使用R2C和C2R FFTW例程将输出取反以取回真实数据。 我测试过,它可以提供正确的输出数据,即它可以返回相同的数组。 但是,输出分布在不同的节点中。我需要在一个节点中累积信息以进行进一步的计算。当我尝试时,它显示出了麻烦。
program test
use, intrinsic :: iso_c_binding
implicit none
include 'mpif.h'
integer (C_INTPTR_T), parameter :: nx = 2
integer (C_INTPTR_T), parameter :: ny = 2
integer (C_INTPTR_T), parameter :: nz = 4
integer (C_INTPTR_T), parameter :: nh = ( nx / 2 ) + 1
include "fftw3-mpi.f03"
integer(C_INTPTR_T) :: i, j, k
real(C_DOUBLE), dimension(nx,ny,nz) :: in,out1
complex(C_DOUBLE_COMPLEX), dimension(nh,ny,nz) :: out
integer :: ierr, myid, nproc, seed, root, dim_array
type(C_PTR) :: plan, plan1, cdatar, cdatac
integer(C_INTPTR_T) :: alloc_local, local_nz, local_k_offset
real(C_DOUBLE), pointer :: idata(:,:,:),idata2(:,:,:)
complex(C_DOUBLE_complex), pointer :: odata(:,:,:)
integer status(MPI_STATUS_SIZE)
seed = 123456789
call mpi_init(ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, nproc, ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr)
root = 0
do i = 1, nx
do j = 1, ny
do k = 1, nz
in(i,j,k) = ran(seed)
seed=in(i,j,k)*seed
enddo
end do
end do
call fftw_mpi_init()
! get local data size and allocate (note dimension reversal)
alloc_local = fftw_mpi_local_size_3d(nz, ny, nh, MPI_COMM_WORLD, &
local_nz, local_k_offset)
cdatar = fftw_alloc_real(2 * alloc_local)
cdatac = fftw_alloc_complex(alloc_local)
call c_f_pointer(cdatar, idata, [2*nh,ny,local_nz])
call c_f_pointer(cdatar, idata2, [2*nh,ny,local_nz])
call c_f_pointer(cdatac, odata, [nh,ny,local_nz])
dim_array = nx*ny*local_nz
! create MPI plan for out-of-place DFT (note dimension reversal)
plan = fftw_mpi_plan_dft_r2c_3d(nz, ny, nx, idata, odata, &
MPI_COMM_WORLD, FFTW_MEASURE)
plan1 = fftw_mpi_plan_dft_c2r_3d(nz, ny, nx, odata, idata2,&
MPI_COMM_WORLD, FFTW_MEASURE)
! initialize data to some function my_function(i,j,k)
do i = 1, nx
do j = 1, ny
do k = 1, local_nz
idata(i, j, k) = in(i, j, k + local_k_offset)
!write ( *, * ) i,j,k+local_k_offset,idata(i,j,k),local_k_offset,myid
end do
end do
end do
! compute transform (as many times as desired)
call fftw_mpi_execute_dft_r2c(plan, idata, odata)
call fftw_mpi_execute_dft_c2r(plan1, odata, idata2)
write(*,*) "Done", myid
if (myid == root) then
do i = 1,nz/local_nz,1
Call MPI_Recv(out1, nx*ny*nz, MPI_REAL, i, local_k_offset, MPI_COMM_WORLD,
status, ierr)
end do
else
do i = 1,nz/local_nz,1
Call MPI_Send( idata2, nx*ny*local_nz, MPI_REAL, root, local_k_offset,
MPI_COMM_WORLD, ierr )
end do
endif
call MPI_Barrier(MPI_COMM_WORLD, IERROR)
! deallocate and destroy plans
call fftw_destroy_plan(plan)
call fftw_mpi_cleanup()
call fftw_free(cdatar)
call fftw_free(cdatac)
if (myid == root) then
do i = 1, nx
do j = 1, ny
do k = 1, nz
write (*,*) i, j, k, in(i,j,k), out1(i,j,k)/(nz*ny*nx),myid
end do
end do
end do
endif
call mpi_finalize(ierr)
end program test