MPI FFTW Fortran R2C & C2R Сбор данных в корне - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь вычислить БПФ реальных случайных данных, а затем инвертировать выходные данные, чтобы получить реальные данные, используя подпрограмму FFTW R2C & C2R в MPI с использованием Fortran. Я проверил это, он дает ПРАВИЛЬНЫЕ выходные данные, то есть он возвращает тот же массив. Однако вывод распределяется в разных узлах. Мне нужно собрать информацию в одном узле, чтобы сделать дальнейший расчет. Когда я пытаюсь, это показывает проблемы.

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
...