Good morning everyone,
I have started using cuda fortran for two weeks now, and I must recognize I am stuck with a strange problem.
I want to compute the derivative of a 2D field using spectral derivatives according to the following program :
program example
use cudafor
use precision_m
use cufft_m
implicit none
integer, parameter :: N = 8
integer, parameter :: Nh = N/2 + 1
double precision, parameter :: Ns = real(N*N)
double precision, parameter :: pi = 3.141592653589793238d0
double precision, dimension(N,N) :: signal, dx_signal, dy_signal
double precision, dimension(N) :: kx
double precision, dimension(Nh) :: ky
double precision, dimension(N,N), device :: d_signal, d_dx_signal, d_dy_signal
double complex, dimension(N,Nh), device :: d_fft, d_dx_fft, d_dy_fft
double precision, dimension(N), device :: d_kx
double precision, dimension(Nh), device :: d_ky
integer :: i, j, plan
double complex :: temp
!--- Initialisation
do i = 1, N
do j = 1, N
signal(i,j) = cos( 2.*pi * ( 0.*(i-1) + 1.*(j-1) ) / N)
end do
end do
kx(1:N/2) = (/(dfloat(i-1) * 2. * pi, i=1,N/2,1)/)
kx(N/2+1:N) = (/(dfloat(i-1-N) * 2. * pi, i=N/2+1,N,1)/)
ky(1:Nh) = (/(dfloat(i-1) * 2. * pi, i=1,Nh,1)/)
! Move to device
d_signal = signal
d_kx = kx
d_ky = ky
!--- Computations
! We compute the Fourier transform
call cufftPlan2D(plan, N, N, CUFFT_D2Z)
call cufftExecD2Z(plan, d_signal, d_fft)
call cufftDestroy(plan)
! We compute the x derivative
!$ cuf kernel do(2) <<<*,*>>>
do i = 1, N
do j = 1, Nh
temp = cmplx(0., 1.) * d_kx(i)
temp = temp * d_fft(i,j)
d_dx_fft(i,j) = temp / Ns
end do
end do
! We compute the y derivative
!$ cuf kernel do(2) <<<*,*>>>
do i = 1, N
do j = 1, Nh
temp = cmplx(0., 1.) * d_ky(j)
temp = temp * d_fft(i,j)
d_dy_fft(i,j) = temp / Ns
end do
end do
! We compute the Fourier inverse transform
call cufftPlan2D(plan, N, N, CUFFT_Z2D)
call cufftExecZ2D(plan, d_dx_fft, d_dx_signal)
call cufftExecZ2D(plan, d_dy_fft, d_dy_signal)
call cufftDestroy(plan)
! Move to host
dx_signal = d_dx_signal
dy_signal = d_dy_signal
!--- Print dx_signal and dy_signal
write(*,*) "dx_signal"
do i = 1, N
write(*,*) ( dx_signal(i,j), j=1,N )
end do
write(*,*) "dy_signal"
do i = 1, N
write(*,*) ( dy_signal(i,j), j=1,N )
end do
end program example
What is strange is that the derivative according to x should be zero, but this is not what we observe. On the contrary, we can almost find the derivative according to y.
I compile using nvfortran and the following command:
nvfortran -fast -Mpreprocess -Mcuda -c precision_m.f90 -o precision_m.o -lcufft
nvfortran -fast -Mpreprocess -Mcuda -c cufft_m.f90 -o cufft_m.o -lcufft
nvfortran -fast -Mpreprocess -Mcuda -c example.f90 -o example.o -lcufft
nvfortran -fast -Mpreprocess -Mcuda -O3 -o example example.o cufft_m.o precision_m.o -lcufft
And I execute using:
./example
Thank you very much for your help
B.